"use client";

import { useSearchParams } from "next/navigation";
import { Printer, X } from "lucide-react";
import { useEffect, useMemo, useState } from "react";

import { useLocale } from "@/components/providers/locale-provider";
import { SearchableSelectField } from "@/components/shared/searchable-select-field";
import { formatCurrencyAmount, formatQuantity } from "@/lib/formatters";
import { splitGradeName } from "@/lib/grade-display";
import type { ApiErrorResponse, DetailResponse } from "@/types/api";
import type {
  AgentRecord,
  CourierRecord,
  EmployeeRecord,
  GradeRecord,
  ProfitShareSchemeRecord,
  UnitRecord,
  WarehouseLocationRecord,
  WarehouseRecord
} from "@/types/master-data";
import type { PurchaseDetail, PurchaseListItem } from "@/types/purchase";

type PurchaseLineForm = {
  grade_id: string;
  qty_ordered: string;
  unit_id: string;
  mal_unit_price: string;
  notes: string;
};

type PurchaseCostLineForm = {
  cost_name: string;
  amount: string;
  notes: string;
  proof_file: File | null;
  proof_file_url: string | null;
};

type PurchaseForm = {
  unit_id: string;
  purchase_date: string;
  received_at: string;
  agent_id: string;
  profit_share_scheme_id: string;
  courier_id: string;
  received_by_employee_id: string;
  moisture_buy_percent: string;
  moisture_received_percent: string;
  market_reference_price: string;
  above_average_ratio_percent: string;
  mk_share_percent: string;
  non_mk_share_percent: string;
  warehouse_id: string;
  warehouse_location_id: string;
  modal_beli: string;
  modal_barang: string;
  modal_masuk: string;
  berat_beli: string;
  berat_masuk: string;
  notes: string;
  lines: PurchaseLineForm[];
  cost_lines: PurchaseCostLineForm[];
};

const newCostLine = (): PurchaseCostLineForm => ({
  cost_name: "",
  amount: "",
  notes: "",
  proof_file: null,
  proof_file_url: null
});

const newLine = (unitId: string = ""): PurchaseLineForm => ({
  grade_id: "",
  qty_ordered: "",
  unit_id: unitId,
  mal_unit_price: "",
  notes: ""
});

async function parseJsonResponse<T>(response: Response, context: string): Promise<T> {
  const responseText = await response.text();
  if (responseText.trim().length === 0) {
    throw new Error(`${context}: respons kosong`);
  }

  try {
    return JSON.parse(responseText) as T;
  } catch {
    const preview = responseText.slice(0, 160);
    throw new Error(`${context}: server mengembalikan data non-JSON (${preview})`);
  }
}

const emptyForm = (): PurchaseForm => ({
  unit_id: "",
  purchase_date: new Date().toISOString().slice(0, 10),
  received_at: new Date().toISOString().slice(0, 16),
  agent_id: "",
  profit_share_scheme_id: "",
  courier_id: "",
  received_by_employee_id: "",
  moisture_buy_percent: "",
  moisture_received_percent: "",
  market_reference_price: "",
  above_average_ratio_percent: "",
  mk_share_percent: "",
  non_mk_share_percent: "",
  warehouse_id: "",
  warehouse_location_id: "",
  modal_beli: "",
  modal_barang: "",
  modal_masuk: "",
  berat_beli: "",
  berat_masuk: "",
  notes: "",
  lines: [newLine()],
  cost_lines: []
});

type PurchasesClientProps = {
  currencyCode: string;
};

const normalizeText = (value: string) => value.toLowerCase().trim().replace(/[^a-z0-9]+/g, " ");

const numberFromForm = (value: string) => {
  const trimmed = value.trim();
  if (!trimmed) return null;
  const parsed = Number(trimmed);
  return Number.isFinite(parsed) ? parsed : null;
};

function extractFirstValidationMessage(errors: unknown): string | null {
  if (typeof errors === "string") return errors;
  if (Array.isArray(errors)) {
    for (const item of errors) {
      const message = extractFirstValidationMessage(item);
      if (message) return message;
    }
    return null;
  }
  if (errors && typeof errors === "object") {
    for (const key of Object.keys(errors as Record<string, unknown>)) {
      const message = extractFirstValidationMessage((errors as Record<string, unknown>)[key]);
      if (message) return message;
    }
  }
  return null;
}

function isMangkokByLabel(code: string, name: string) {
  const normalizedCode = normalizeText(code);
  const normalizedName = normalizeText(name);
  return normalizedCode.startsWith("mgk") || normalizedName.includes("mangkok");
}

const toLineAmount = (value: string) => Number(value) || 0;

function toDateTimeLocal(value: string | null) {
  if (!value) return "";
  return value.length > 16 ? value.slice(0, 16) : value;
}

function toFormNumber(value: number | null, digits = 2) {
  if (value === null || !Number.isFinite(value)) return "";
  return digits === 0 ? String(Math.round(value)) : value.toFixed(digits);
}

function convertQtyToKg(qty: number, unitCode: string | null | undefined) {
  const normalizedUnit = normalizeText(unitCode ?? "");
  if (normalizedUnit === "g" || normalizedUnit === "gr" || normalizedUnit === "gram" || normalizedUnit === "grams") {
    return qty / 1000;
  }
  return qty;
}

