"use client";

import { NEXT_PUBLIC_API_URL } from "@/config/api";
import { clientAuthFetch } from "@/app/utils/clientAuthFetch";

export interface JobOrderListItem {
  id: number;
  code: string | null;
  planStart: string | null;
  itemCode: string | null;
  itemName: string | null;
  reqQty: number | null;
  stockInLineId: number | null;
  itemId: number | null;
  lotNo: string | null;
  bagPrintedQty?: number;
  labelPrintedQty?: number;
  laserPrintedQty?: number;
}

export interface LaserLastReceiveSuccess {
  jobOrderId?: number | null;
  jobOrderNo?: string | null;
  lotNo?: string | null;
  itemId?: number | null;
  stockInLineId?: number | null;
  printerAck?: string | null;
  sentAt?: string | null;
  source?: string | null;
}

export interface LaserBag2Settings {
  host: string;
  port: number;
  /** Comma-separated item codes; empty string = show all packaging job orders */
  itemCodes: string;
  /** Last job where the laser returned a receive ack (from DB settings). */
  lastReceiveSuccess?: LaserLastReceiveSuccess | null;
}

export interface LaserBag2SendRequest {
  itemId: number | null;
  stockInLineId: number | null;
  itemCode: string | null;
  itemName: string | null;
  printerIp?: string;
  printerPort?: number;
  jobOrderId?: number | null;
  jobOrderNo?: string | null;
  lotNo?: string | null;
  source?: string | null;
}

export interface LaserBag2SendResponse {
  success: boolean;
  message: string;
  payloadSent?: string | null;
  /** Raw TCP reply from the laser plugin (often `receive;;`). */
  printerAck?: string | null;
  /** True when the peer reply contained `receive` and not `invalid`. */
  receiveAcknowledged?: boolean;
}

/**
 * Uses server LASER_PRINT.itemCodes filter. Calls public GET /py/laser-job-orders (same as Python Bag2 /py/job-orders),
 * so it works without relying on authenticated /plastic routes.
 */
export async function fetchLaserJobOrders(planStart: string): Promise<JobOrderListItem[]> {
  const base = (NEXT_PUBLIC_API_URL ?? "").replace(/\/$/, "");
  if (!base) {
    throw new Error("NEXT_PUBLIC_API_URL is not set; cannot reach API.");
  }
  const url = `${base}/py/laser-job-orders?planStart=${encodeURIComponent(planStart)}`;
  let res: Response;
  try {
    res = await clientAuthFetch(url, { method: "GET" });
  } catch (e) {
    const msg = e instanceof Error ? e.message : String(e);
    throw new Error(
      `無法連線 API（${url}）：${msg}。請確認後端已啟動且 NEXT_PUBLIC_API_URL 指向正確（例如 http://localhost:8090/api）。`,
    );
  }
  if (!res.ok) {
    const body = await res.text().catch(() => "");
    throw new Error(
      `載入工單失敗（${res.status}）${body ? `：${body.slice(0, 200)}` : ""}`,
    );
  }
  return res.json() as Promise<JobOrderListItem[]>;
}

export async function fetchLaserBag2Settings(): Promise<LaserBag2Settings> {
  const base = (NEXT_PUBLIC_API_URL ?? "").replace(/\/$/, "");
  if (!base) {
    throw new Error("NEXT_PUBLIC_API_URL is not set.");
  }
  const url = `${base}/plastic/laser-bag2-settings`;
  let res: Response;
  try {
    res = await clientAuthFetch(url, { method: "GET" });
  } catch (e) {
    const msg = e instanceof Error ? e.message : String(e);
    throw new Error(`無法連線至 ${url}：${msg}`);
  }
  if (!res.ok) {
    const body = await res.text().catch(() => "");
    throw new Error(`載入設定失敗（${res.status}）${body ? body.slice(0, 200) : ""}`);
  }
  return res.json() as Promise<LaserBag2Settings>;
}

export async function sendLaserBag2Job(body: LaserBag2SendRequest): Promise<LaserBag2SendResponse> {
  const url = `${NEXT_PUBLIC_API_URL}/plastic/print-laser-bag2`;
  const res = await clientAuthFetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  const data = (await res.json()) as LaserBag2SendResponse;
  if (!res.ok) {
    return data;
  }
  return data;
}

export interface PrinterStatusRequest {
  printerType: "laser";
  printerIp?: string;
  printerPort?: number;
}

export interface PrinterStatusResponse {
  connected: boolean;
  message: string;
}

export async function checkPrinterStatus(request: PrinterStatusRequest): Promise<PrinterStatusResponse> {
  const base = (NEXT_PUBLIC_API_URL ?? "").replace(/\/$/, "");
  if (!base) {
    throw new Error("NEXT_PUBLIC_API_URL is not set.");
  }
  const url = `${base}/plastic/check-printer`;
  const res = await clientAuthFetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(request),
  });
  const data = (await res.json()) as PrinterStatusResponse;
  return data;
}

export interface LaserBag2JobSendResult {
  jobOrderId: number;
  itemCode: string | null;
  success: boolean;
  message: string;
  printerAck?: string | null;
  receiveAcknowledged?: boolean;
}

export interface LaserBag2AutoSendReport {
  planStart: string;
  jobOrdersFound: number;
  jobOrdersProcessed: number;
  results: LaserBag2JobSendResult[];
}

/**
 * Same workflow as /laserPrint row click: list job orders (LASER_PRINT.itemCodes) for planStart,
 * then TCP send using DB LASER_PRINT.host / port (server currently sends first matching job only).
 */
export async function runLaserBag2AutoSend(params?: {
  planStart?: string;
  limitPerRun?: number;
}): Promise<LaserBag2AutoSendReport> {
  const base = (NEXT_PUBLIC_API_URL ?? "").replace(/\/$/, "");
  if (!base) {
    throw new Error("NEXT_PUBLIC_API_URL is not set.");
  }
  const sp = new URLSearchParams();
  if (params?.planStart) sp.set("planStart", params.planStart);
  if (params?.limitPerRun != null) sp.set("limitPerRun", String(params.limitPerRun));
  const q = sp.toString();
  const url = `${base}/plastic/laser-bag2-auto-send${q ? `?${q}` : ""}`;
  const res = await clientAuthFetch(url, { method: "POST" });
  if (!res.ok) {
    const t = await res.text().catch(() => "");
    throw new Error(t || `HTTP ${res.status}`);
  }
  return res.json() as Promise<LaserBag2AutoSendReport>;
}

export async function patchSetting(name: string, value: string): Promise<void> {
  const url = `${NEXT_PUBLIC_API_URL}/settings/${encodeURIComponent(name)}`;
  const res = await clientAuthFetch(url, {
    method: "PATCH",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ value }),
  });
  if (!res.ok) {
    const t = await res.text().catch(() => "");
    throw new Error(t || `Failed to save setting: ${res.status}`);
  }
}
