/**
 * ERP Bridge HTTP client
 * Calls the FastAPI erp-bridge service running at 127.0.0.1:8080 (internal only).
 * All requests are authenticated with X-API-Key header.
 */

import { ENV } from "./_core/env";

const TIMEOUT_MS = 8_000;

/** Caller identity forwarded to the ERP bridge for permission scoping. */
export interface UserCtx {
  role: string;           // "admin" | "agent" | "user"
  erpContactCid?: string | null; // ERP ContactID for dealer-role scoping
}

/** Generic fetch wrapper with timeout and error handling */
async function erpFetch<T>(
  path: string,
  options: RequestInit = {},
  userCtx?: UserCtx
): Promise<T> {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);

  const url = `${ENV.erpApiUrl}${path}`;

  const roleHeader = userCtx?.role ?? "user";
  const cidHeader  = userCtx?.erpContactCid ?? "";

  try {
    const res = await fetch(url, {
      ...options,
      signal: controller.signal,
      headers: {
        "Content-Type": "application/json",
        "X-API-Key": ENV.erpApiKey,
        "X-User-Role": roleHeader,
        "X-Customer-CID": cidHeader,
        ...(options.headers ?? {}),
      },
    });

    if (!res.ok) {
      const text = await res.text().catch(() => "");
      throw new Error(`ERP bridge ${res.status} for ${path}: ${text}`);
    }

    return (await res.json()) as T;
  } catch (err: unknown) {
    if ((err as Error).name === "AbortError") {
      throw new Error(`ERP bridge timeout after ${TIMEOUT_MS}ms for ${path}`);
    }
    throw err;
  } finally {
    clearTimeout(timer);
  }
}

// ─── Request / response types ─────────────────────────────────────────────────

export interface CatalogItem {
  Model: string | null;
  Manufacturer: string | null;
  Description: string | null;
  Type: string | null;
  Department: string | null;
  Color: string | null;
  UOM: string | null;
  Status: string | null;
  StockQTY: number | null;
  EstimatedValue: number | null;
}

export interface ContactRecord {
  ContactID: string | null;
  Company: string | null;
  ContactName1: string | null;
  Phone1: string | null;
  Email1: string | null;
  Address1: string | null;
  City: string | null;
  State: string | null;
  Country: string | null;
  Sales1: string | null;
  AR_CreditHold: boolean | null;
  Active: boolean | null;
  Terms: string | null;
  PriceType: string | null;
}

export interface OrderListItem {
  SOID: string | null;
  OrderType: string | null;
  Status: string | null;
  SubStatus: string | null;
  CustomerName: string | null;
  CustomerCID: string | null;
  POID: string | null;
  Model: string | null;
  Quantity: number | null;
  UnitPrice: number | null;
  TotalPrice: number | null;
  InvoiceNo: string | null;
  InvoiceDate: string | null;
  TrackingNumber: string | null;
  ETD: string | null;
  ShipVia: string | null;
  Carrier: string | null;
  SODate: string | null;
  ScheduleDate: string | null;
}

export interface OrderItem {
  LineNo: number | null;
  ItemID: string | null;
  Model: string | null;
  Manufacturer: string | null;
  Description: string | null;
  Quantity: number | null;
  UnitPrice: number | null;
  TotalPrice: number | null;
  Status: string | null;
  StatusDesc: string | null;
  ETD: string | null;
  ItemNote: string | null;
  WarehouseID: number | null;
  InvoiceQuantity: number | null;
  TransactedQuantity: number | null;
}

export interface OrderNote {
  ID: number;
  GeneralNote: string | null;
  DeliveryCarrier: string | null;
  CODCharges: number | null;
  PickOrderNote: string | null;
  InternalNote: string | null;
  AccNotes: string | null;
  Pickslip: string | null;
  CreateUser: string | null;
  CreateTime: string | null;
}

export interface OrderDetail {
  SOID: string | null;
  POID: string | null;
  OrderType: string | null;
  Status: string | null;
  StatusDesc: string | null;
  CustomerName: string | null;
  CustomerCID: string | null;
  ReceiverName: string | null;
  ReceiverAddress1: string | null;
  ReceiverCity: string | null;
  ReceiverState: string | null;
  ReceiverCountry: string | null;
  ReceiverZipcode: string | null;
  ShipVia: string | null;
  Shipper: string | null;
  ScheduleDate: string | null;
  ArrivalDate: string | null;
  Notes: string | null;
  InternalNote: string | null;
  ModifyTime: string | null;
  Items: OrderItem[];
  Notes_: OrderNote[]; // mapped from "Notes" array in the response
}

export interface StockRecord {
  Model: string | null;
  Manufacturer: string | null;
  Description: string | null;
  Quantity: number | null;
  PalletID: string | null;
  WarehouseCID: string | null;
  SubInv: string | null;
  HoldByPalletID: string | null;
  HoldByRef: string | null;
  B_ETA: string | null;
  A_ETA: string | null;
  SalesOrderID: string | null;
}

export interface ProductImageRecord {
  model: string;
  apppicture_path: string;
  full_url: string;
}

export interface ProductImagesResult {
  base_url: string;
  images: ProductImageRecord[];
}

// ─── API calls ────────────────────────────────────────────────────────────────

export interface CatalogParams {
  model?: string;
  manufacturer?: string;
  description?: string;
  category?: string;
  status?: string;
  limit?: number;
}

export async function fetchCatalog(params: CatalogParams, userCtx?: UserCtx): Promise<CatalogItem[]> {
  return erpFetch<CatalogItem[]>("/catalog", {
    method: "POST",
    body: JSON.stringify({ limit: 20, ...params }),
  }, userCtx);
}

export interface ContactParams {
  contact_id?: string;
  company?: string;
  name?: string;
  limit?: number;
}

export async function fetchContacts(params: ContactParams, userCtx?: UserCtx): Promise<ContactRecord[]> {
  return erpFetch<ContactRecord[]>("/contacts", {
    method: "POST",
    body: JSON.stringify({ limit: 10, ...params }),
  }, userCtx);
}

export interface OrderListParams {
  so_id?: string;
  customer_name?: string;
  customer_cid?: string;
  po_id?: string;
  status?: string;
  limit?: number;
}

export async function fetchOrdersList(params: OrderListParams, userCtx?: UserCtx): Promise<OrderListItem[]> {
  return erpFetch<OrderListItem[]>("/orders", {
    method: "POST",
    body: JSON.stringify({ limit: 20, ...params }),
  }, userCtx);
}

export async function fetchOrderDetail(soId: string, userCtx?: UserCtx): Promise<OrderDetail | null> {
  try {
    return await erpFetch<OrderDetail>(`/orders/${encodeURIComponent(soId)}`, {}, userCtx);
  } catch (err: unknown) {
    if ((err as Error).message?.includes("404")) return null;
    throw err;
  }
}

export interface StockParams {
  model?: string;
  warehouse_cid?: string;
  limit?: number;
}

export async function fetchStock(params: StockParams, userCtx?: UserCtx): Promise<StockRecord[]> {
  return erpFetch<StockRecord[]>("/stock", {
    method: "POST",
    body: JSON.stringify({ limit: 50, ...params }),
  }, userCtx);
}

export interface ProductImagesParams {
  model: string;
  limit?: number;
}

export async function fetchProductImages(params: ProductImagesParams, userCtx?: UserCtx): Promise<ProductImagesResult> {
  return erpFetch<ProductImagesResult>("/catalog/images", {
    method: "POST",
    body: JSON.stringify({ limit: 10, ...params }),
  }, userCtx);
}