export function PurchasesClient({ currencyCode }: PurchasesClientProps) {
  const { dict, locale } = useLocale();
  const searchParams = useSearchParams();
  const requestedId = searchParams.get("id");
  const [items, setItems] = useState<PurchaseListItem[]>([]);
  const [grades, setGrades] = useState<GradeRecord[]>([]);
  const [units, setUnits] = useState<UnitRecord[]>([]);
  const [agents, setAgents] = useState<AgentRecord[]>([]);
  const [profitShareSchemes, setProfitShareSchemes] = useState<ProfitShareSchemeRecord[]>([]);
  const [couriers, setCouriers] = useState<CourierRecord[]>([]);
  const [employees, setEmployees] = useState<EmployeeRecord[]>([]);
  const [warehouses, setWarehouses] = useState<WarehouseRecord[]>([]);
  const [locations, setLocations] = useState<WarehouseLocationRecord[]>([]);
  const [form, setForm] = useState<PurchaseForm>(emptyForm);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [selectedPurchase, setSelectedPurchase] = useState<PurchaseDetail | null>(null);
  const [detailLoading, setDetailLoading] = useState(false);
  const [loading, setLoading] = useState(true);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const selectedUnit = units.find((unit) => unit.id === form.unit_id) ?? null;

  async function loadLookupsAndPurchases() {
    setLoading(true);
    setError(null);
    try {
      const [
        purchasesRes,
        unitsRes,
        agentsRes,
        profitShareSchemesRes,
        couriersRes,
        employeesRes,
        warehousesRes,
        locationsRes,
        gradesRes
      ] = await Promise.all([
        fetch("/api/v1/purchases?purchase_type=REGULAR", { cache: "no-store" }),
        fetch("/api/v1/units", { cache: "no-store" }),
        fetch("/api/v1/agents", { cache: "no-store" }),
        fetch("/api/v1/profit-share-schemes", { cache: "no-store" }),
        fetch("/api/v1/couriers", { cache: "no-store" }),
        fetch("/api/v1/employees", { cache: "no-store" }),
        fetch("/api/v1/warehouses", { cache: "no-store" }),
        fetch("/api/v1/warehouse-locations", { cache: "no-store" }),
        fetch("/api/v1/grades", { cache: "no-store" })
      ]);

      const purchasesPayload = await parseJsonResponse<{ data: PurchaseListItem[] }>(purchasesRes, "Memuat daftar pembelian");
      const unitsPayload = await parseJsonResponse<{ data: UnitRecord[] }>(unitsRes, "Memuat satuan");
      const agentsPayload = await parseJsonResponse<{ data: AgentRecord[] }>(agentsRes, "Memuat daftar agen");
      const profitShareSchemesPayload = await parseJsonResponse<{ data: ProfitShareSchemeRecord[] }>(
        profitShareSchemesRes,
        "Memuat skema bagi hasil"
      );
      const couriersPayload = await parseJsonResponse<{ data: CourierRecord[] }>(couriersRes, "Memuat daftar kurir");
      const employeesPayload = await parseJsonResponse<{ data: EmployeeRecord[] }>(employeesRes, "Memuat daftar pegawai");
      const warehousesPayload = await parseJsonResponse<{ data: WarehouseRecord[] }>(warehousesRes, "Memuat gudang");
      const locationsPayload = await parseJsonResponse<{ data: WarehouseLocationRecord[] }>(
        locationsRes,
        "Memuat lokasi gudang"
      );
      const gradesPayload = await parseJsonResponse<{ data: GradeRecord[] }>(gradesRes, "Memuat grade");

      if (
        !purchasesRes.ok ||
        !unitsRes.ok ||
        !agentsRes.ok ||
        !profitShareSchemesRes.ok ||
        !couriersRes.ok ||
        !employeesRes.ok ||
        !warehousesRes.ok ||
        !locationsRes.ok ||
        !gradesRes.ok
      ) {
        throw new Error(dict.purchases.loadingError);
      }

      setItems(purchasesPayload.data);
      setUnits(unitsPayload.data);
      setAgents(agentsPayload.data);
      setProfitShareSchemes(profitShareSchemesPayload.data);
      setCouriers(couriersPayload.data);
      setEmployees(employeesPayload.data);
      setWarehouses(warehousesPayload.data);
      setLocations(locationsPayload.data);
      setGrades(gradesPayload.data);
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.purchases.loadingError);
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    void loadLookupsAndPurchases();
  }, []);

  useEffect(() => {
    if (!requestedId) return;
    void openDetail(requestedId);
  }, [requestedId]);

  function resetForm() {
    setEditingId(null);
    setForm(emptyForm());
    setError(null);
  }

  async function fetchPurchaseDetail(id: string) {
    const response = await fetch(`/api/v1/purchases/${id}`, { cache: "no-store" });
    const payload = await parseJsonResponse<DetailResponse<PurchaseDetail> | ApiErrorResponse>(
      response,
      "Memuat detail pembelian"
    );
    if (!response.ok) throw new Error("message" in payload ? payload.message : dict.purchases.detailError);
    if (!("data" in payload)) throw new Error(dict.purchases.detailError);
    return payload.data;
  }

  async function openDetail(id: string) {
    setDetailLoading(true);
    setError(null);
    try {
      const detail = await fetchPurchaseDetail(id);
      setSelectedPurchase(detail);
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.purchases.detailError);
    } finally {
      setDetailLoading(false);
    }
  }

  function syncProfitScheme(agentId: string) {
    if (!agentId) return "";
    const selectedAgent = agents.find((agent) => agent.id === agentId);
    return selectedAgent?.profit_share_scheme?.id ?? "";
  }

  function setAgentAndScheme(agentId: string) {
    const schemeId = syncProfitScheme(agentId);
    setForm((current) => ({
      ...current,
      agent_id: agentId,
      profit_share_scheme_id: schemeId || current.profit_share_scheme_id
    }));
  }

  async function startEdit(id: string) {
    setError(null);
    try {
      const detail = await fetchPurchaseDetail(id);

      setEditingId(detail.id);
      const defaultUnitId = detail.lines[0]?.unit.id ?? units[0]?.id ?? "";
      const defaultWarehouseId = detail.lines[0]?.warehouse?.id ?? "";
      const defaultWarehouseLocationId = detail.lines[0]?.warehouse_location?.id ?? "";
      const beratBeli = detail.analysis?.weight_buy ?? detail.lines.reduce((sum, line) => sum + line.qty_ordered, 0);
      const beratMasuk = detail.analysis?.weight_received ?? beratBeli;
      const derivedModalBarang = detail.lines.reduce(
        (sum, line) =>
          sum + convertQtyToKg(line.qty_ordered, line.unit.code) * (line.mal_unit_price ?? line.unit_price),
        0
      );
      const modalBarang = detail.analysis?.modal_barang ?? derivedModalBarang;
      const modalBeli = detail.analysis?.modal_beli ?? 0;
      setForm({
        unit_id: defaultUnitId,
        purchase_date: detail.purchase_date,
        received_at: toDateTimeLocal(detail.received_at),
        agent_id: detail.agent?.id ?? "",
        profit_share_scheme_id: detail.profit_share_scheme?.id ?? "",
        courier_id: detail.courier?.id ?? "",
        received_by_employee_id: detail.received_by_employee?.id ?? "",
        moisture_buy_percent: detail.moisture_buy_percent?.toString() ?? "",
        moisture_received_percent: detail.moisture_received_percent?.toString() ?? "",
        market_reference_price: detail.analysis?.market_reference_price?.toString() ?? "",
        above_average_ratio_percent: detail.above_average_ratio_percent?.toString() ?? "",
        mk_share_percent: detail.mk_share_percent?.toString() ?? "",
        non_mk_share_percent: detail.non_mk_share_percent?.toString() ?? "",
        warehouse_id: defaultWarehouseId,
        warehouse_location_id: defaultWarehouseLocationId,
        modal_beli: String(modalBeli),
        modal_barang: String(modalBarang),
        modal_masuk: detail.analysis?.modal_masuk?.toString() ?? "",
        berat_beli: String(beratBeli),
        berat_masuk: String(beratMasuk),
        notes: detail.notes ?? "",
        cost_lines: detail.analysis?.cost_lines?.map((costLine) => ({
          cost_name: costLine.cost_name,
          amount: String(costLine.amount),
          notes: costLine.notes ?? "",
          proof_file: null,
          proof_file_url: costLine.proof_file_url ?? ""
        })) ?? [],
        lines: detail.lines.map((line) => ({
          grade_id: line.grade?.id ?? "",
          qty_ordered: String(line.qty_ordered),
          unit_id: defaultUnitId,
          mal_unit_price: line.mal_unit_price?.toString() ?? "",
          notes: line.notes ?? ""
        }))
      });
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.purchases.detailError);
    }
  }

  async function printPurchaseReceipt(detail: PurchaseDetail) {
    setError(null);
    const printWindow = window.open("", "_blank", "width=1120,height=760");

    if (!printWindow) {
      window.alert(locale === "id" ? "Popup cetak diblokir browser. Izinkan pop-up untuk situs ini lalu coba lagi." : "Print popup was blocked by the browser. Allow pop-ups for this site and try again.");
      return;
    }

    try {
      printWindow.document.open();
      printWindow.document.write(`<!doctype html><html><head><title>${locale === "id" ? "Menyiapkan Penerimaan" : "Preparing Receipt"}</title></head><body style="font-family: Arial, sans-serif; padding: 24px;">${locale === "id" ? "Menyiapkan receipt pembelian..." : "Preparing purchase receipt..."}</body></html>`);
      printWindow.document.close();

      printWindow.document.open();
      printWindow.document.write(buildPurchaseReceiptPrintHtml(detail, locale, currencyCode));
      printWindow.document.close();
    } catch (err) {
      if (!printWindow.closed) {
        printWindow.close();
      }
      setError(err instanceof Error ? err.message : locale === "id" ? "Gagal menyiapkan receipt pembelian." : "Failed to prepare the purchase receipt.");
    }
  }

  async function savePurchase(intent: "draft" | "submit") {
    if (!form.unit_id) {
      setError(locale === "id" ? "Unit berat harus dipilih." : "Weight unit must be selected.");
      return;
    }
    if (!form.received_by_employee_id) {
      setError(locale === "id" ? "Penerima di kantor wajib dipilih." : "Receiving employee is required.");
      return;
    }
    if (!form.lines.length) {
      setError(locale === "id" ? "Minimal satu line item harus diisi." : "At least one item row is required.");
      return;
    }
    const invalidQtyLineIndex = form.lines.findIndex((line) => Number(line.qty_ordered) <= 0);
    if (invalidQtyLineIndex >= 0) {
      setError(locale === "id" ? `Line item ke-${invalidQtyLineIndex + 1}: Qty masuk harus lebih besar dari 0.` : `Item row ${invalidQtyLineIndex + 1}: Qty must be greater than 0.`);
      return;
    }

    setSubmitting(true);
    setError(null);
    try {
      const normalizedCostLines = form.cost_lines.filter(
        (costLine) =>
          costLine.cost_name.trim() !== "" ||
          costLine.amount.trim() !== "" ||
          costLine.notes.trim() !== "" ||
          costLine.proof_file !== null ||
          costLine.proof_file_url !== null
      );

      const hasCostProof = normalizedCostLines.some((costLine) => costLine.proof_file !== null);
      const parsedBeratBeli = numberFromForm(form.berat_beli);
      const parsedBeratMasuk = numberFromForm(form.berat_masuk);
      const beratBeliPayload = parsedBeratBeli ?? totalOrderedQty;
      const beratBeliKgPayload = convertQtyToKg(beratBeliPayload, selectedUnit?.code);
      const modalBeliPayload = beratBeliKgPayload > 0 ? totalModalBeliValue / beratBeliKgPayload : 0;
      const payload = {
        warehouse_id: form.warehouse_id || "",
        warehouse_location_id: form.warehouse_location_id || null,
        modal_beli: modalBeliPayload,
        modal_barang: modalBarangValue,
        modal_masuk: modalMasuk ?? 0,
        modal_jual: modalJualValue ?? 0,
        total_modal_beli: totalModalBeliValue,
        total_modal_mal: totalModalMalValue ?? 0,
        average_price: hargaRataRataValue ?? 0,
        berat_beli: beratBeliPayload,
        berat_masuk: parsedBeratMasuk ?? totalOrderedQty,
        purchase_date: form.purchase_date,
        received_at: form.received_at,
        agent_id: form.agent_id || "",
        profit_share_scheme_id: form.profit_share_scheme_id || "",
        courier_id: form.courier_id || "",
        received_by_employee_id: form.received_by_employee_id,
        moisture_buy_percent: numberFromForm(form.moisture_buy_percent),
        moisture_received_percent: kadarMasukValue,
        moisture_final_percent: kadarAkhirValue,
        market_reference_price: numberFromForm(form.market_reference_price),
        above_average_ratio_percent: numberFromForm(form.above_average_ratio_percent),
        mk_share_percent: computedMkSharePercent,
        non_mk_share_percent: computedNonMkSharePercent,
        notes: form.notes || "",
        lines: form.lines.map((line) => ({
          grade_id: line.grade_id || "",
          qty_ordered: Number(line.qty_ordered),
          qty_received: Number(line.qty_ordered),
          qty_accepted: Number(line.qty_ordered),
          qty_rejected: 0,
          purchase_moisture_percent: null,
          moisture_received_percent: null,
          unit_id: form.unit_id || line.unit_id,
          unit_price: Number(line.mal_unit_price),
          unit_cost: 0,
          mal_unit_price: numberFromForm(line.mal_unit_price),
          classification_status: "FINAL",
          warehouse_id: form.warehouse_id || "",
          warehouse_location_id: form.warehouse_location_id || null,
          notes: line.notes || ""
        })),
        cost_lines: normalizedCostLines.map((costLine) => ({
          cost_name: costLine.cost_name,
          amount: Number(costLine.amount),
          notes: costLine.notes || "",
          proof_file_url: costLine.proof_file_url || ""
        }))
      };
      const body = hasCostProof
        ? (() => {
            const formData = new FormData();
            formData.append("payload", JSON.stringify(payload));
            if (hasCostProof) {
              normalizedCostLines.forEach((costLine, index) => {
                if (costLine.proof_file) {
                  formData.append(`cost_proof_${index}`, costLine.proof_file);
                }
              });
            }
            return formData;
          })()
        : JSON.stringify(payload);
      const headers = hasCostProof ? undefined : { "Content-Type": "application/json" };

      const response = await fetch(
        editingId ? `/api/v1/purchases/${editingId}` : "/api/v1/purchases",
        {
          method: editingId ? "PUT" : "POST",
          headers: headers,
          body
        }
      );
      const responseText = await response.text();
      let result: DetailResponse<PurchaseDetail> | ApiErrorResponse;
      try {
        result = responseText ? (JSON.parse(responseText) as DetailResponse<PurchaseDetail> | ApiErrorResponse) : ({} as ApiErrorResponse);
      } catch {
        throw new Error(responseText || "Request tidak valid");
      }
      if (!response.ok) {
        if ("errors" in result && result.errors) {
          const firstError = extractFirstValidationMessage(result.errors);
          throw new Error(firstError ?? result.message ?? (locale === "id" ? "Validasi gagal" : "Validation failed"));
        }
        throw new Error("message" in result ? result.message : dict.common.requestFailed);
      }
      if (!("data" in result)) {
        throw new Error(dict.purchases.saveError);
      }

      const purchaseId = result.data.id;
      if (intent === "submit") {
        const submitResponse = await fetch(`/api/v1/purchases/${purchaseId}/submit`, { method: "POST" });
        if (!submitResponse.ok) {
          const submitText = await submitResponse.text();
          const statusText = `${submitResponse.status} ${submitResponse.statusText || "Submit gagal"}`;
          let submitPayload: ApiErrorResponse = { message: "Submit gagal" };
          try {
            submitPayload = submitText ? (JSON.parse(submitText) as ApiErrorResponse) : { message: "Submit gagal" };
          } catch {}
          const detail =
            submitPayload.message ||
            `Submit gagal (${statusText})` +
              (submitText ? `: ${submitText.slice(0, 120)}` : "");
          throw new Error(detail);
        }
      }

      resetForm();
      await loadLookupsAndPurchases();
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.purchases.saveError);
    } finally {
      setSubmitting(false);
    }
  }

  async function handleCancelPurchase(id: string) {
    if (!window.confirm(dict.purchases.cancelConfirm)) return;
    try {
      const response = await fetch(`/api/v1/purchases/${id}/cancel`, { method: "POST" });
      if (!response.ok) {
        const payload = await parseJsonResponse<ApiErrorResponse>(response, "Batal pembelian");
        throw new Error(payload.message);
      }
      await loadLookupsAndPurchases();
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.purchases.cancelError);
    }
  }

  async function handleDeleteDraftPurchase(id: string) {
    if (!window.confirm(dict.purchases.deleteDraftOrCancelledConfirm)) return;
    try {
      const response = await fetch(`/api/v1/purchases/${id}`, { method: "DELETE" });
      if (!response.ok) {
        const payload = await parseJsonResponse<ApiErrorResponse>(response, "Hapus pembelian");
        throw new Error(payload.message);
      }
      await loadLookupsAndPurchases();
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.purchases.deleteError);
    }
  }

  function updateLine(index: number, patch: Partial<PurchaseLineForm>) {
    setForm((current) => ({
      ...current,
      lines: current.lines.map((line, i) => {
        if (i !== index) return line;
        return { ...line, ...patch };
      })
    }));
  }

  function addLine() {
    setForm((current) => ({ ...current, lines: [...current.lines, newLine(current.unit_id)] }));
  }

  function removeLine(index: number) {
    setForm((current) => ({
      ...current,
      lines: current.lines.length === 1 ? current.lines : current.lines.filter((_, i) => i !== index)
    }));
  }

  function updateCostLine(index: number, patch: Partial<PurchaseCostLineForm>) {
    setForm((current) => ({
      ...current,
      cost_lines: current.cost_lines.map((line, i) => {
        if (i !== index) return line;
        return { ...line, ...patch };
      })
    }));
  }

  function addCostLine() {
    setForm((current) => ({ ...current, cost_lines: [...current.cost_lines, newCostLine()] }));
  }

  function removeCostLine(index: number) {
    setForm((current) => ({
      ...current,
      cost_lines: current.cost_lines.length === 0 ? current.cost_lines : current.cost_lines.filter((_, i) => i !== index)
    }));
  }

  function onHeaderUnitChange(value: string) {
    setForm((current) => ({
      ...current,
      unit_id: value,
      lines: current.lines.map((line) => ({ ...line, unit_id: value }))
    }));
  }

  function setCostLineProofFile(index: number, file: File | null) {
    setForm((current) => ({
      ...current,
      cost_lines: current.cost_lines.map((line, i) => {
        if (i !== index) return line;
        return { ...line, proof_file: file, proof_file_url: file ? null : line.proof_file_url };
      })
    }));
  }

  const normalizedCostLines = useMemo(
    () =>
      form.cost_lines.filter(
        (costLine) =>
          costLine.cost_name.trim() !== "" ||
          costLine.amount.trim() !== "" ||
          costLine.notes.trim() !== "" ||
          costLine.proof_file !== null ||
          costLine.proof_file_url !== null
      ),
    [form.cost_lines]
  );

  const gradeCodeIsMangkok = useMemo(() => {
    const map = new Map<string, boolean>();
    grades.forEach((grade) => map.set(grade.code.toLowerCase(), grade.is_mangkok));
    return map;
  }, [grades]);

  const gradeNameIsMangkok = useMemo(() => {
    const map = new Map<string, boolean>();
    grades.forEach((grade) => map.set(normalizeText(grade.name), grade.is_mangkok));
    return map;
  }, [grades]);

  const mangkokItemGradeIds = useMemo(() => {
    const set = new Set<string>();
    grades.forEach((grade) => {
      const { itemGradeName } = splitGradeName(grade.name);
      const byCode = gradeCodeIsMangkok.get(grade.code.toLowerCase());
      const byName = gradeNameIsMangkok.get(normalizeText(grade.name));

      if (typeof byCode === "boolean") {
        if (byCode) set.add(grade.id);
        return;
      }
      if (typeof byName === "boolean") {
        if (byName) set.add(grade.id);
        return;
      }
      if (isMangkokByLabel(grade.code, itemGradeName)) {
        set.add(grade.id);
      }
    });
    return set;
  }, [gradeCodeIsMangkok, gradeNameIsMangkok, grades]);

  const lineShares = useMemo(() => {
    let mkQty = 0;
    let nonMkQty = 0;
    let totalQty = 0;

    form.lines.forEach((line) => {
      const qty = toLineAmount(line.qty_ordered);
      totalQty += qty;
      if (mangkokItemGradeIds.has(line.grade_id)) {
        mkQty += qty;
      } else {
        nonMkQty += qty;
      }
    });

    return { mkQty, nonMkQty, totalQty };
  }, [form.lines, mangkokItemGradeIds]);

  const computedMkSharePercent = lineShares.totalQty > 0 ? (lineShares.mkQty / lineShares.totalQty) * 100 : null;
  const computedNonMkSharePercent = lineShares.totalQty > 0 ? (lineShares.nonMkQty / lineShares.totalQty) * 100 : null;

  const totalModalBarangFromLines = useMemo(
    () =>
      form.lines.reduce((sum, line) => {
        const qty = toLineAmount(line.qty_ordered);
        const malPrice = toLineAmount(line.mal_unit_price);
        return sum + convertQtyToKg(qty, selectedUnit?.code) * malPrice;
      }, 0),
    [form.lines, selectedUnit?.code]
  );

  const totalOrderedQty = useMemo(
    () => form.lines.reduce((sum, line) => sum + toLineAmount(line.qty_ordered), 0),
    [form.lines]
  );

  const lineItemStats = useMemo(
    () =>
      form.lines.map((line) => {
        const qty = toLineAmount(line.qty_ordered);
        const malPrice = toLineAmount(line.mal_unit_price);
        const totalMal = convertQtyToKg(qty, selectedUnit?.code) * malPrice;
        const sharePercent = totalOrderedQty > 0 ? (qty / totalOrderedQty) * 100 : null;
        return { totalMal, sharePercent };
      }),
    [form.lines, selectedUnit?.code, totalOrderedQty]
  );

  const totalCostLines = useMemo(
    () => normalizedCostLines.reduce((sum, costLine) => sum + toLineAmount(costLine.amount), 0),
    [normalizedCostLines]
  );

  const modalBarangInputValue = numberFromForm(form.modal_barang);

  const beratBeliRawValue = useMemo(() => {
    const parsed = numberFromForm(form.berat_beli);
    return parsed === null ? totalOrderedQty : parsed;
  }, [form.berat_beli, totalOrderedQty]);

  const beratMasukRawValue = useMemo(() => {
    const parsed = numberFromForm(form.berat_masuk);
    return parsed === null ? totalOrderedQty : parsed;
  }, [form.berat_masuk, totalOrderedQty]);

  const beratBeliKgValue = useMemo(
    () => convertQtyToKg(beratBeliRawValue, selectedUnit?.code),
    [beratBeliRawValue, selectedUnit?.code]
  );

  const beratMasukKgValue = useMemo(
    () => convertQtyToKg(beratMasukRawValue, selectedUnit?.code),
    [beratMasukRawValue, selectedUnit?.code]
  );

  const beratAkhirKgValue = useMemo(
    () => convertQtyToKg(totalOrderedQty, selectedUnit?.code),
    [selectedUnit?.code, totalOrderedQty]
  );

  const beratNaikPercent = useMemo(() => {
    if (beratBeliRawValue <= 0) return null;
    return ((beratMasukRawValue - beratBeliRawValue) / beratBeliRawValue) * 100;
  }, [beratBeliRawValue, beratMasukRawValue]);

  const susutTambahValue = useMemo(
    () => beratMasukRawValue - beratBeliRawValue,
    [beratBeliRawValue, beratMasukRawValue]
  );

  const kadarMasukValue = useMemo(() => {
    return beratNaikPercent;
  }, [beratNaikPercent]);

  const kadarAkhirValue = useMemo(() => {
    if (beratAkhirKgValue <= 0) return null;
    return ((beratAkhirKgValue - beratMasukKgValue) / beratAkhirKgValue) * 100;
  }, [beratAkhirKgValue, beratMasukKgValue]);

  const modalBarangValue = useMemo(
    () => modalBarangInputValue ?? totalModalBarangFromLines,
    [modalBarangInputValue, totalModalBarangFromLines]
  );

  const totalModalBeliValue = useMemo(
    () => modalBarangValue + totalCostLines,
    [modalBarangValue, totalCostLines]
  );

  const modalMasuk = useMemo(
    () => (beratMasukKgValue > 0 ? totalModalBeliValue / beratMasukKgValue : null),
    [beratMasukKgValue, totalModalBeliValue]
  );

  const modalBeliValue = useMemo(
    () => (beratBeliKgValue > 0 ? totalModalBeliValue / beratBeliKgValue : 0),
    [beratBeliKgValue, totalModalBeliValue]
  );

  const totalModalMalValue = useMemo(
    () => totalModalBarangFromLines,
    [totalModalBarangFromLines]
  );

  const modalJualValue = useMemo(
    () => (beratAkhirKgValue > 0 ? totalModalMalValue / beratAkhirKgValue : 0),
    [beratAkhirKgValue, totalModalMalValue]
  );

  const hargaRataRataValue = useMemo(
    () => (beratAkhirKgValue > 0 ? totalModalBeliValue / beratAkhirKgValue : null),
    [beratAkhirKgValue, totalModalBeliValue]
  );

  const barangAtasRata2Value = useMemo(() => {
    if (hargaRataRataValue === null || totalOrderedQty <= 0) return null;
    const qtyAboveAverage = form.lines.reduce((sum, line) => {
      const qty = toLineAmount(line.qty_ordered);
      const malPrice = toLineAmount(line.mal_unit_price);
      if (qty <= 0 || malPrice <= hargaRataRataValue) return sum;
      return sum + qty;
    }, 0);
    return (qtyAboveAverage / totalOrderedQty) * 100;
  }, [form.lines, hargaRataRataValue, totalOrderedQty]);

  useEffect(() => {
    setForm((current) => {
      const mkValue = toFormNumber(computedMkSharePercent, 2);
      const nonMkValue = toFormNumber(computedNonMkSharePercent, 2);
      const moistureReceivedValue = toFormNumber(kadarMasukValue, 2);
      const aboveAverageValue = toFormNumber(barangAtasRata2Value, 2);
      if (
        current.mk_share_percent === mkValue &&
        current.non_mk_share_percent === nonMkValue &&
        current.moisture_received_percent === moistureReceivedValue &&
        current.above_average_ratio_percent === aboveAverageValue
      ) {
        return current;
      }
      return {
        ...current,
        mk_share_percent: mkValue,
        non_mk_share_percent: nonMkValue,
        moisture_received_percent: moistureReceivedValue,
        above_average_ratio_percent: aboveAverageValue
      };
    });
  }, [barangAtasRata2Value, computedMkSharePercent, computedNonMkSharePercent, kadarMasukValue]);

  const locationOptions = useMemo(
    () => locations.filter((location) => location.warehouse_id === form.warehouse_id),
    [form.warehouse_id, locations]
  );

  const masterReady =
    grades.length > 0 &&
    units.length > 0 &&
    employees.length > 0 &&
    warehouses.length > 0;
  const missingMasterLabels = [
    grades.length === 0 ? "grade" : null,
    units.length === 0 ? "unit" : null,
    employees.length === 0 ? "pegawai penerima" : null,
    warehouses.length === 0 ? "gudang" : null
  ].filter((value): value is string => Boolean(value));

  const agentMap = useMemo(() => {
    const map = new Map<string, AgentRecord>();
    agents.forEach((agent) => map.set(agent.id, agent));
    return map;
  }, [agents]);

  const isLoading = loading;

  return (
    <section className="grid gap-6 xl:grid-cols-[1fr_1fr]">
      <div className="ops-card p-6">
        <div className="flex items-start justify-between gap-4">
          <div>
            <p className="ops-overline">{dict.purchases.overline}</p>
            <h2 className="mt-2 text-[28px] font-semibold tracking-tight text-ink">
              {editingId ? dict.purchases.editTitle : dict.purchases.createTitle}
            </h2>
            <p className="mt-3 text-[13px] leading-6 text-slate-500">{dict.purchases.helper}</p>
          </div>
          {editingId ? <button type="button" onClick={resetForm} className="ops-btn-secondary">{dict.common.cancelEdit}</button> : null}
        </div>

        {!isLoading && !masterReady ? (
          <div className="mt-6 rounded border border-ember/30 bg-ember/10 px-4 py-3 text-sm text-ember">
            {missingMasterLabels.length > 0
              ? `Lengkapi master data ${missingMasterLabels.join(", ")} terlebih dahulu sebelum membuat purchase.`
              : dict.purchases.masterWarning}
          </div>
        ) : null}

        <form className="mt-6 space-y-5" onSubmit={(event) => { event.preventDefault(); void savePurchase("draft"); }}>
          <div className="grid gap-4 md:grid-cols-3">
            <Field label={dict.purchases.purchaseDate} type="date" value={form.purchase_date} onChange={(value) => setForm((c) => ({ ...c, purchase_date: value }))} />
            <Field
              label={locale === "id" ? "Tanggal diterima" : "Received date"}
              type="datetime-local"
              value={form.received_at}
              onChange={(value) => setForm((c) => ({ ...c, received_at: value }))}
            />
            <SelectField
              label={locale === "id" ? "Unit berat" : "Weight unit"}
              value={form.unit_id}
              onChange={onHeaderUnitChange}
              options={units.map((unit) => ({ value: unit.id, label: `${unit.code} - ${unit.name}` }))}
              placeholder={`Pilih ${dict.common.unit.toLowerCase()}`}
            />
          </div>

          <div className="grid gap-4 md:grid-cols-2">
            <SelectField
              label={locale === "id" ? "Agen / sales" : "Agent / sales"}
              value={form.agent_id}
              onChange={setAgentAndScheme}
              options={agents.map((agent) => ({ value: agent.id, label: agent.name }))}
              placeholder={locale === "id" ? "Pembelian bebas (tanpa agen)" : "Direct purchase (without agent)"}
            />
            <SelectField
              label={locale === "id" ? "Skema bagi hasil" : "Profit share scheme"}
              value={form.profit_share_scheme_id}
              onChange={(value) => setForm((c) => ({ ...c, profit_share_scheme_id: value }))}
              options={profitShareSchemes.map((scheme) => ({ value: scheme.id, label: scheme.name }))}
              placeholder={locale === "id" ? "Pilih skema" : "Choose scheme"}
            />
          </div>

          <div className="grid gap-4 md:grid-cols-2">
            <SelectField
              label={dict.purchases.courier || "Jasa Pengiriman"}
              value={form.courier_id}
              onChange={(value) => setForm((c) => ({ ...c, courier_id: value }))}
              options={couriers.map((courier) => ({ value: courier.id, label: courier.name }))}
              placeholder={locale === "id" ? "Pilih jasa pengiriman (opsional)" : "Choose delivery service (optional)"}
            />
            <SelectField
              label={locale === "id" ? "Penerima di kantor" : "Receiving employee"}
              value={form.received_by_employee_id}
              onChange={(value) => setForm((c) => ({ ...c, received_by_employee_id: value }))}
              options={employees.map((employee) => ({ value: employee.id, label: `${employee.name} · ${employee.position}` }))}
              placeholder={locale === "id" ? "Pilih penerima" : "Choose receiver"}
            />
          </div>

          <div className="grid gap-4 md:grid-cols-4">
            <Field
              label={locale === "id" ? "Modal barang" : "Item capital"}
              type="number"
              value={form.modal_barang}
              onChange={(value) => setForm((c) => ({ ...c, modal_barang: value }))}
            />
            <Field
              label="Modal beli"
              type="number"
              value={toFormNumber(modalBeliValue, 2)}
              onChange={() => {}}
              readOnly
            />
            <Field
              label="Modal masuk"
              type="number"
              value={toFormNumber(modalMasuk, 2)}
              onChange={() => {}}
              readOnly
            />
            <Field
              label="Berat beli"
              type="number"
              value={form.berat_beli}
              onChange={(value) => setForm((current) => ({ ...current, berat_beli: value }))}
            />
          </div>

          <div className="grid gap-4 md:grid-cols-4">
            <Field
              label="Berat masuk"
              type="number"
              value={form.berat_masuk}
              onChange={(value) => setForm((current) => ({ ...current, berat_masuk: value }))}
            />
            <Field
              label="Berat naik (%)"
              type="number"
              value={toFormNumber(beratNaikPercent, 2)}
              onChange={() => {}}
              readOnly
            />
            <Field
              label="Berat akhir"
              type="number"
              value={toFormNumber(beratAkhirKgValue, 3)}
              onChange={() => {}}
              readOnly
            />
            <Field
              label="Susut / tambah"
              type="number"
              value={toFormNumber(susutTambahValue, 3)}
              onChange={() => {}}
              readOnly
            />
          </div>

          <div className="grid gap-4 md:grid-cols-4">
            <Field
              label="Kadar masuk (%)"
              type="number"
              value={toFormNumber(kadarMasukValue, 2)}
              onChange={() => {}}
              readOnly
            />
            <Field
              label="Kadar beli (%)"
              type="number"
              value={form.moisture_buy_percent}
              onChange={(value) => setForm((c) => ({ ...c, moisture_buy_percent: value }))}
            />
            <Field
              label="Kadar akhir (%)"
              type="number"
              value={toFormNumber(kadarAkhirValue, 2)}
              onChange={() => {}}
              readOnly
            />
            <Field
              label="Harga rata2"
              type="number"
              value={toFormNumber(hargaRataRataValue, 2)}
              onChange={() => {}}
              readOnly
            />
          </div>

          <div className="grid gap-4 md:grid-cols-4">
            <Field
              label="Brg atas rata2 (%)"
              type="number"
              value={form.above_average_ratio_percent}
              onChange={() => {}}
              readOnly
            />
            <Field
              label="Harga MK A/R"
              type="number"
              value={form.market_reference_price}
              onChange={(value) => setForm((c) => ({ ...c, market_reference_price: value }))}
            />
            <Field
              label="Modal jual"
              type="number"
              value={toFormNumber(modalJualValue, 2)}
              onChange={() => {}}
              readOnly
            />
            <Field
              label={locale === "id" ? "Total modal beli" : "Total purchase capital"}
              type="number"
              value={toFormNumber(totalModalBeliValue, 2)}
              onChange={() => {}}
              readOnly
            />
          </div>

          <div className="grid gap-4 md:grid-cols-4">
            <Field
              label={locale === "id" ? "Total modal MAL" : "Total MAL capital"}
              type="number"
              value={toFormNumber(totalModalMalValue, 2)}
              onChange={() => {}}
              readOnly
            />
            <Field
              label="MK (%)"
              type="number"
              value={form.mk_share_percent}
              onChange={() => {}}
              readOnly
            />
            <Field
              label="Non-MK (%)"
              type="number"
              value={form.non_mk_share_percent}
              onChange={() => {}}
              readOnly
            />
            <div aria-hidden="true" className="hidden md:block" />
          </div>

          <div className="grid gap-4 md:grid-cols-2">
            <SelectField
              label={dict.common.warehouse}
              value={form.warehouse_id}
              onChange={(value) =>
                setForm((current) => ({
                  ...current,
                  warehouse_id: value,
                  warehouse_location_id: ""
                }))
              }
              options={warehouses.map((warehouse) => ({ value: warehouse.id, label: `${warehouse.code} - ${warehouse.name}` }))}
              placeholder={dict.receipts.chooseWarehouse}
            />
            <SelectField
              label={dict.common.location}
              value={form.warehouse_location_id}
              onChange={(value) => setForm((current) => ({ ...current, warehouse_location_id: value }))}
              options={locationOptions.map((location) => ({ value: location.id, label: `${location.code} - ${location.name}` }))}
              placeholder={dict.purchases.optional}
            />
          </div>

          <label className="block">
            <span className="ops-label">{dict.common.notes}</span>
            <textarea value={form.notes} onChange={(e) => setForm((c) => ({ ...c, notes: e.target.value }))} rows={3} className="ops-textarea" />
          </label>

          <div className="rounded-lg border border-line/70 bg-slate-50/70 p-4">
            <div className="flex items-center justify-between">
              <h3 className="text-lg font-semibold text-ink">{locale === "id" ? "Baris Biaya" : "Cost Rows"}</h3>
            </div>
            <div className="mt-4 space-y-4">
              {form.cost_lines.map((costLine, index) => (
                <div key={index} className="rounded border border-line/70 bg-white p-4">
                  <div className="mb-4 flex items-center justify-between gap-3">
                    <p className="text-sm font-semibold uppercase tracking-[0.08em] text-slate-500">
                      {locale === "id" ? `Baris Biaya ${index + 1}` : `Cost Row ${index + 1}`}
                    </p>
                  </div>
                  <div className="grid gap-4 md:grid-cols-3">
                    <Field label={locale === "id" ? "Nama Biaya" : "Cost Name"} value={costLine.cost_name} onChange={(value) => updateCostLine(index, { cost_name: value })} />
                    <Field
                      label={locale === "id" ? "Jumlah Biaya" : "Cost Amount"}
                      type="number"
                      value={costLine.amount}
                      onChange={(value) => updateCostLine(index, { amount: value })}
                    />
                  </div>
                  <label className="mt-4 block">
                    <span className="ops-label">Catatan</span>
                    <textarea
                      value={costLine.notes}
                      onChange={(e) => updateCostLine(index, { notes: e.target.value })}
                      rows={2}
                      className="ops-textarea"
                    />
                  </label>
                  <label className="mt-4 block">
                    <span className="ops-label">Bukti / resi (jpg, png, pdf)</span>
                    <input
                      type="file"
                      accept=".jpg,.jpeg,.png,.pdf"
                      onChange={(event) => {
                        const file = event.target.files?.[0] ?? null;
                        setCostLineProofFile(index, file);
                      }}
                      className="ops-input"
                    />
                  </label>
                  <div className="mt-2 text-sm text-slate-600">
                    {costLine.proof_file ? (
                      <p>{locale === "id" ? "Bukti baru" : "New proof"}: {costLine.proof_file.name}</p>
                    ) : costLine.proof_file_url ? (
                      <p>
                        {locale === "id" ? "Bukti sebelumnya" : "Previous proof"}: <a href={costLine.proof_file_url} target="_blank" rel="noreferrer" className="text-azure underline">{locale === "id" ? "Lihat file" : "View file"}</a>
                      </p>
                    ) : null}
                  </div>
                  <div className="mt-4 flex items-center justify-between">
                    <button type="button" onClick={() => removeCostLine(index)} className="ops-btn-danger">{locale === "id" ? "Hapus biaya" : "Remove cost"}</button>
                  </div>
                </div>
              ))}
            </div>
            <div className="mt-4 flex justify-end">
              <button type="button" onClick={addCostLine} className="ops-btn-secondary">{locale === "id" ? "Tambah biaya" : "Add cost"}</button>
            </div>
          </div>

          <div className="rounded-lg border border-line/70 bg-slate-50/70 p-4">
            <div className="flex items-center justify-between">
              <h3 className="text-lg font-semibold text-ink">{dict.purchases.lineItems}</h3>
            </div>
            <div className="mt-4 space-y-4">
              {form.lines.map((line, index) => (
                <div key={index} className="rounded border border-line/70 bg-white p-4">
                  <div className="mb-4 flex items-center justify-between gap-3">
                    <p className="text-sm font-semibold uppercase tracking-[0.08em] text-slate-500">
                      {locale === "id" ? `Baris Barang ${index + 1}` : `Item Row ${index + 1}`}
                    </p>
                  </div>
                  <div className="grid gap-4 md:grid-cols-2">
                    <SearchableSelectField
                      label={dict.common.itemGrade}
                      value={line.grade_id}
                      onChange={(value) => updateLine(index, { grade_id: value })}
                      options={grades.map((grade) => ({ value: grade.id, label: `${grade.code} - ${grade.name}` }))}
                      searchPlaceholder={locale === "id" ? "Cari grade..." : "Search grade..."}
                      placeholder={dict.purchases.optional}
                    />
                    <Field label={`${dict.common.qty}${selectedUnit ? ` (${selectedUnit.code})` : ""}`} value={line.qty_ordered} onChange={(value) => updateLine(index, { qty_ordered: value })} type="number" />
                  </div>
                  <div className="mt-4 grid gap-4 md:grid-cols-2">
                    <Field
                      label={locale === "id" ? "Harga MAL (/kg)" : "MAL Price (/kg)"}
                      value={line.mal_unit_price}
                      onChange={(value) => updateLine(index, { mal_unit_price: value })}
                      type="number"
                    />
                    <div className="rounded-xl border border-line/70 bg-slate-50 px-4 py-3">
                      <div className="grid gap-3 sm:grid-cols-2">
                        <div>
                          <p className="text-[11px] font-semibold uppercase tracking-[0.08em] text-slate-500">
                            {locale === "id" ? "Total MAL" : "Total MAL"}
                          </p>
                          <p className="mt-1 text-sm font-semibold text-ink">
                            {formatCurrencyAmount(lineItemStats[index]?.totalMal ?? 0, locale, currencyCode, 0)}
                          </p>
                        </div>
                        <div>
                          <p className="text-[11px] font-semibold uppercase tracking-[0.08em] text-slate-500">
                            %
                          </p>
                          <p className="mt-1 text-sm font-semibold text-ink">
                            {toFormNumber(lineItemStats[index]?.sharePercent ?? null, 2) || "0.00"}%
                          </p>
                        </div>
                      </div>
                    </div>
                  </div>
                  {agentMap.size > 0 && line.grade_id ? (
                    <p className="mt-2 text-xs text-slate-500">
                      {locale === "id" ? "Tip: harga MAL untuk grade yang dipilih dapat dicek di modul Grade/Standar Harga jika tersedia." : "Tip: the MAL price for the selected grade can be checked in the Grade/Price Standards module when available."}
                    </p>
                  ) : null}
                  <div className="mt-4 flex items-center justify-between">
                    <button type="button" onClick={() => removeLine(index)} className="ops-btn-danger">
                      {dict.purchases.removeLine}
                    </button>
                  </div>
                </div>
              ))}
            </div>
            <div className="mt-4 flex justify-end">
              <button type="button" onClick={addLine} className="ops-btn-secondary">{dict.purchases.addLine}</button>
            </div>
          </div>

          <div className="rounded border border-line/70 bg-slate-50 px-4 py-4">
            <div className="grid gap-2 md:grid-cols-3">
              <div>
                <p className="text-sm text-ink/60">{locale === "id" ? "Total qty" : "Total qty"}</p>
                <p className="text-xl font-semibold">{formatQuantity(totalOrderedQty, locale, selectedUnit?.code)}</p>
              </div>
              <div>
                <p className="text-sm text-ink/60">Berat masuk</p>
                <p className="text-xl font-semibold">{formatQuantity(Number(form.berat_masuk || String(totalOrderedQty)), locale, selectedUnit?.code)}</p>
              </div>
              <div className="text-right">
                <p className="text-sm text-ink/60">Total harga MAL</p>
                <p className="text-xl font-semibold">
                  {formatCurrencyAmount(totalModalBarangFromLines, locale, currencyCode, 0)}
                </p>
              </div>
            </div>
          </div>

          {form.agent_id && !form.profit_share_scheme_id ? (
            <div className="rounded border border-ember/30 bg-ember/10 px-4 py-3 text-sm text-ember">
              {locale === "id" ? "Jika memakai agen, skema bagi hasil wajib dipilih." : "If an agent is used, a profit share scheme is required."}
            </div>
          ) : null}

          <div className="flex items-center justify-between">
            <div className="flex items-center gap-3">
            <button type="submit" disabled={submitting || !masterReady || !form.unit_id} className="ops-btn-secondary">{dict.purchases.saveDraft}</button>
              <button type="button" disabled={submitting || !masterReady || !form.unit_id} onClick={() => void savePurchase("submit")} className="ops-btn-primary">
                {submitting ? dict.common.processing : dict.purchases.submit}
              </button>
            </div>
            {error ? <div className="rounded border border-ember/30 bg-ember/10 px-4 py-2 text-sm text-ember">{error}</div> : null}
          </div>
        </form>
      </div>

      <div className="ops-table-shell">
          <div className="ops-section-head">
          <div>
            <p className="ops-title">{dict.purchases.listTitle}</p>
            <p className="ops-copy">{dict.purchases.listCopy}</p>
          </div>
          <div className="ops-chip-muted">{items.length} {locale === "id" ? "pembelian" : "purchases"}</div>
        </div>
        {isLoading ? <div className="px-6 py-8 text-sm text-ink/60">{dict.common.loading}</div> : items.length === 0 ? <div className="px-6 py-8 text-sm text-ink/60">{dict.purchases.noData}</div> : (
          <div className="overflow-x-auto">
            <table className="ops-table">
              <thead>
                <tr>
                  <th>No</th>
                  <th>{dict.common.date}</th>
                  <th>{locale === "id" ? "Diterima" : "Received"}</th>
                  <th>{locale === "id" ? "Agen" : "Agent"}</th>
                  <th>{dict.purchases.line}</th>
                  <th>{dict.common.total}</th>
                  <th>{dict.common.status}</th>
                  <th>{dict.common.actions}</th>
                </tr>
              </thead>
              <tbody>
                {items.map((item) => (
                  <tr key={item.id}>
                    <td className="font-semibold text-ink">{item.purchase_no}</td>
                    <td className="text-slate-600">{item.purchase_date}</td>
                    <td className="text-slate-600">{item.received_at ? item.received_at.slice(0, 16).replace("T", " ") : "-"}</td>
                    <td className="text-slate-600">{item.agent?.name || "-"}</td>
                    <td className="text-slate-600">{item.line_count}</td>
                    <td className="text-slate-600">
                      {formatCurrencyAmount(item.grand_total, locale, currencyCode, 0)}
                    </td>
                    <td>
                      <span className={item.status === "SUBMITTED" ? "ops-chip-active" : item.status === "CANCELLED" ? "ops-chip-danger" : "ops-chip-muted"}>{item.status}</span>
                    </td>
                    <td>
                      <div className="flex gap-2">
                        <button type="button" onClick={() => void openDetail(item.id)} className="ops-btn-secondary">{dict.common.detail}</button>
                        {item.receipt_count === 0 && item.lot_count === 0 ? (
                          <button type="button" onClick={() => void startEdit(item.id)} className="ops-btn-secondary">{dict.common.edit}</button>
                        ) : null}
                        {(item.status === "DRAFT" || item.status === "CANCELLED") ? (
                          <button type="button" onClick={() => void handleDeleteDraftPurchase(item.id)} className="ops-btn-danger">
                            {dict.common.delete}
                          </button>
                        ) : null}
                        {item.status !== "CANCELLED" ? <button type="button" onClick={() => void handleCancelPurchase(item.id)} className="ops-btn-danger">{locale === "id" ? "Batalkan" : "Cancel"}</button> : null}
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>

      {(detailLoading || selectedPurchase) ? (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-950/45 px-6 py-8 backdrop-blur-[2px]">
          <div className="absolute inset-0" onClick={() => { if (!detailLoading) setSelectedPurchase(null); }} />
          <div className="relative z-10 max-h-[calc(100vh-4rem)] w-full max-w-5xl overflow-y-auto rounded-2xl border border-line/70 bg-white shadow-panel">
            {detailLoading ? (
              <div className="p-6 text-sm text-ink/60">{locale === "id" ? "Memuat detail pembelian..." : "Loading purchase details..."}</div>
            ) : selectedPurchase ? (
              <div className="p-6">
                <div className="flex items-start justify-between gap-4">
                  <div>
                    <p className="ops-overline">{locale === "id" ? "Detail pembelian" : "Purchase details"}</p>
                    <h3 className="mt-2 text-2xl font-semibold text-ink">{selectedPurchase.purchase_no}</h3>
                    <p className="mt-2 text-sm text-slate-500">
                      {selectedPurchase.agent?.name ?? (locale === "id" ? "Pembelian bebas" : "Direct purchase")} · {selectedPurchase.purchase_date}
                    </p>
                  </div>
                  <div className="flex flex-wrap items-center gap-2">
                    <span className={selectedPurchase.status === "SUBMITTED" ? "ops-chip-active" : selectedPurchase.status === "CANCELLED" ? "ops-chip-danger" : "ops-chip-muted"}>
                      {selectedPurchase.status}
                    </span>
                    {selectedPurchase.status === "SUBMITTED" ? (
                      <button type="button" onClick={() => void printPurchaseReceipt(selectedPurchase)} className="ops-btn-secondary">
                        <Printer className="h-4 w-4" />
                        {locale === "id" ? "Cetak bukti penerimaan" : "Print receipt"}
                      </button>
                    ) : null}
                    <button type="button" onClick={() => setSelectedPurchase(null)} className="inline-flex h-11 w-11 items-center justify-center rounded-xl border border-line/70 bg-white text-slate-500 transition hover:bg-slate-50 hover:text-ink" aria-label={locale === "id" ? "Tutup detail" : "Close details"}>
                      <X className="h-5 w-5" />
                    </button>
                  </div>
                </div>

                <div className="mt-5 grid gap-3 md:grid-cols-2 xl:grid-cols-4">
                  <InfoCard label={locale === "id" ? "Agen / penjual" : "Agent / seller"} value={selectedPurchase.agent?.name ?? (locale === "id" ? "Pembelian bebas" : "Direct purchase")} />
                  <InfoCard label={locale === "id" ? "Jasa Pengiriman" : "Courier"} value={selectedPurchase.courier?.name ?? "-"} />
                  <InfoCard label={locale === "id" ? "Penerima" : "Receiver"} value={selectedPurchase.received_by_employee?.name ?? "-"} />
                  <InfoCard label={locale === "id" ? "Skema bagi hasil" : "Profit share scheme"} value={selectedPurchase.profit_share_scheme?.name ?? "-"} />
                </div>

                <div className="mt-5 space-y-3">
                  {selectedPurchase.lines.map((line) => (
                    <div key={line.id} className="rounded border border-line/70 bg-slate-50/70 px-4 py-3 text-sm text-slate-600">
                      <div className="font-medium text-ink">{line.grade?.name ?? "-"}</div>
                      <div className="mt-1">
                        {locale === "id" ? "Dipesan" : "Ordered"} {formatQuantity(line.qty_ordered, locale, line.unit.code)} · {locale === "id" ? "Harga MAL" : "MAL Price"} {formatCurrencyAmount(line.mal_unit_price ?? 0, locale, currencyCode, 0)} · {locale === "id" ? "Subtotal" : "Subtotal"} {formatCurrencyAmount(line.subtotal, locale, currencyCode, 0)}
                      </div>
                      <div className="mt-1">
                        {locale === "id" ? "Gudang" : "Warehouse"} {line.warehouse?.name ?? "-"}{line.warehouse_location ? ` · ${line.warehouse_location.name}` : ""}
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            ) : null}
          </div>
        </div>
      ) : null}
    </section>
  );
}

function escapeHtml(value: string) {
  return value
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;")
    .replaceAll("'", "&#39;");
}

function buildPurchaseReceiptPrintHtml(detail: PurchaseDetail, locale: string, currencyCode: string) {
  const isIndonesian = locale === "id";
  const safePurchaseNo = escapeHtml(detail.purchase_no);
  const safeAgent = escapeHtml(detail.agent?.name ?? (isIndonesian ? "Pembelian bebas" : "Direct purchase"));
  const safeDate = escapeHtml(new Date(detail.purchase_date).toLocaleDateString(isIndonesian ? "id-ID" : "en-US"));
  const safeStatus = escapeHtml(detail.status);
  const safeCourier = escapeHtml(detail.courier?.name ?? "-");
  const safeReceiver = escapeHtml(detail.received_by_employee?.name ?? "-");
  const safeScheme = escapeHtml(detail.profit_share_scheme?.name ?? "-");
  const safeNotes = escapeHtml(detail.notes ?? "-");

  const totalQty = detail.lines.reduce((sum, line) => sum + line.qty_ordered, 0);
  const totalModal = detail.lines.reduce((sum, line) => sum + line.subtotal, 0);

  const rows = detail.lines.map((line, index) => {
    const safeGrade = escapeHtml(line.grade?.name ?? "-");
    const safeWarehouse = escapeHtml(line.warehouse?.name ?? "-");
    const safeLocation = escapeHtml(line.warehouse_location?.name ?? "-");
    const safeNotesLine = escapeHtml(line.notes ?? "-");
    const qty = escapeHtml(formatQuantity(line.qty_ordered, locale, line.unit.code));
    const malPrice = escapeHtml(formatCurrencyAmount(line.mal_unit_price ?? 0, locale, currencyCode, 0));
    const subtotal = escapeHtml(formatCurrencyAmount(line.subtotal, locale, currencyCode, 0));

    return `<tr>
      <td>${index + 1}</td>
      <td>${safeGrade}</td>
      <td>${qty}</td>
      <td>${malPrice}</td>
      <td>${subtotal}</td>
      <td>${safeWarehouse}</td>
      <td>${safeLocation}</td>
      <td>${safeNotesLine}</td>
    </tr>`;
  }).join("");

  return `<!doctype html>
<html lang="${isIndonesian ? "id" : "en"}">
  <head>
    <meta charset="utf-8" />
    <title>${isIndonesian ? "Cetak Receipt" : "Print Receipt"} ${safePurchaseNo}</title>
    <style>
      body { margin: 0; background: #eef3f5; color: #182126; font-family: Arial, Helvetica, sans-serif; }
      .sheet { max-width: 1120px; margin: 0 auto; padding: 24px; }
      .card { background: #fff; border: 1px solid #d8e0e3; border-radius: 14px; padding: 24px; }
      .header { display: flex; justify-content: space-between; gap: 16px; align-items: flex-start; }
      .eyebrow { margin: 0 0 6px; color: #66768a; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
      h1 { margin: 0; font-size: 34px; line-height: 1.1; }
      .sub { margin-top: 10px; color: #66768a; font-size: 14px; }
      .status { border: 1px solid #d8e0e3; border-radius: 999px; padding: 10px 14px; font-size: 12px; font-weight: 700; text-transform: uppercase; }
      .meta { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-top: 20px; }
      .meta-card { border: 1px solid #d8e0e3; border-radius: 12px; padding: 14px; background: #f8fafb; }
      .label { color: #66768a; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
      .value { margin-top: 8px; font-size: 16px; font-weight: 600; line-height: 1.4; }
      h2 { margin: 28px 0 12px; font-size: 18px; }
      table { width: 100%; border-collapse: collapse; border: 1px solid #d8e0e3; }
      th, td { border-bottom: 1px solid #d8e0e3; padding: 10px 12px; text-align: left; vertical-align: top; font-size: 12px; line-height: 1.45; }
      th { background: #f3f6f7; color: #66768a; font-size: 11px; letter-spacing: .05em; text-transform: uppercase; }
      .notes { border: 1px solid #d8e0e3; border-radius: 12px; padding: 14px; background: #f8fafb; white-space: pre-wrap; font-size: 13px; line-height: 1.6; }
      @media print {
        body { background: #fff; }
        .sheet { max-width: none; padding: 0; }
        .card { border: none; border-radius: 0; padding: 0; }
      }
    </style>
  </head>
  <body>
    <div class="sheet">
      <div class="card">
        <div class="header">
          <div>
            <p class="eyebrow">${isIndonesian ? "Receipt Pembelian" : "Purchase Receipt"}</p>
            <h1>${safePurchaseNo}</h1>
            <div class="sub">${safeAgent} · ${safeDate}</div>
          </div>
          <div class="status">${safeStatus}</div>
        </div>

        <div class="meta">
          <div class="meta-card"><div class="label">${isIndonesian ? "Pembelian" : "Purchase"}</div><div class="value">${safePurchaseNo}</div></div>
          <div class="meta-card"><div class="label">${isIndonesian ? "Jasa Pengiriman" : "Courier"}</div><div class="value">${safeCourier}</div></div>
          <div class="meta-card"><div class="label">${isIndonesian ? "Penerima" : "Receiver"}</div><div class="value">${safeReceiver}</div></div>
          <div class="meta-card"><div class="label">${isIndonesian ? "Skema bagi hasil" : "Profit share scheme"}</div><div class="value">${safeScheme}</div></div>
          <div class="meta-card"><div class="label">${isIndonesian ? "Tanggal pembelian" : "Purchase date"}</div><div class="value">${safeDate}</div></div>
          <div class="meta-card"><div class="label">${isIndonesian ? "Jumlah baris" : "Line count"}</div><div class="value">${detail.lines.length}</div></div>
          <div class="meta-card"><div class="label">${isIndonesian ? "Total qty" : "Total qty"}</div><div class="value">${escapeHtml(formatQuantity(totalQty, locale, detail.lines[0]?.unit.code ?? null))}</div></div>
          <div class="meta-card"><div class="label">${isIndonesian ? "Total modal" : "Total capital"}</div><div class="value">${escapeHtml(formatCurrencyAmount(totalModal, locale, currencyCode, 0))}</div></div>
        </div>

        <h2>${isIndonesian ? "Baris pembelian" : "Purchase lines"}</h2>
        <table>
          <thead>
            <tr>
              <th>${isIndonesian ? "No" : "No"}</th>
              <th>Grade</th>
              <th>Qty</th>
              <th>${isIndonesian ? "Harga MAL" : "MAL Price"}</th>
              <th>Subtotal</th>
              <th>${isIndonesian ? "Gudang" : "Warehouse"}</th>
              <th>${isIndonesian ? "Lokasi" : "Location"}</th>
              <th>${isIndonesian ? "Catatan" : "Notes"}</th>
            </tr>
          </thead>
          <tbody>${rows}</tbody>
        </table>

        <h2>${isIndonesian ? "Catatan pembelian" : "Purchase notes"}</h2>
        <div class="notes">${safeNotes}</div>
      </div>
    </div>
    <script>
      window.addEventListener("load", () => {
        setTimeout(() => window.print(), 120);
      });
    </script>
  </body>
</html>`;
}

function InfoCard({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded border border-line/70 bg-slate-50/70 px-4 py-3">
      <p className="ops-overline">{label}</p>
      <p className="mt-2 text-[14px] font-medium text-ink">{value}</p>
    </div>
  );
}

function Field({
  label,
  value,
  onChange,
  type = "text",
  readOnly
}: {
  label: string;
  value: string;
  onChange: (value: string) => void;
  type?: string;
  readOnly?: boolean;
}) {
  return (
    <label className="block">
      <span className="ops-label">{label}</span>
      <input
        type={type}
        readOnly={readOnly}
        disabled={readOnly}
        value={value}
        onChange={(event) => onChange(event.target.value)}
        className="ops-input"
      />
    </label>
  );
}

function SelectField({
  label,
  value,
  onChange,
  options,
  placeholder
}: {
  label: string;
  value: string;
  onChange: (value: string) => void;
  options: Array<{ value: string; label: string }>;
  placeholder: string;
}) {
  return (
    <label className="block">
      <span className="ops-label">{label}</span>
      <select value={value} onChange={(event) => onChange(event.target.value)} className="ops-select">
        {placeholder ? <option value="">{placeholder}</option> : null}
        {options.map((option) => <option key={option.value} value={option.value}>{option.label}</option>)}
      </select>
    </label>
  );
}
