// Fixed Assets Control Module — สินทรัพย์ถาวร
// Pages exposed on window:
//   • AssetTrackingPage           — overview of all assets + current owner
//   • AssetTransferRequestPage    — list + create + confirm/reject transfer requests
//   • AssetRegisterPage           — master data CRUD + Excel import (FA monitor / admin)
//   • FAReportPage                — current-asset-by-owner report + Excel export
// Helpers also exposed: canManageFAUi.

// ---------------------------------------------------------------------------
// Constants & helpers
// ---------------------------------------------------------------------------
const FA_ATT_TYPES = [
  { code: "image",   label: "รูปสินทรัพย์",        icon: "fileText" },
  { code: "invoice", label: "ใบกำกับ / เอกสารซื้อ", icon: "fileText" },
  { code: "other",   label: "เอกสารอื่นๆ",          icon: "fileText" },
];
const FA_ATT_MAX_BYTES = 5 * 1024 * 1024;
const FA_ATT_ALLOWED = ["pdf","jpg","jpeg","png","docx","xlsx"];

const FA_TRANSFER_STATUS_META = {
  pending:   { color: "amber",   label: "รอยืนยัน",         icon: "clock" },
  confirmed: { color: "emerald", label: "ยืนยันแล้ว / เสร็จสิ้น", icon: "checkCircle" },
  rejected:  { color: "rose",    label: "ปฏิเสธ",          icon: "x" },
  cancelled: { color: "slate",   label: "ยกเลิก",          icon: "ban" },
};

const canManageFAUi = (role) =>
  role === "fa_monitor" || role === "admin" || role === "super_admin";
if (typeof window !== "undefined") window.canManageFAUi = canManageFAUi;

const FAStatusBadge = ({ status }) => (
  status === "active"
    ? <Badge color="emerald">ใช้งาน</Badge>
    : <Badge color="slate">ปิดใช้งาน</Badge>
);
const FATransferBadge = ({ status }) => {
  const m = FA_TRANSFER_STATUS_META[status] || { color: "slate", label: status, icon: "info" };
  return <Badge color={m.color} icon={m.icon}>{m.label}</Badge>;
};

// Resolve an asset's current owner display name from the users[] hydrated by workspace.
const ownerName = (asset, users) => {
  if (!asset?.current_owner_user_id) return "—";
  const u = (users || []).find(x => x.id === asset.current_owner_user_id || x.api_user_id === asset.current_owner_user_id);
  if (!u) return asset.current_owner_user_id;
  return (typeof displayName === "function") ? displayName(u) : (u.full_name || u.email || u.id);
};
const ownerPositionLabel = (asset, users, positions) => {
  if (!asset?.current_owner_user_id) return "—";
  const u = (users || []).find(x => x.id === asset.current_owner_user_id || x.api_user_id === asset.current_owner_user_id);
  if (!u) return "—";
  const names = (u.positions || []).map(pid => (positions || []).find(p => p.id === pid)?.name).filter(Boolean);
  return names.join(" · ") || "—";
};
const ownerDepartmentLabel = (asset, users, positions, departments) => {
  if (!asset?.current_owner_user_id) return "—";
  const u = (users || []).find(x => x.id === asset.current_owner_user_id || x.api_user_id === asset.current_owner_user_id);
  if (!u) return "—";
  const deptIds = new Set();
  (u.positions || []).forEach(pid => {
    const pos = (positions || []).find(p => p.id === pid);
    if (pos?.department_id) deptIds.add(pos.department_id);
  });
  const names = Array.from(deptIds).map(did => (departments || []).find(d => d.id === did)?.name).filter(Boolean);
  return names.join(" · ") || "—";
};

// Map an asset's owner_user_id to the tenant_users (membership) row, so the JWT
// owner check on the backend ("am I the current owner?") works without front-end guessing.
// We rely on workspace's `users[]` which carries both identity id and api_user_id.

// ---------------------------------------------------------------------------
// MASTER DATA MODAL — manage Categories or Locations inline from any form
// ---------------------------------------------------------------------------
const FAMasterListModal = ({ tenant, kind, onClose, onChanged }) => {
  // kind: 'category' | 'location'
  const toast = useToast();
  const meta = kind === "category"
    ? { title: "หมวดสินทรัพย์ (Category)", labelOne: "หมวด" }
    : { title: "สถานที่ (Location)",       labelOne: "สถานที่" };
  const [rows, setRows] = useState([]);
  const [loading, setLoading] = useState(false);
  const [newName, setNewName] = useState("");
  const [editingId, setEditingId] = useState(null);
  const [editName, setEditName] = useState("");
  const [busy, setBusy] = useState(false);

  const reload = async () => {
    if (!tenant?.id) return;
    setLoading(true);
    try {
      const list = await window.apiClient.faMasterList(tenant.id, kind, { status: "__all__" });
      setRows(Array.isArray(list) ? list : []);
    } catch (e) { toast({ kind:"error", msg: e.message || "โหลดไม่สำเร็จ" }); }
    finally { setLoading(false); }
  };
  useEffect(() => { reload(); /* eslint-disable-next-line */ }, [tenant?.id, kind]);

  const create = async () => {
    if (!newName.trim()) { toast({ kind:"error", msg:`กรุณาระบุชื่อ${meta.labelOne}` }); return; }
    setBusy(true);
    try {
      await window.apiClient.faMasterCreate(tenant.id, kind, newName.trim());
      toast({ kind:"success", msg:"เพิ่มแล้ว" });
      setNewName("");
      await reload();
      onChanged && onChanged();
    } catch (e) { toast({ kind:"error", msg: e.message || "เพิ่มไม่สำเร็จ" }); }
    finally { setBusy(false); }
  };

  const saveEdit = async (row) => {
    if (!editName.trim()) { toast({ kind:"error", msg:`กรุณาระบุชื่อ${meta.labelOne}` }); return; }
    setBusy(true);
    try {
      await window.apiClient.faMasterUpdate(tenant.id, kind, row.id, { name: editName.trim() });
      toast({ kind:"success", msg:"บันทึกแล้ว" });
      setEditingId(null); setEditName("");
      await reload();
      onChanged && onChanged();
    } catch (e) { toast({ kind:"error", msg: e.message || "บันทึกไม่สำเร็จ" }); }
    finally { setBusy(false); }
  };

  const toggleStatus = async (row) => {
    setBusy(true);
    try {
      await window.apiClient.faMasterUpdate(tenant.id, kind, row.id, { status: row.status === "active" ? "inactive" : "active" });
      toast({ kind:"success", msg:"เปลี่ยนสถานะแล้ว" });
      await reload();
      onChanged && onChanged();
    } catch (e) { toast({ kind:"error", msg: e.message || "ดำเนินการไม่สำเร็จ" }); }
    finally { setBusy(false); }
  };

  const remove = async (row) => {
    if (!confirm(`ลบ${meta.labelOne} "${row.name}" ?`)) return;
    setBusy(true);
    try {
      await window.apiClient.faMasterDelete(tenant.id, kind, row.id);
      toast({ kind:"success", msg:"ลบแล้ว" });
      await reload();
      onChanged && onChanged();
    } catch (e) { toast({ kind:"error", msg: e.message || "ลบไม่สำเร็จ" }); }
    finally { setBusy(false); }
  };

  return (
    <Modal open={true} onClose={onClose} title={`จัดการ${meta.title}`} width={620}>
      <div className="flex items-end gap-2 mb-3">
        <div className="flex-1">
          <div className="text-[11px] text-ink-500 font-semibold mb-1">เพิ่ม{meta.labelOne}ใหม่</div>
          <Input value={newName} onChange={e=>setNewName(e.target.value)}
            placeholder={`ชื่อ${meta.labelOne} (เช่น ${kind === "category" ? "IT, Furniture" : "สำนักงานใหญ่ ชั้น 4"})`}
            onKeyDown={e => { if (e.key === "Enter") create(); }}/>
        </div>
        <Button variant="primary" icon="plus" onClick={create} disabled={busy}>เพิ่ม</Button>
      </div>

      <div className="text-[11px] text-ink-500 font-semibold mb-1">รายการทั้งหมด ({rows.length})</div>
      <div className="rounded-xl border border-ink-100 overflow-hidden">
        <table className="w-full text-[12.5px]">
          <thead className="bg-ink-50 text-ink-600 text-[11px] uppercase tracking-wider">
            <tr>
              <th className="px-3 py-2 text-left">ชื่อ</th>
              <th className="px-3 py-2 text-center">สถานะ</th>
              <th className="px-3 py-2 text-center">ใช้อยู่</th>
              <th className="px-3 py-2 text-right">Action</th>
            </tr>
          </thead>
          <tbody>
            {loading && <tr><td colSpan={4} className="px-3 py-4 text-center text-ink-500">กำลังโหลด…</td></tr>}
            {!loading && rows.length === 0 && (
              <tr><td colSpan={4} className="px-3 py-6 text-center text-ink-500">ยังไม่มีรายการ — เริ่มเพิ่มด้านบน</td></tr>
            )}
            {rows.map(r => (
              <tr key={r.id} className="border-t border-ink-100">
                <td className="px-3 py-2">
                  {editingId === r.id ? (
                    <Input value={editName} onChange={e=>setEditName(e.target.value)}
                      onKeyDown={e => { if (e.key === "Enter") saveEdit(r); if (e.key === "Escape") { setEditingId(null); setEditName(""); } }}
                      autoFocus/>
                  ) : <span className="text-ink-900">{r.name}</span>}
                </td>
                <td className="px-3 py-2 text-center">
                  <Badge color={r.status === "active" ? "emerald" : "slate"}>{r.status}</Badge>
                </td>
                <td className="px-3 py-2 text-center text-ink-600">{r.usage_count || 0}</td>
                <td className="px-3 py-2 text-right whitespace-nowrap">
                  {editingId === r.id ? (
                    <>
                      <Button variant="primary" icon="check" onClick={()=>saveEdit(r)} disabled={busy}>บันทึก</Button>
                      <Button variant="ghost" icon="x" onClick={()=>{ setEditingId(null); setEditName(""); }}>ยกเลิก</Button>
                    </>
                  ) : (
                    <>
                      <Button variant="ghost" icon="edit" onClick={()=>{ setEditingId(r.id); setEditName(r.name); }}>แก้ไข</Button>
                      <Button variant="ghost" icon={r.status === "active" ? "ban" : "check"} onClick={()=>toggleStatus(r)}>
                        {r.status === "active" ? "ปิด" : "เปิด"}
                      </Button>
                      <Button variant="ghost" icon="trash" onClick={()=>remove(r)} disabled={(r.usage_count || 0) > 0}>ลบ</Button>
                    </>
                  )}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      <div className="mt-3 text-[11px] text-ink-500">
        * รายการที่ยังมีสินทรัพย์ใช้งานอยู่ — ลบไม่ได้ (กรุณาเปลี่ยนสินทรัพย์ไปใช้ตัวอื่นก่อน หรือเปลี่ยนสถานะเป็น "ปิด" แทน)
      </div>
      <div className="mt-4 flex justify-end">
        <Button variant="secondary" onClick={onClose}>ปิด</Button>
      </div>
    </Modal>
  );
};
// Expose globally so the workspace / other pages can reuse it.
if (typeof window !== "undefined") window.FAMasterListModal = FAMasterListModal;

// ---------------------------------------------------------------------------
// CREATE / EDIT ASSET MODAL  (used by Register page + Tracking page detail)
// ---------------------------------------------------------------------------
const CreateAssetModal = ({ tenant, currentUser, currentRole, users, positions, departments, divisions,
                            initial, resubmitOf, onClose, onSaved }) => {
  const toast = useToast();
  // 3 modes:
  //   resubmit  → editing a rejected/cancelled request, will POST /resubmit
  //   edit      → editing an existing asset (PATCH /assets)
  //   create    → brand new asset (POST /create-requests)
  const isResubmit = !!resubmitOf?.id;
  const isEdit = !isResubmit && !!initial?.id;
  // Only Admin / Super Admin can manage Category + Location master data
  const canManageMasters = isTenantAdminRole(currentRole);
  const src = resubmitOf || initial;
  const [form, setForm] = useState(() => ({
    asset_code:              src?.asset_code || "",
    asset_tag_code:          src?.asset_tag_code || "",
    asset_name:              src?.asset_name || "",
    asset_category:          src?.asset_category || "",
    description:             src?.description || "",
    serial_number:           src?.serial_number || "",
    brand:                   src?.brand || "",
    model:                   src?.model || "",
    purchase_date:           src?.purchase_date || "",
    purchase_price:          src?.purchase_price ?? "",
    supplier_name:           src?.supplier_name || "",
    purchase_invoice_number: src?.purchase_invoice_number || "",
    current_owner_user_id:   src?.current_owner_user_id || "",
    location:                src?.location || "",
    status:                  src?.status || "active",
    remark:                  src?.remark || "",
  }));
  const set = (patch) => setForm(prev => ({ ...prev, ...patch }));
  const [saving, setSaving] = useState(false);
  // Two attachments collected inline with the create/edit form
  const [imageFile, setImageFile] = useState(null);     // รูปสินทรัพย์
  const [invoiceFile, setInvoiceFile] = useState(null); // เอกสารซื้อ / ใบกำกับ
  // Approver picker (used on CREATE and RESUBMIT — edit-existing-asset bypasses approval)
  const [approverUserId, setApproverUserId] = useState(resubmitOf?.approver_user_id || "");
  const [requesterComment, setRequesterComment] = useState(resubmitOf?.requester_comment || "");
  // Master data lists — loaded once on mount; refreshable via the manage modal
  const [categories, setCategories] = useState([]);   // [{id, name, status, ...}]
  const [locations,  setLocations]  = useState([]);
  const [mgrKind, setMgrKind] = useState(null);       // null | "category" | "location"

  const reloadMasters = async () => {
    if (!tenant?.id) return;
    try {
      const [cats, locs] = await Promise.all([
        window.apiClient.faMasterList(tenant.id, "category"),
        window.apiClient.faMasterList(tenant.id, "location"),
      ]);
      setCategories(Array.isArray(cats) ? cats : []);
      setLocations(Array.isArray(locs)  ? locs : []);
    } catch (e) { toast({ kind:"error", msg: e.message || "โหลด master data ไม่สำเร็จ" }); }
  };
  useEffect(() => { reloadMasters(); /* eslint-disable-next-line */ }, [tenant?.id]);

  // Asset Code uniqueness check — load existing codes from assets + pending requests
  // on mount, then validate as user types (case-insensitive). Backend re-checks
  // at submit time too, but this gives immediate visual feedback.
  const [existingCodes, setExistingCodes] = useState(new Set());
  useEffect(() => {
    if (!tenant?.id) return;
    Promise.all([
      window.apiClient.faAssetsList(tenant.id).catch(() => []),
      window.apiClient.faCreateReqList(tenant.id, { status: "pending" }).catch(() => []),
    ]).then(([assets, reqs]) => {
      const set = new Set();
      (Array.isArray(assets) ? assets : []).forEach(a => set.add((a.asset_code || "").toLowerCase()));
      (Array.isArray(reqs) ? reqs : []).forEach(r => set.add((r.asset_code || "").toLowerCase()));
      // Exclude the row we're editing/resubmitting so the user can keep the same code
      if (isEdit && initial?.asset_code)        set.delete(initial.asset_code.toLowerCase());
      if (isResubmit && resubmitOf?.asset_code) set.delete(resubmitOf.asset_code.toLowerCase());
      setExistingCodes(set);
    });
    // eslint-disable-next-line
  }, [tenant?.id, isEdit, isResubmit, initial?.id, resubmitOf?.id]);
  const codeTrimmed = (form.asset_code || "").trim();
  const codeIsDuplicate = !!codeTrimmed && existingCodes.has(codeTrimmed.toLowerCase());

  // Validate a file: ≤5MB + allowed extension (PDF/JPG/PNG/DOCX/XLSX for invoice; JPG/PNG only for image)
  const validateFile = (file, kind) => {
    if (!file) return null;
    if (file.size > FA_ATT_MAX_BYTES) return `ไฟล์${kind === "image" ? "รูปสินทรัพย์" : "เอกสารซื้อ"}เกิน 5MB`;
    const ext = (file.name.split(".").pop() || "").toLowerCase();
    const allowed = kind === "image" ? ["jpg","jpeg","png"] : FA_ATT_ALLOWED;
    if (!allowed.includes(ext)) return `ชนิดไฟล์ไม่รองรับ (${kind === "image" ? "JPG/PNG เท่านั้น" : "PDF/JPG/PNG/DOCX/XLSX"})`;
    return null;
  };

  const ownerOptions = useMemo(() => {
    return (users || []).filter(u => u.from_api).map(u => ({
      id: u.id,
      label: (typeof displayName === "function" ? displayName(u) : (u.full_name || u.email)),
      email: u.email,
      employee_code: u.employee_code,
      membership_id: u.membership_id,
    }));
  }, [users]);
  // Approver dropdown excludes the current user — no self-approval. Backend enforces
  // the same rule both at submit time and again at the approve endpoint.
  const myId = currentUser?.id || currentUser?.api_user_id;
  const approverOptions = useMemo(() =>
    ownerOptions.filter(u => u.id !== myId && u.id !== currentUser?.api_user_id),
  [ownerOptions, myId, currentUser?.api_user_id]);

  const onPickOwner = (uid) => {
    const u = ownerOptions.find(x => x.id === uid);
    set({ current_owner_user_id: u ? u.id : "" });
  };

  const handleSave = async () => {
    if (!form.asset_code.trim()) { toast({ kind:"error", msg:"กรุณาระบุ Asset Code" }); return; }
    if (codeIsDuplicate) {
      toast({ kind:"error", msg:`Asset Code "${codeTrimmed}" มีอยู่แล้ว — กรุณาใช้รหัสอื่น` }); return;
    }
    if (!form.asset_name.trim()) { toast({ kind:"error", msg:"กรุณาระบุชื่อสินทรัพย์" }); return; }
    if (!form.asset_category)   { toast({ kind:"error", msg:"กรุณาเลือกหมวด (Category)" }); return; }
    if (!form.location)         { toast({ kind:"error", msg:"กรุณาเลือกสถานที่ (Location)" }); return; }
    if (form.purchase_date && !/^\d{4}-\d{2}-\d{2}$/.test(form.purchase_date)) {
      toast({ kind:"error", msg:"Purchase Date ต้องเป็น YYYY-MM-DD" }); return;
    }
    // CREATE + RESUBMIT both need an approver; EDIT-asset is direct
    if (!isEdit && !approverUserId) { toast({ kind:"error", msg:"กรุณาเลือกผู้อนุมัติ" }); return; }
    if (!isEdit && approverUserId === myId) {
      toast({ kind:"error", msg:"ไม่สามารถเลือกตัวเองเป็นผู้อนุมัติได้ — กรุณาเลือกผู้อื่น" }); return;
    }
    // File pre-flight validation — fail early before hitting the API
    const fileErr = validateFile(imageFile, "image") || validateFile(invoiceFile, "invoice");
    if (fileErr) { toast({ kind:"error", msg: fileErr }); return; }

    setSaving(true);
    try {
      // Resolve owner_user_id → owner_employee_id (membership id) via users[] for backend snapshot
      const ownerObj = ownerOptions.find(o => o.id === form.current_owner_user_id);
      const payload = {
        ...form,
        purchase_price: form.purchase_price === "" ? null : Number(form.purchase_price),
        current_owner_user_id: form.current_owner_user_id || null,
        current_owner_employee_id: ownerObj?.membership_id || null,
      };

      if (isEdit) {
        // EDIT: direct PATCH on the asset
        await window.apiClient.faAssetUpdate(tenant.id, initial.id, payload);
        // Edit-time attachments go on the asset itself (same as before)
        const uploads = [];
        if (imageFile)   uploads.push(window.apiClient.faAssetUploadAttachment(tenant.id, initial.id, imageFile,   { attachment_type: "image" }));
        if (invoiceFile) uploads.push(window.apiClient.faAssetUploadAttachment(tenant.id, initial.id, invoiceFile, { attachment_type: "invoice" }));
        if (uploads.length > 0) {
          try { await Promise.all(uploads); }
          catch (uerr) {
            toast({ kind:"error", msg: "บันทึกข้อมูลสำเร็จ แต่อัปโหลดไฟล์บางส่วนไม่สำเร็จ: " + (uerr.message || "") });
            onSaved && onSaved();
            onClose && onClose();
            return;
          }
        }
        toast({ kind:"success", msg:"บันทึกข้อมูลแล้ว" });
      } else if (isResubmit) {
        // RESUBMIT: reuse existing request id, server flips status back to pending
        await window.apiClient.faCreateReqResubmit(tenant.id, resubmitOf.id, {
          ...payload,
          approver_user_id: approverUserId,
          requester_comment: requesterComment || null,
        });
        const uploads = [];
        if (imageFile)   uploads.push(window.apiClient.faCreateReqUploadAttachment(tenant.id, resubmitOf.id, imageFile,   { attachment_type: "image" }));
        if (invoiceFile) uploads.push(window.apiClient.faCreateReqUploadAttachment(tenant.id, resubmitOf.id, invoiceFile, { attachment_type: "invoice" }));
        if (uploads.length > 0) {
          try { await Promise.all(uploads); }
          catch (uerr) {
            toast({ kind:"error", msg: `ส่งซ้ำสำเร็จ แต่ไฟล์แนบใหม่บางส่วนล้มเหลว — เพิ่มเติมได้ใน My FA Approval` });
            onSaved && onSaved();
            onClose && onClose();
            return;
          }
        }
        toast({ kind:"success", msg:`ส่งคำขอ ${resubmitOf.request_number} อีกครั้งแล้ว · รออนุมัติจากผู้อนุมัติ` });
      } else {
        // CREATE: submit approval request — asset materialises only after approver confirms
        const reqRes = await window.apiClient.faCreateReqSubmit(tenant.id, {
          ...payload,
          approver_user_id: approverUserId,
          requester_comment: requesterComment || null,
        });
        // Upload attachments against the create-request (carried over on approval)
        const uploads = [];
        if (imageFile)   uploads.push(window.apiClient.faCreateReqUploadAttachment(tenant.id, reqRes.id, imageFile,   { attachment_type: "image" }));
        if (invoiceFile) uploads.push(window.apiClient.faCreateReqUploadAttachment(tenant.id, reqRes.id, invoiceFile, { attachment_type: "invoice" }));
        if (uploads.length > 0) {
          try { await Promise.all(uploads); }
          catch (uerr) {
            toast({ kind:"error", msg: `ส่งคำขอ ${reqRes.request_number} แล้ว แต่ไฟล์แนบบางส่วนล้มเหลว — เพิ่มเติมได้ใน My FA Approval` });
            onSaved && onSaved();
            onClose && onClose();
            return;
          }
        }
        toast({ kind:"success", msg:`ส่งคำขออนุมัติ ${reqRes.request_number} แล้ว · รออนุมัติจากผู้อนุมัติ` });
      }

      onSaved && onSaved();
      onClose && onClose();
    } catch (e) {
      toast({ kind:"error", msg: e.message || "บันทึกไม่สำเร็จ" });
    } finally { setSaving(false); }
  };

  return (
    <Modal open={true} onClose={onClose}
      title={isEdit       ? `แก้ไขสินทรัพย์ · ${initial.asset_code}`
            : isResubmit  ? `แก้ไข & ส่งใหม่ · ${resubmitOf.request_number}`
                          : "เพิ่มสินทรัพย์ใหม่"}
      width={840}>
      <div className="grid grid-cols-2 gap-3">
        <Field label="Asset Code *"
          hint={codeTrimmed && !codeIsDuplicate ? "✓ ไม่ซ้ำกับรหัสที่มีอยู่" : "ต้องไม่ซ้ำกับสินทรัพย์/คำขออื่น"}
          error={codeIsDuplicate ? `Asset Code "${codeTrimmed}" มีอยู่แล้ว — กรุณาใช้รหัสอื่น` : null}>
          <Input value={form.asset_code} onChange={e=>set({ asset_code: e.target.value })}
            placeholder="เช่น FA-2026-0001"
            className={codeIsDuplicate ? "!border-rose-400 focus:!border-rose-500" : ""}/>
        </Field>
        <Field label="Asset Tag Code">
          <Input value={form.asset_tag_code} onChange={e=>set({ asset_tag_code: e.target.value })} placeholder="ป้ายติดเครื่อง (ถ้ามี)"/>
        </Field>
        <Field label="ชื่อสินทรัพย์ *" className="col-span-2">
          <Input value={form.asset_name} onChange={e=>set({ asset_name: e.target.value })}/>
        </Field>
        <Field label="หมวด / Category *">
          <div className="flex items-center gap-1.5">
            <Select value={form.asset_category} onChange={e=>set({ asset_category: e.target.value })} className="flex-1">
              <option value="">— เลือกหมวด —</option>
              {categories.filter(c => c.status === "active" || c.name === form.asset_category)
                .map(c => <option key={c.id} value={c.name}>{c.name}{c.status !== "active" ? " (ปิด)" : ""}</option>)}
            </Select>
            {canManageMasters && (
              <Button variant="ghost" icon="settings" onClick={()=>setMgrKind("category")} title="จัดการหมวด">จัดการ</Button>
            )}
          </div>
        </Field>
        <Field label="Serial Number">
          <Input value={form.serial_number} onChange={e=>set({ serial_number: e.target.value })}/>
        </Field>
        <Field label="Brand">
          <Input value={form.brand} onChange={e=>set({ brand: e.target.value })}/>
        </Field>
        <Field label="Model">
          <Input value={form.model} onChange={e=>set({ model: e.target.value })}/>
        </Field>
        <Field label="Purchase Date" hint="วว-ดด-ปปปป (ค.ศ.)">
          {window.ThaiDateInput
            ? <window.ThaiDateInput value={form.purchase_date} onChange={(v)=>set({ purchase_date: v })}/>
            : <Input type="date" value={form.purchase_date} onChange={e=>set({ purchase_date: e.target.value })}/>}
        </Field>
        <Field label="Purchase Price (THB)">
          <Input type="number" min="0" step="0.01" value={form.purchase_price} onChange={e=>set({ purchase_price: e.target.value })}/>
        </Field>
        <Field label="ผู้จำหน่าย / Supplier">
          <Input value={form.supplier_name} onChange={e=>set({ supplier_name: e.target.value })}/>
        </Field>
        <Field label="Invoice Number">
          <Input value={form.purchase_invoice_number} onChange={e=>set({ purchase_invoice_number: e.target.value })}/>
        </Field>
        <Field label="ผู้ครอบครองปัจจุบัน">
          <Select value={form.current_owner_user_id} onChange={e=>onPickOwner(e.target.value)}>
            <option value="">— ไม่ระบุ —</option>
            {ownerOptions.map(u => <option key={u.id} value={u.id}>{u.label} ({u.email})</option>)}
          </Select>
        </Field>
        <Field label="สถานที่ / Location *">
          <div className="flex items-center gap-1.5">
            <Select value={form.location} onChange={e=>set({ location: e.target.value })} className="flex-1">
              <option value="">— เลือกสถานที่ —</option>
              {locations.filter(l => l.status === "active" || l.name === form.location)
                .map(l => <option key={l.id} value={l.name}>{l.name}{l.status !== "active" ? " (ปิด)" : ""}</option>)}
            </Select>
            {canManageMasters && (
              <Button variant="ghost" icon="settings" onClick={()=>setMgrKind("location")} title="จัดการสถานที่">จัดการ</Button>
            )}
          </div>
        </Field>
        <Field label="สถานะ">
          <Select value={form.status} onChange={e=>set({ status: e.target.value })}>
            <option value="active">Active</option>
            <option value="inactive">Inactive</option>
          </Select>
        </Field>
        <Field label="คำอธิบาย / Description" className="col-span-2">
          <Textarea rows={2} value={form.description} onChange={e=>set({ description: e.target.value })}/>
        </Field>
        <Field label="หมายเหตุ" className="col-span-2">
          <Textarea rows={2} value={form.remark} onChange={e=>set({ remark: e.target.value })}/>
        </Field>

        {/* Inline attachments — max 5MB per file */}
        <div className="col-span-2 rounded-xl border border-ink-100 bg-ink-50/40 p-3">
          <div className="text-[12px] font-semibold text-ink-800 mb-2 flex items-center gap-1.5">
            <Icon name="paperclip" size={13}/> ไฟล์แนบ <span className="text-[10.5px] text-ink-500 font-normal">(แต่ละไฟล์ห้ามเกิน 5MB)</span>
          </div>
          <div className="grid grid-cols-2 gap-3">
            <Field label="รูปสินทรัพย์ (JPG/PNG)">
              <input type="file" accept=".jpg,.jpeg,.png"
                onChange={e => setImageFile(e.target.files?.[0] || null)}
                className="block w-full text-[12px] file:mr-3 file:px-3 file:py-1.5 file:rounded-md file:border-0 file:bg-brand-50 file:text-brand-700 hover:file:bg-brand-100"/>
              {imageFile && (
                <div className="text-[11px] text-ink-600 mt-1 flex items-center gap-2">
                  <span className="truncate flex-1">{imageFile.name} · {formatBytes(imageFile.size)}</span>
                  <button type="button" onClick={()=>setImageFile(null)} className="text-rose-600 hover:underline">ลบ</button>
                </div>
              )}
            </Field>
            <Field label="เอกสารซื้อ / ใบกำกับ (PDF/JPG/PNG/DOCX/XLSX)">
              <input type="file" accept=".pdf,.jpg,.jpeg,.png,.docx,.xlsx"
                onChange={e => setInvoiceFile(e.target.files?.[0] || null)}
                className="block w-full text-[12px] file:mr-3 file:px-3 file:py-1.5 file:rounded-md file:border-0 file:bg-brand-50 file:text-brand-700 hover:file:bg-brand-100"/>
              {invoiceFile && (
                <div className="text-[11px] text-ink-600 mt-1 flex items-center gap-2">
                  <span className="truncate flex-1">{invoiceFile.name} · {formatBytes(invoiceFile.size)}</span>
                  <button type="button" onClick={()=>setInvoiceFile(null)} className="text-rose-600 hover:underline">ลบ</button>
                </div>
              )}
            </Field>
          </div>
          {isEdit && (
            <div className="text-[10.5px] text-ink-500 mt-2">
              * แนบไฟล์ตรงนี้จะ <strong>เพิ่ม</strong>ไฟล์ใหม่ให้สินทรัพย์ — ไม่ทับไฟล์เก่า (จัดการไฟล์เดิมได้ที่หน้า Detail Drawer)
            </div>
          )}
        </div>

        {/* Approver section — shown for CREATE + RESUBMIT (edit-asset bypasses). */}
        {!isEdit && (
          <div className="col-span-2 rounded-xl border border-amber-200 bg-amber-50/50 p-3">
            <div className="text-[12px] font-semibold text-amber-900 mb-2 flex items-center gap-1.5">
              <Icon name="send" size={13}/>
              {isResubmit ? "ส่งขออนุมัติอีกครั้ง" : "ส่งขออนุมัติ"}
              <span className="text-[10.5px] text-amber-700 font-normal">(สินทรัพย์จะถูกสร้างเมื่อผู้อนุมัติยืนยัน)</span>
            </div>
            {isResubmit && resubmitOf?.approver_comment && (
              <div className="mb-2 text-[11.5px] text-rose-800 bg-rose-50/70 border border-rose-200 rounded-lg p-2">
                <strong>เหตุผลที่ถูกปฏิเสธ:</strong> {resubmitOf.approver_comment}
              </div>
            )}
            <div className="grid grid-cols-2 gap-3">
              <Field label="ผู้อนุมัติ *" hint="เลือกผู้อื่นในบริษัท — ไม่สามารถอนุมัติเองได้">
                <Select value={approverUserId} onChange={e=>setApproverUserId(e.target.value)}>
                  <option value="">— เลือกผู้อนุมัติ —</option>
                  {approverOptions.map(u => <option key={u.id} value={u.id}>{u.label} ({u.email})</option>)}
                </Select>
                {approverOptions.length === 0 && (
                  <div className="text-[11px] text-rose-700 mt-1">⚠ ยังไม่มีสมาชิกอื่นในบริษัทที่อนุมัติได้ — กรุณาเพิ่มสมาชิกใน User Management ก่อน</div>
                )}
              </Field>
              <Field label="ความคิดเห็นถึงผู้อนุมัติ">
                <Input value={requesterComment} onChange={e=>setRequesterComment(e.target.value)} placeholder="เหตุผล / บริบทเพิ่มเติม (ถ้ามี)"/>
              </Field>
            </div>
          </div>
        )}
      </div>
      <div className="mt-5 flex justify-end gap-2">
        <Button variant="ghost" onClick={onClose}>ยกเลิก</Button>
        <Button variant="primary" icon={isEdit ? "check" : "send"} onClick={handleSave} disabled={saving || codeIsDuplicate}>
          {saving
            ? (isEdit ? "กำลังบันทึก…" : "กำลังส่งคำขอ…")
            : codeIsDuplicate
              ? "Asset Code ซ้ำ — แก้ไขก่อน"
              : (isEdit ? "บันทึก" : isResubmit ? "ส่งขออนุมัติอีกครั้ง" : "ส่งขออนุมัติ")}
        </Button>
      </div>

      {mgrKind && (
        <FAMasterListModal tenant={tenant} kind={mgrKind}
          onClose={()=>setMgrKind(null)}
          onChanged={reloadMasters}/>
      )}
    </Modal>
  );
};

// ---------------------------------------------------------------------------
// ATTACHMENT UPLOAD MODAL
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// FILE PREVIEW MODAL — inline preview for image / PDF; download fallback for others.
// Caller fetches the blob first (because the API needs the JWT header), then
// passes us { url, contentType, filename } where `url` is from URL.createObjectURL.
// ---------------------------------------------------------------------------
const FAFilePreviewModal = ({ preview, onClose, onDownload }) => {
  if (!preview) return null;
  const { url, contentType, filename } = preview;
  const ct = (contentType || "").toLowerCase();
  const ext = (filename || "").split(".").pop().toLowerCase();
  const isImage = ct.startsWith("image/") || ["jpg","jpeg","png","gif","webp"].includes(ext);
  const isPdf = ct === "application/pdf" || ext === "pdf";

  return (
    <Modal open={true} onClose={onClose} title={`ดูตัวอย่าง · ${filename}`} width={isPdf ? 960 : 720}>
      {isImage && (
        <div className="flex justify-center bg-ink-900/5 rounded-lg overflow-auto" style={{ maxHeight: "70vh" }}>
          <img src={url} alt={filename} style={{ maxWidth: "100%", maxHeight: "70vh", objectFit: "contain" }}/>
        </div>
      )}
      {isPdf && (
        <iframe src={url} title={filename}
          style={{ width: "100%", height: "75vh", border: "1px solid #e5e7eb", borderRadius: 8 }}/>
      )}
      {!isImage && !isPdf && (
        <div className="rounded-xl border-2 border-dashed border-ink-200 bg-ink-50/40 p-8 text-center">
          <Icon name="fileText" size={32} className="text-ink-400 mx-auto mb-2"/>
          <div className="text-[13px] text-ink-700 font-medium mb-1">ไฟล์ชนิดนี้ไม่รองรับการแสดงตัวอย่าง</div>
          <div className="text-[11.5px] text-ink-500 mb-3">{filename}</div>
          <Button variant="primary" icon="download" onClick={onDownload}>ดาวน์โหลดเพื่อเปิดดู</Button>
        </div>
      )}
      <div className="mt-4 flex justify-end gap-2">
        <Button variant="ghost" icon="download" onClick={onDownload}>ดาวน์โหลด</Button>
        <Button variant="secondary" onClick={onClose}>ปิด</Button>
      </div>
    </Modal>
  );
};

const FAAttachmentUploadModal = ({ tenant, asset, onClose, onUploaded }) => {
  const toast = useToast();
  const [file, setFile] = useState(null);
  const [type, setType] = useState("image");
  const [busy, setBusy] = useState(false);

  const submit = async () => {
    if (!file) { toast({ kind:"error", msg:"กรุณาเลือกไฟล์" }); return; }
    if (file.size > FA_ATT_MAX_BYTES) { toast({ kind:"error", msg:`ไฟล์เกิน ${FA_ATT_MAX_BYTES/(1024*1024)} MB` }); return; }
    const ext = (file.name.split(".").pop() || "").toLowerCase();
    if (!FA_ATT_ALLOWED.includes(ext)) { toast({ kind:"error", msg:"ชนิดไฟล์ไม่รองรับ (PDF/JPG/PNG/DOCX/XLSX)" }); return; }
    setBusy(true);
    try {
      await window.apiClient.faAssetUploadAttachment(tenant.id, asset.id, file, { attachment_type: type });
      toast({ kind:"success", msg:"อัปโหลดไฟล์แล้ว" });
      onUploaded && onUploaded();
      onClose && onClose();
    } catch (e) { toast({ kind:"error", msg: e.message || "อัปโหลดไม่สำเร็จ" }); }
    finally { setBusy(false); }
  };

  return (
    <Modal open={true} onClose={onClose} title={`แนบไฟล์ · ${asset.asset_code}`} width={520}>
      <div className="space-y-3">
        <Field label="ประเภทไฟล์">
          <Select value={type} onChange={e=>setType(e.target.value)}>
            {FA_ATT_TYPES.map(t => <option key={t.code} value={t.code}>{t.label}</option>)}
          </Select>
        </Field>
        <Field label="ไฟล์ (≤5MB, PDF/JPG/PNG/DOCX/XLSX)">
          <input type="file" accept=".pdf,.jpg,.jpeg,.png,.docx,.xlsx"
            onChange={e => setFile(e.target.files?.[0] || null)}
            className="block w-full text-[12px] file:mr-3 file:px-3 file:py-1.5 file:rounded-md file:border-0 file:bg-brand-50 file:text-brand-700 hover:file:bg-brand-100"/>
        </Field>
        {file && (
          <div className="text-[11.5px] text-ink-600">
            {file.name} · {formatBytes(file.size)}
          </div>
        )}
      </div>
      <div className="mt-5 flex justify-end gap-2">
        <Button variant="ghost" onClick={onClose}>ยกเลิก</Button>
        <Button variant="primary" icon="upload" onClick={submit} disabled={busy}>
          {busy ? "กำลังอัปโหลด…" : "อัปโหลด"}
        </Button>
      </div>
    </Modal>
  );
};

// ---------------------------------------------------------------------------
// ASSET DETAIL DRAWER  (view-only inspect + tabs for attachments / transfers / history)
// ---------------------------------------------------------------------------
const AssetDetailDrawer = ({ tenant, currentRole, currentUser, asset, users, positions, departments,
                             onClose, onChanged, onRequestTransfer }) => {
  const toast = useToast();
  const canManage = canManageFAUi(currentRole);
  const [tab, setTab] = useState("info");
  const [detail, setDetail] = useState(asset);
  const [loading, setLoading] = useState(false);
  const [history, setHistory] = useState([]);
  const [uploadOpen, setUploadOpen] = useState(false);
  const [editOpen, setEditOpen] = useState(false);

  const reload = async () => {
    if (!asset?.id) return;
    setLoading(true);
    try {
      const d = await window.apiClient.faAssetGet(tenant.id, asset.id);
      setDetail(d);
    } catch (e) { toast({ kind:"error", msg: e.message || "โหลดสินทรัพย์ไม่สำเร็จ" }); }
    finally { setLoading(false); }
  };
  useEffect(() => { reload(); /* eslint-disable-next-line */ }, [asset?.id]);

  useEffect(() => {
    if (tab !== "history" || !asset?.id) return;
    window.apiClient.faOwnerHistory(tenant.id, asset.id).then(rows => setHistory(rows || [])).catch(()=>{});
  }, [tab, asset?.id, tenant?.id]);

  const downloadAtt = async (att) => {
    try {
      const blob = await window.apiClient.faAssetDownloadAttachmentBlob(tenant.id, asset.id, att.id);
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url; a.download = att.filename;
      document.body.appendChild(a); a.click(); a.remove();
      setTimeout(() => URL.revokeObjectURL(url), 1000);
    } catch (e) { toast({ kind:"error", msg: e.message || "ดาวน์โหลดไม่สำเร็จ" }); }
  };
  // Inline preview — fetch blob (auth-headered) then open in modal
  const [preview, setPreview] = useState(null);   // null | { url, contentType, filename, att }
  const previewAtt = async (att) => {
    try {
      const blob = await window.apiClient.faAssetDownloadAttachmentBlob(tenant.id, asset.id, att.id);
      const url = URL.createObjectURL(blob);
      setPreview({ url, contentType: att.content_type || blob.type, filename: att.filename, att });
    } catch (e) { toast({ kind:"error", msg: e.message || "เปิดดูไม่สำเร็จ" }); }
  };
  const closePreview = () => {
    if (preview?.url) { try { URL.revokeObjectURL(preview.url); } catch {} }
    setPreview(null);
  };
  const deleteAtt = async (att) => {
    if (!confirm(`ลบไฟล์ ${att.filename}?`)) return;
    try {
      await window.apiClient.faAssetDeleteAttachment(tenant.id, asset.id, att.id);
      toast({ kind:"success", msg:"ลบไฟล์แล้ว" });
      reload();
    } catch (e) { toast({ kind:"error", msg: e.message || "ลบไม่สำเร็จ" }); }
  };

  const toggleStatus = async () => {
    if (!detail) return;
    try {
      if (detail.status === "active") {
        await window.apiClient.faAssetInactivate(tenant.id, detail.id);
        toast({ kind:"success", msg:"ปิดใช้งานแล้ว" });
      } else {
        await window.apiClient.faAssetReactivate(tenant.id, detail.id);
        toast({ kind:"success", msg:"เปิดใช้งานแล้ว" });
      }
      await reload();
      onChanged && onChanged();
    } catch (e) { toast({ kind:"error", msg: e.message || "ดำเนินการไม่สำเร็จ" }); }
  };

  return (
    <Drawer open={true} onClose={onClose} title={detail?.asset_name || asset.asset_name} subtitle={`${asset.asset_code}${asset.asset_tag_code ? " · " + asset.asset_tag_code : ""}`} width={680}>
      <div className="flex items-center gap-2 mb-3">
        <FAStatusBadge status={detail?.status || asset.status}/>
        {detail?.pending_transfer_id && <Badge color="amber" icon="clock">มีคำขอโอนรอดำเนินการ</Badge>}
        <div className="ml-auto flex items-center gap-1.5">
          {canManage && (
            <>
              <Button variant="ghost" icon="edit" onClick={()=>setEditOpen(true)}>แก้ไข</Button>
              <Button variant="ghost" icon="upload" onClick={()=>setUploadOpen(true)}>แนบไฟล์</Button>
              <Button variant="ghost" icon={detail?.status === "active" ? "ban" : "check"} onClick={toggleStatus}>
                {detail?.status === "active" ? "ปิดใช้งาน" : "เปิดใช้งาน"}
              </Button>
            </>
          )}
          {(detail?.status === "active" && !detail?.pending_transfer_id) && (
            <Button variant="secondary" icon="send" onClick={()=>onRequestTransfer && onRequestTransfer(detail)}>ขอโอน</Button>
          )}
        </div>
      </div>

      <div className="flex gap-1 border-b border-ink-200 mb-3 text-[12px]">
        {[
          { k:"info",        label:"ข้อมูล" },
          { k:"attachments", label:`ไฟล์แนบ (${(detail?.attachments || []).length})` },
          { k:"transfers",   label:`คำขอโอน (${(detail?.transfers || []).length})` },
          { k:"history",     label:"ประวัติผู้ครอบครอง" },
        ].map(t => (
          <button key={t.k} onClick={()=>setTab(t.k)}
            className={`px-3 h-8 -mb-px border-b-2 transition ${tab===t.k?"border-brand-600 text-brand-700 font-semibold":"border-transparent text-ink-500 hover:text-ink-800"}`}>
            {t.label}
          </button>
        ))}
      </div>

      {tab === "info" && detail && (
        <div className="grid grid-cols-2 gap-3 text-[12.5px]">
          <KV label="Asset Code" value={detail.asset_code}/>
          <KV label="Asset Tag Code" value={detail.asset_tag_code || "—"}/>
          <KV label="หมวด / Category" value={detail.asset_category || "—"}/>
          <KV label="Serial Number" value={detail.serial_number || "—"}/>
          <KV label="Brand" value={detail.brand || "—"}/>
          <KV label="Model" value={detail.model || "—"}/>
          <KV label="Purchase Date" value={detail.purchase_date ? formatDate(detail.purchase_date) : "—"}/>
          <KV label="Purchase Price" value={isFinite(detail.purchase_price) && detail.purchase_price !== null ? formatMoney(detail.purchase_price) : "—"}/>
          <KV label="Supplier" value={detail.supplier_name || "—"}/>
          <KV label="Invoice Number" value={detail.purchase_invoice_number || "—"}/>
          <KV label="ผู้ครอบครองปัจจุบัน" value={ownerName(detail, users)}/>
          <KV label="ตำแหน่ง" value={ownerPositionLabel(detail, users, positions)}/>
          <KV label="หน่วยงาน" value={ownerDepartmentLabel(detail, users, positions, departments)}/>
          <KV label="Location" value={detail.location || "—"}/>
          <KV label="โอนล่าสุด" value={detail.last_transfer_at ? formatDateTime(detail.last_transfer_at) : "—"}/>
          <KV label="อัปเดตล่าสุด" value={formatDateTime(detail.updated_at)}/>
          <div className="col-span-2 mt-1 rounded-lg border border-ink-100 bg-ink-50/60 p-3">
            <div className="text-[11px] uppercase tracking-wider text-ink-500 font-semibold mb-1">รายละเอียด / หมายเหตุ</div>
            <div className="whitespace-pre-wrap">{detail.description || detail.remark || "—"}</div>
          </div>
        </div>
      )}

      {tab === "attachments" && (
        <div className="space-y-2">
          {(detail?.attachments || []).length === 0 ? (
            <EmptyHint icon="paperclip" text="ยังไม่มีไฟล์แนบ"/>
          ) : (detail.attachments).map(att => (
            <div key={att.id} className="flex items-center gap-3 px-3 py-2 rounded-lg border border-ink-100 bg-white">
              <Icon name="paperclip" size={14} className="text-ink-500"/>
              <div className="flex-1 min-w-0">
                <div className="text-[12.5px] text-ink-900 truncate">{att.filename}</div>
                <div className="text-[10.5px] text-ink-500">
                  {(FA_ATT_TYPES.find(t => t.code === att.attachment_type)?.label) || att.attachment_type}
                  {" · "}{formatBytes(att.file_size || 0)}
                  {" · "}{formatDateTime(att.uploaded_at)}
                </div>
              </div>
              <Button variant="ghost" icon="eye" onClick={()=>previewAtt(att)}>ดูตัวอย่าง</Button>
              <Button variant="ghost" icon="download" onClick={()=>downloadAtt(att)}>โหลด</Button>
              {canManage && <Button variant="ghost" icon="trash" onClick={()=>deleteAtt(att)}>ลบ</Button>}
            </div>
          ))}
        </div>
      )}

      {tab === "transfers" && (
        <div className="space-y-2">
          {(detail?.transfers || []).length === 0 ? (
            <EmptyHint icon="send" text="ยังไม่มีคำขอโอน"/>
          ) : (detail.transfers).map(tr => (
            <div key={tr.id} className="px-3 py-2 rounded-lg border border-ink-100 bg-white text-[12px]">
              <div className="flex items-center gap-2">
                <span className="font-mono font-semibold text-ink-900">{tr.transfer_request_number}</span>
                <FATransferBadge status={tr.status}/>
                <span className="ml-auto text-ink-500">{formatDateTime(tr.created_at)}</span>
              </div>
              {tr.transfer_reason && <div className="mt-1 text-ink-700">เหตุผล: {tr.transfer_reason}</div>}
              {tr.owner_comment && <div className="mt-0.5 text-ink-500">ความเห็นเจ้าของ: {tr.owner_comment}</div>}
            </div>
          ))}
        </div>
      )}

      {tab === "history" && (
        <div className="space-y-2">
          {history.length === 0 ? (
            <EmptyHint icon="history" text="ยังไม่มีประวัติผู้ครอบครอง"/>
          ) : history.map(h => (
            <div key={h.id} className="px-3 py-2 rounded-lg border border-ink-100 bg-white text-[12px]">
              <div className="flex items-center gap-2">
                <span className="font-semibold text-ink-900">{ownerName({ current_owner_user_id: h.new_owner_user_id }, users)}</span>
                <Badge color="slate" className="!text-[10px]">{h.source}</Badge>
                <span className="ml-auto font-mono text-ink-500">{h.transfer_date}</span>
              </div>
              {h.previous_owner_user_id && (
                <div className="text-[11px] text-ink-500 mt-0.5">
                  จาก: {ownerName({ current_owner_user_id: h.previous_owner_user_id }, users)}
                </div>
              )}
              {h.comment && <div className="text-ink-600 mt-0.5">{h.comment}</div>}
            </div>
          ))}
        </div>
      )}

      {uploadOpen && (
        <FAAttachmentUploadModal tenant={tenant} asset={detail} onClose={()=>setUploadOpen(false)} onUploaded={reload}/>
      )}
      {editOpen && (
        <CreateAssetModal tenant={tenant} currentUser={currentUser} currentRole={currentRole}
          users={users} positions={positions} departments={departments}
          initial={detail} onClose={()=>setEditOpen(false)}
          onSaved={()=>{ reload(); onChanged && onChanged(); }}/>
      )}
      <FAFilePreviewModal preview={preview} onClose={closePreview}
        onDownload={() => { if (preview?.att) downloadAtt(preview.att); }}/>
    </Drawer>
  );
};
const KV = ({ label, value }) => (
  <div className="rounded-lg border border-ink-100 bg-white px-3 py-2">
    <div className="text-[10.5px] uppercase tracking-wider text-ink-400 font-semibold">{label}</div>
    <div className="text-ink-900 mt-0.5">{value}</div>
  </div>
);
const EmptyHint = ({ icon, text }) => (
  <div className="rounded-xl border-2 border-dashed border-ink-200 bg-ink-50/30 p-6 text-center">
    <Icon name={icon} size={24} className="text-ink-400 mx-auto mb-1"/>
    <div className="text-[12.5px] text-ink-500">{text}</div>
  </div>
);

// ---------------------------------------------------------------------------
// CREATE TRANSFER REQUEST MODAL
// ---------------------------------------------------------------------------
const CreateTransferModal = ({ tenant, assets, presetAssetId, users, onClose, onCreated }) => {
  const toast = useToast();
  const [assetId, setAssetId] = useState(presetAssetId || "");
  const [reason, setReason] = useState("");
  const [requestedDate, setRequestedDate] = useState("");
  const [comment, setComment] = useState("");
  const [busy, setBusy] = useState(false);

  const eligible = useMemo(() =>
    (assets || []).filter(a => a.status === "active" && !a.pending_transfer_id),
  [assets]);

  const selected = eligible.find(a => a.id === assetId);

  const submit = async () => {
    if (!assetId) { toast({ kind:"error", msg:"กรุณาเลือกสินทรัพย์" }); return; }
    if (!reason.trim()) { toast({ kind:"error", msg:"กรุณาระบุเหตุผลในการโอน" }); return; }
    setBusy(true);
    try {
      const res = await window.apiClient.faTransferCreate(tenant.id, {
        asset_id: assetId,
        transfer_reason: reason.trim(),
        requested_transfer_date: requestedDate || null,
        requester_comment: comment || null,
      });
      toast({ kind:"success", msg:`สร้างคำขอ ${res.transfer_request_number} แล้ว` });
      onCreated && onCreated();
      onClose && onClose();
    } catch (e) { toast({ kind:"error", msg: e.message || "สร้างไม่สำเร็จ" }); }
    finally { setBusy(false); }
  };

  return (
    <Modal open={true} onClose={onClose} title="ขอโอนสินทรัพย์ใหม่" width={640}>
      <div className="space-y-3">
        <Field label="สินทรัพย์ที่ต้องการขอโอน *">
          <Select value={assetId} onChange={e=>setAssetId(e.target.value)}>
            <option value="">— เลือกสินทรัพย์ —</option>
            {eligible.map(a => (
              <option key={a.id} value={a.id}>
                {a.asset_code} · {a.asset_name}
              </option>
            ))}
          </Select>
        </Field>
        {selected && (
          <div className="rounded-lg border border-amber-200 bg-amber-50/60 px-3 py-2 text-[12px]">
            <div className="text-ink-700"><strong>ผู้ครอบครองปัจจุบัน:</strong> {ownerName(selected, users)}</div>
            <div className="text-ink-500">ตำแหน่ง: {selected.location || "—"} · หมวด: {selected.asset_category || "—"}</div>
          </div>
        )}
        <Field label="เหตุผลในการโอน *">
          <Textarea rows={3} value={reason} onChange={e=>setReason(e.target.value)} placeholder="เช่น โอนเครื่องคอมพิวเตอร์ให้พนักงานใหม่"/>
        </Field>
        <Field label="วันที่ต้องการรับโอน (ถ้ามี)" hint="วว-ดด-ปปปป (ค.ศ.)">
          {window.ThaiDateInput
            ? <window.ThaiDateInput value={requestedDate} onChange={(v)=>setRequestedDate(v)}/>
            : <Input type="date" value={requestedDate} onChange={e=>setRequestedDate(e.target.value)}/>}
        </Field>
        <Field label="ความคิดเห็นเพิ่มเติม">
          <Textarea rows={2} value={comment} onChange={e=>setComment(e.target.value)}/>
        </Field>
      </div>
      <div className="mt-5 flex justify-end gap-2">
        <Button variant="ghost" onClick={onClose}>ยกเลิก</Button>
        <Button variant="primary" icon="send" onClick={submit} disabled={busy}>
          {busy ? "กำลังส่ง…" : "ส่งคำขอ"}
        </Button>
      </div>
    </Modal>
  );
};

// ---------------------------------------------------------------------------
// CONFIRM / REJECT TRANSFER MODAL
// ---------------------------------------------------------------------------
const ConfirmTransferModal = ({ tenant, transfer, mode, onClose, onDone, users }) => {
  // mode: "confirm" | "reject" | "cancel"
  const toast = useToast();
  const [comment, setComment] = useState("");
  const [busy, setBusy] = useState(false);
  const meta = {
    confirm: { title:"ยืนยันการโอน", btn:"ยืนยันรับโอน", color:"primary", icon:"checkCircle",
               note:"การยืนยันจะเปลี่ยนผู้ครอบครองเป็นผู้ขอทันที", required:false },
    reject:  { title:"ปฏิเสธคำขอโอน", btn:"ปฏิเสธ", color:"danger", icon:"x",
               note:"ปฏิเสธแล้วจะคืนสถานะสินทรัพย์ให้ผู้ครอบครองเดิม", required:true },
    cancel:  { title:"ยกเลิกคำขอ", btn:"ยกเลิกคำขอ", color:"danger", icon:"ban",
               note:"ยกเลิกได้เฉพาะคำขอที่ยังรอดำเนินการ", required:false },
  }[mode];

  const submit = async () => {
    if (meta.required && !comment.trim()) { toast({ kind:"error", msg:"กรุณาระบุเหตุผล" }); return; }
    setBusy(true);
    try {
      if (mode === "confirm") await window.apiClient.faTransferConfirm(tenant.id, transfer.id, comment);
      if (mode === "reject")  await window.apiClient.faTransferReject(tenant.id, transfer.id, comment);
      if (mode === "cancel")  await window.apiClient.faTransferCancel(tenant.id, transfer.id, comment);
      toast({ kind:"success", msg:`${meta.title}แล้ว` });
      onDone && onDone();
      onClose && onClose();
    } catch (e) { toast({ kind:"error", msg: e.message || "ดำเนินการไม่สำเร็จ" }); }
    finally { setBusy(false); }
  };

  return (
    <Modal open={true} onClose={onClose} title={`${meta.title} · ${transfer.transfer_request_number}`} width={520}>
      <div className="space-y-3 text-[12.5px]">
        <div className="rounded-lg border border-ink-100 bg-ink-50/60 px-3 py-2">
          <div><strong>สินทรัพย์:</strong> {transfer.asset_code_snapshot} · {transfer.asset_name_snapshot}</div>
          <div className="text-ink-500 mt-0.5">เหตุผล: {transfer.transfer_reason || "—"}</div>
        </div>
        <div className="text-[11.5px] text-ink-500">{meta.note}</div>
        <Field label={`ความคิดเห็น ${meta.required ? "*" : "(ถ้ามี)"}`}>
          <Textarea rows={3} value={comment} onChange={e=>setComment(e.target.value)}/>
        </Field>
      </div>
      <div className="mt-5 flex justify-end gap-2">
        <Button variant="ghost" onClick={onClose}>ปิด</Button>
        <Button variant={meta.color} icon={meta.icon} onClick={submit} disabled={busy}>
          {busy ? "กำลังบันทึก…" : meta.btn}
        </Button>
      </div>
    </Modal>
  );
};

// ---------------------------------------------------------------------------
// EXCEL IMPORT MODAL  (uses SheetJS via CDN — lazy-loaded similar to PR module)
// ---------------------------------------------------------------------------
const loadSheetJs = async () => {
  if (window.XLSX) return window.XLSX;
  await new Promise((resolve, reject) => {
    const s = document.createElement("script");
    s.src = "https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js";
    s.onload = resolve; s.onerror = reject;
    document.head.appendChild(s);
  });
  return window.XLSX;
};
const FA_IMPORT_COLUMNS = [
  "asset_code","asset_tag_code","asset_name","asset_category","description",
  "serial_number","brand","model","purchase_date","purchase_price",
  "supplier_name","purchase_invoice_number","current_owner_email",
  "current_owner_employee_code","location","status","remark",
];

const ImportAssetsModal = ({ tenant, onClose, onDone }) => {
  const toast = useToast();
  const [file, setFile] = useState(null);
  const [rows, setRows] = useState([]);
  const [preview, setPreview] = useState(null);   // null | { valid_count, errors[] } after server-side import
  const [busy, setBusy] = useState(false);

  const downloadTemplate = async () => {
    try {
      const XLSX = await loadSheetJs();
      const ws = XLSX.utils.aoa_to_sheet([
        FA_IMPORT_COLUMNS,
        ["FA-2026-0001","TAG-001","Laptop Dell Latitude","IT","",
         "SN-12345","Dell","Latitude 5530","2026-05-01","35000",
         "Bangkok Computer","INV-2026-001","employee@example.com",
         "EMP001","สำนักงานใหญ่","active",""],
      ]);
      ws["!cols"] = FA_IMPORT_COLUMNS.map(() => ({ wch: 22 }));
      const wb = XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(wb, ws, "Assets");
      XLSX.writeFile(wb, "fa-import-template.xlsx");
    } catch (e) { toast({ kind:"error", msg: e.message || "ดาวน์โหลดไม่สำเร็จ" }); }
  };

  const onPick = async (f) => {
    if (!f) return;
    setFile(f);
    try {
      const XLSX = await loadSheetJs();
      const buf = await f.arrayBuffer();
      const wb = XLSX.read(buf, { type: "array" });
      const ws = wb.Sheets[wb.SheetNames[0]];
      const aoa = XLSX.utils.sheet_to_json(ws, { header: 1, raw: false });
      if (aoa.length === 0) { toast({ kind:"error", msg:"ไฟล์ว่าง" }); return; }
      const headers = aoa[0].map(h => String(h || "").trim());
      const data = aoa.slice(1).filter(r => r.some(c => String(c || "").trim() !== ""));
      const mapped = data.map(arr => {
        const o = {};
        headers.forEach((h, i) => { o[h] = arr[i] !== undefined ? String(arr[i]) : ""; });
        return o;
      });
      setRows(mapped);
      setPreview(null);
    } catch (e) { toast({ kind:"error", msg: e.message || "อ่านไฟล์ไม่สำเร็จ" }); }
  };

  const submit = async () => {
    if (rows.length === 0) { toast({ kind:"error", msg:"ยังไม่มีข้อมูลให้นำเข้า" }); return; }
    setBusy(true);
    try {
      const res = await window.apiClient.faAssetsBulkImport(tenant.id, {
        rows, file_name: file?.name || "fa-import.xlsx",
      });
      setPreview(res);
      toast({ kind: res.failed_count === 0 ? "success" : "info",
              msg: `นำเข้าสำเร็จ ${res.success_count}/${res.total} (ผิดพลาด ${res.failed_count})` });
      onDone && onDone();
    } catch (e) { toast({ kind:"error", msg: e.message || "นำเข้าไม่สำเร็จ" }); }
    finally { setBusy(false); }
  };

  const downloadErrors = () => {
    if (!preview?.errors?.length) return;
    const headers = ["row","asset_code","error"];
    const data = preview.errors.map(e => [e.row, e.asset_code || "", e.error]);
    window.downloadCsv(`fa-import-errors-${new Date().toISOString().slice(0,10)}.csv`, headers, data);
  };

  return (
    <Modal open={true} onClose={onClose} title="นำเข้าสินทรัพย์จากไฟล์ Excel" width={780}>
      <div className="space-y-3">
        <div className="rounded-lg border border-blue-100 bg-blue-50/50 p-3 text-[12px] text-blue-900">
          <div className="font-semibold mb-1">วิธีใช้งาน</div>
          <ol className="list-decimal pl-4 space-y-0.5">
            <li>กดปุ่ม “ดาวน์โหลดแบบฟอร์ม” แล้วกรอกข้อมูลใน Excel</li>
            <li>คอลัมน์ที่จำเป็น: <code>asset_code</code>, <code>asset_name</code></li>
            <li>ระบุผู้ครอบครองด้วย <code>current_owner_email</code> หรือ <code>current_owner_employee_code</code> (จับคู่กับ Employee Mapping)</li>
            <li>วันที่ใช้รูปแบบ <code>YYYY-MM-DD</code> · สถานะใส่ <code>active</code> หรือ <code>inactive</code></li>
            <li>ระบบจะแสดงรายงานผลพร้อมรายการ error</li>
          </ol>
        </div>
        <div className="flex items-center gap-2">
          <Button variant="secondary" icon="download" onClick={downloadTemplate}>ดาวน์โหลดแบบฟอร์ม</Button>
          <input type="file" accept=".xlsx,.xls"
            onChange={e => onPick(e.target.files?.[0])}
            className="text-[12px] file:mr-3 file:px-3 file:py-1.5 file:rounded-md file:border-0 file:bg-brand-50 file:text-brand-700 hover:file:bg-brand-100"/>
        </div>
        {rows.length > 0 && !preview && (
          <div className="text-[12px] text-ink-700">
            พบ {rows.length} แถวจากไฟล์ {file?.name}
          </div>
        )}
        {preview && (
          <div className="rounded-lg border border-ink-100 bg-ink-50/40 p-3 text-[12px]">
            <div className="flex items-center gap-3 mb-2">
              <div>ทั้งหมด: <strong>{preview.total}</strong></div>
              <div className="text-emerald-700">สำเร็จ: <strong>{preview.success_count}</strong></div>
              <div className="text-rose-700">ผิดพลาด: <strong>{preview.failed_count}</strong></div>
              {preview.failed_count > 0 && (
                <Button variant="ghost" icon="download" onClick={downloadErrors}>โหลดรายการ error</Button>
              )}
            </div>
            {(preview.errors || []).slice(0, 12).map((e, i) => (
              <div key={i} className="text-rose-700">แถว {e.row}{e.asset_code ? ` · ${e.asset_code}`:""}: {e.error}</div>
            ))}
            {(preview.errors || []).length > 12 && (
              <div className="text-ink-500 mt-1">…และอีก {preview.errors.length - 12} รายการ</div>
            )}
          </div>
        )}
      </div>
      <div className="mt-5 flex justify-end gap-2">
        <Button variant="ghost" onClick={onClose}>ปิด</Button>
        <Button variant="primary" icon="upload" onClick={submit} disabled={busy || rows.length === 0}>
          {busy ? "กำลังนำเข้า…" : `นำเข้า ${rows.length} แถว`}
        </Button>
      </div>
    </Modal>
  );
};

// ===========================================================================
// PAGE 1 — ASSET TRACKING
// ===========================================================================
const AssetTrackingPage = ({ tenant, currentUser, currentRole, users, positions, departments }) => {
  const toast = useToast();
  const [rows, setRows] = useState([]);
  const [loading, setLoading] = useState(false);
  const [q, setQ] = useState("");
  const [filterStatus, setFilterStatus] = useState("__all__");
  const [filterCategory, setFilterCategory] = useState("__all__");
  const [filterPending, setFilterPending] = useState("__all__");
  const [filterOwner, setFilterOwner] = useState("__all__");
  const [openAsset, setOpenAsset] = useState(null);
  const [transferFor, setTransferFor] = useState(null);

  const reload = async () => {
    if (!tenant?.id) return;
    setLoading(true);
    try {
      const list = await window.apiClient.faAssetsList(tenant.id);
      setRows(Array.isArray(list) ? list : []);
    } catch (e) { toast({ kind:"error", msg: e.message || "โหลดข้อมูลไม่สำเร็จ" }); }
    finally { setLoading(false); }
  };
  useEffect(() => { reload(); /* eslint-disable-next-line */ }, [tenant?.id]);

  const categories = useMemo(() => Array.from(new Set(rows.map(r => r.asset_category).filter(Boolean))).sort(), [rows]);
  const ownerOptions = useMemo(() => {
    const map = new Map();
    rows.forEach(r => { if (r.current_owner_user_id) map.set(r.current_owner_user_id, ownerName(r, users)); });
    return Array.from(map.entries()).map(([id, name]) => ({ id, name }));
  }, [rows, users]);

  const filtered = useMemo(() => {
    const ql = q.trim().toLowerCase();
    return rows.filter(r => {
      if (filterStatus !== "__all__" && r.status !== filterStatus) return false;
      if (filterCategory !== "__all__" && r.asset_category !== filterCategory) return false;
      if (filterPending === "pending" && !r.pending_transfer_id) return false;
      if (filterPending === "none" && r.pending_transfer_id) return false;
      if (filterOwner !== "__all__" && r.current_owner_user_id !== filterOwner) return false;
      if (!ql) return true;
      return (r.asset_code||"").toLowerCase().includes(ql)
          || (r.asset_tag_code||"").toLowerCase().includes(ql)
          || (r.asset_name||"").toLowerCase().includes(ql)
          || (r.asset_category||"").toLowerCase().includes(ql)
          || (r.serial_number||"").toLowerCase().includes(ql)
          || (r.location||"").toLowerCase().includes(ql)
          || ownerName(r, users).toLowerCase().includes(ql);
    });
  }, [rows, q, filterStatus, filterCategory, filterPending, filterOwner, users]);

  const kpis = useMemo(() => ({
    total: rows.length,
    active: rows.filter(r => r.status === "active").length,
    inactive: rows.filter(r => r.status === "inactive").length,
    pending: rows.filter(r => r.pending_transfer_id).length,
  }), [rows]);

  return (
    <div className="p-6 max-w-[1500px] mx-auto">
      <div className="text-[11px] tracking-wider text-amber-700 font-bold mb-1">⛬ ASSET TRACKING</div>
      <div className="flex items-start justify-between gap-3 mb-3">
        <div>
          <div className="text-[24px] font-bold text-ink-900 leading-tight">Asset Tracking</div>
          <div className="text-[13px] text-ink-500 mt-1">ภาพรวมสินทรัพย์ถาวรทั้งหมด พร้อมผู้ครอบครองปัจจุบัน</div>
        </div>
        <Button variant="secondary" icon="refresh" onClick={reload} disabled={loading}>รีเฟรช</Button>
      </div>

      <div className="grid grid-cols-4 gap-3 mb-4">
        <KpiCard tone="indigo" label="ทั้งหมด" value={kpis.total}/>
        <KpiCard tone="emerald" label="ใช้งานอยู่" value={kpis.active}/>
        <KpiCard tone="slate" label="ปิดใช้งาน" value={kpis.inactive}/>
        <KpiCard tone="amber" label="มีคำขอโอนรอ" value={kpis.pending}/>
      </div>

      <div className="rounded-xl border border-ink-100 bg-white p-3 mb-3 flex flex-wrap gap-2 items-center">
        <input value={q} onChange={e=>setQ(e.target.value)} placeholder="ค้นหา code / tag / ชื่อ / serial / location / ผู้ครอบครอง…"
          className="h-9 px-3 text-[12.5px] bg-ink-50 border border-ink-200 rounded-lg flex-1 min-w-[280px] focus:border-brand-500 ring-focus"/>
        <Select value={filterStatus} onChange={e=>setFilterStatus(e.target.value)} className="!w-36">
          <option value="__all__">ทุกสถานะ</option>
          <option value="active">Active</option>
          <option value="inactive">Inactive</option>
        </Select>
        <Select value={filterCategory} onChange={e=>setFilterCategory(e.target.value)} className="!w-44">
          <option value="__all__">ทุกหมวด</option>
          {categories.map(c => <option key={c} value={c}>{c}</option>)}
        </Select>
        <Select value={filterPending} onChange={e=>setFilterPending(e.target.value)} className="!w-44">
          <option value="__all__">ทุกการโอน</option>
          <option value="pending">มีคำขอโอนรอ</option>
          <option value="none">ไม่มีคำขอโอน</option>
        </Select>
        <Select value={filterOwner} onChange={e=>setFilterOwner(e.target.value)} className="!w-52">
          <option value="__all__">ทุกผู้ครอบครอง</option>
          {ownerOptions.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}
        </Select>
      </div>

      <div className="rounded-xl border border-ink-100 bg-white overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full text-[12.5px]">
            <thead className="bg-ink-50 text-ink-600 text-[11px] uppercase tracking-wider">
              <tr>
                <th className="px-3 py-2 text-left">Asset Code</th>
                <th className="px-3 py-2 text-left">ชื่อสินทรัพย์</th>
                <th className="px-3 py-2 text-left">Serial</th>
                <th className="px-3 py-2 text-left">ผู้ครอบครอง</th>
                <th className="px-3 py-2 text-left">Location</th>
                <th className="px-3 py-2 text-center">สถานะ</th>
                <th className="px-3 py-2 text-center">โอน</th>
                <th className="px-3 py-2 text-left">โอนล่าสุด</th>
                <th className="px-3 py-2 text-right">Action</th>
              </tr>
            </thead>
            <tbody>
              {loading && <tr><td colSpan={9} className="px-3 py-6 text-center text-ink-500">กำลังโหลด…</td></tr>}
              {!loading && filtered.length === 0 && (
                <tr><td colSpan={9} className="px-3 py-10 text-center text-ink-500">ไม่พบข้อมูล</td></tr>
              )}
              {filtered.map(r => (
                <tr key={r.id} className="border-t border-ink-100 hover:bg-ink-50/50">
                  <td className="px-3 py-2 font-mono font-semibold text-ink-900">{r.asset_code}</td>
                  <td className="px-3 py-2 text-ink-900">{r.asset_name}</td>
                  <td className="px-3 py-2 font-mono text-ink-600">{r.serial_number || "—"}</td>
                  <td className="px-3 py-2 text-ink-900">{ownerName(r, users)}</td>
                  <td className="px-3 py-2 text-ink-700">{r.location || "—"}</td>
                  <td className="px-3 py-2 text-center"><FAStatusBadge status={r.status}/></td>
                  <td className="px-3 py-2 text-center">
                    {r.pending_transfer_id
                      ? <Badge color="amber" icon="clock">รอยืนยัน</Badge>
                      : <span className="text-ink-300">—</span>}
                  </td>
                  <td className="px-3 py-2 font-mono text-ink-600">{r.last_transfer_at ? formatDate(r.last_transfer_at.slice(0,10)) : "—"}</td>
                  <td className="px-3 py-2 text-right whitespace-nowrap">
                    <Button variant="ghost" icon="eye" onClick={()=>setOpenAsset(r)}>ดู</Button>
                    {r.status === "active" && !r.pending_transfer_id && (
                      <Button variant="ghost" icon="send" onClick={()=>setTransferFor(r)}>ขอโอน</Button>
                    )}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      {openAsset && (
        <AssetDetailDrawer tenant={tenant} currentRole={currentRole} currentUser={currentUser}
          asset={openAsset} users={users} positions={positions} departments={departments}
          onClose={()=>setOpenAsset(null)}
          onChanged={reload}
          onRequestTransfer={(a)=>{ setOpenAsset(null); setTransferFor(a); }}/>
      )}
      {transferFor && (
        <CreateTransferModal tenant={tenant} assets={rows} presetAssetId={transferFor.id} users={users}
          onClose={()=>setTransferFor(null)} onCreated={reload}/>
      )}
    </div>
  );
};

// ===========================================================================
// PAGE 2 — ASSET TRANSFER REQUEST
// ===========================================================================
const AssetTransferRequestPage = ({ tenant, currentUser, currentRole, users }) => {
  const toast = useToast();
  const [transfers, setTransfers] = useState([]);
  const [assets, setAssets] = useState([]);
  const [loading, setLoading] = useState(false);
  const [tab, setTab] = useState("incoming");  // incoming | outgoing | all
  const [filterStatus, setFilterStatus] = useState("__all__");
  const [createOpen, setCreateOpen] = useState(false);
  const [actOn, setActOn] = useState(null);  // { transfer, mode }

  const reload = async () => {
    if (!tenant?.id) return;
    setLoading(true);
    try {
      const [tr, ast] = await Promise.all([
        window.apiClient.faTransfersList(tenant.id, { scope: tab === "all" ? "all" : tab }),
        window.apiClient.faAssetsList(tenant.id, { status: "active" }),
      ]);
      setTransfers(Array.isArray(tr) ? tr : []);
      setAssets(Array.isArray(ast) ? ast : []);
    } catch (e) { toast({ kind:"error", msg: e.message || "โหลดไม่สำเร็จ" }); }
    finally { setLoading(false); }
  };
  useEffect(() => { reload(); /* eslint-disable-next-line */ }, [tenant?.id, tab]);

  const filtered = useMemo(() => transfers.filter(t =>
    filterStatus === "__all__" || t.status === filterStatus
  ), [transfers, filterStatus]);

  const myUserId = currentUser?.id || currentUser?.api_user_id;
  const counts = useMemo(() => {
    const c = { pending: 0, confirmed: 0, rejected: 0, cancelled: 0 };
    transfers.forEach(t => { c[t.status] = (c[t.status] || 0) + 1; });
    return c;
  }, [transfers]);

  return (
    <div className="p-6 max-w-[1400px] mx-auto">
      <div className="text-[11px] tracking-wider text-amber-700 font-bold mb-1">↻ ASSET TRANSFER REQUEST</div>
      <div className="flex items-start justify-between gap-3 mb-3">
        <div>
          <div className="text-[24px] font-bold text-ink-900 leading-tight">Asset Transfer Request</div>
          <div className="text-[13px] text-ink-500 mt-1">ขอโอนสินทรัพย์ · ผู้ครอบครองยืนยันหรือปฏิเสธ · ระบบจะเปลี่ยนเจ้าของอัตโนมัติเมื่อยืนยัน</div>
        </div>
        <Button variant="primary" icon="plus" onClick={()=>setCreateOpen(true)}>สร้างคำขอโอน</Button>
      </div>

      <div className="grid grid-cols-4 gap-3 mb-4">
        <KpiCard tone="amber" label="รอยืนยัน" value={counts.pending || 0}/>
        <KpiCard tone="emerald" label="ยืนยันแล้ว" value={counts.confirmed || 0}/>
        <KpiCard tone="rose" label="ปฏิเสธ" value={counts.rejected || 0}/>
        <KpiCard tone="slate" label="ยกเลิก" value={counts.cancelled || 0}/>
      </div>

      <div className="flex items-center gap-1 border-b border-ink-200 mb-3 text-[12.5px]">
        {[
          { k:"incoming", label:"รอฉันยืนยัน (Incoming)" },
          { k:"outgoing", label:"คำขอของฉัน (Outgoing)" },
          { k:"all",      label:"ทั้งหมด" },
        ].map(t => (
          <button key={t.k} onClick={()=>setTab(t.k)}
            className={`px-3 h-9 -mb-px border-b-2 transition ${tab===t.k?"border-brand-600 text-brand-700 font-semibold":"border-transparent text-ink-500 hover:text-ink-800"}`}>
            {t.label}
          </button>
        ))}
        <div className="ml-auto">
          <Select value={filterStatus} onChange={e=>setFilterStatus(e.target.value)} className="!w-44">
            <option value="__all__">ทุกสถานะ</option>
            <option value="pending">รอยืนยัน</option>
            <option value="confirmed">ยืนยันแล้ว</option>
            <option value="rejected">ปฏิเสธ</option>
            <option value="cancelled">ยกเลิก</option>
          </Select>
        </div>
      </div>

      <div className="rounded-xl border border-ink-100 bg-white overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full text-[12.5px]">
            <thead className="bg-ink-50 text-ink-600 text-[11px] uppercase tracking-wider">
              <tr>
                <th className="px-3 py-2 text-left">เลขที่คำขอ</th>
                <th className="px-3 py-2 text-left">วันที่</th>
                <th className="px-3 py-2 text-left">สินทรัพย์</th>
                <th className="px-3 py-2 text-left">ผู้ครอบครองเดิม</th>
                <th className="px-3 py-2 text-left">ผู้ขอ</th>
                <th className="px-3 py-2 text-left">เหตุผล</th>
                <th className="px-3 py-2 text-center">สถานะ</th>
                <th className="px-3 py-2 text-right">Action</th>
              </tr>
            </thead>
            <tbody>
              {loading && <tr><td colSpan={8} className="px-3 py-6 text-center text-ink-500">กำลังโหลด…</td></tr>}
              {!loading && filtered.length === 0 && (
                <tr><td colSpan={8} className="px-3 py-10 text-center text-ink-500">ไม่พบข้อมูล</td></tr>
              )}
              {filtered.map(t => {
                const isIncomingForMe = t.from_owner_user_id === myUserId && t.status === "pending";
                const isMine = t.created_by_user_id === myUserId;
                return (
                  <tr key={t.id} className="border-t border-ink-100 hover:bg-ink-50/50">
                    <td className="px-3 py-2 font-mono font-semibold text-ink-900">{t.transfer_request_number}</td>
                    <td className="px-3 py-2 font-mono text-ink-600">{t.request_date}</td>
                    <td className="px-3 py-2">
                      <div className="text-ink-900">{t.asset_code_snapshot}</div>
                      <div className="text-[11px] text-ink-500 truncate max-w-[280px]">{t.asset_name_snapshot}</div>
                    </td>
                    <td className="px-3 py-2 text-ink-700">{ownerName({ current_owner_user_id: t.from_owner_user_id }, users)}</td>
                    <td className="px-3 py-2 text-ink-700">{ownerName({ current_owner_user_id: t.to_owner_user_id || t.created_by_user_id }, users)}</td>
                    <td className="px-3 py-2 text-ink-700 truncate max-w-[300px]">{t.transfer_reason || "—"}</td>
                    <td className="px-3 py-2 text-center"><FATransferBadge status={t.status}/></td>
                    <td className="px-3 py-2 text-right whitespace-nowrap">
                      {isIncomingForMe && (
                        <>
                          <Button variant="primary" icon="checkCircle" onClick={()=>setActOn({ transfer: t, mode: "confirm" })}>ยืนยัน</Button>
                          <Button variant="ghost" icon="x" onClick={()=>setActOn({ transfer: t, mode: "reject" })}>ปฏิเสธ</Button>
                        </>
                      )}
                      {isMine && t.status === "pending" && (
                        <Button variant="ghost" icon="ban" onClick={()=>setActOn({ transfer: t, mode: "cancel" })}>ยกเลิก</Button>
                      )}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>

      {createOpen && (
        <CreateTransferModal tenant={tenant} assets={assets} users={users}
          onClose={()=>setCreateOpen(false)} onCreated={reload}/>
      )}
      {actOn && (
        <ConfirmTransferModal tenant={tenant} transfer={actOn.transfer} mode={actOn.mode} users={users}
          onClose={()=>setActOn(null)} onDone={reload}/>
      )}
    </div>
  );
};

// ===========================================================================
// PAGE 3 — ASSET REGISTER
// ===========================================================================
const AssetRegisterPage = ({ tenant, currentUser, currentRole, users, positions, departments, divisions }) => {
  const toast = useToast();
  const canManage = canManageFAUi(currentRole);
  const [rows, setRows] = useState([]);
  const [loading, setLoading] = useState(false);
  const [q, setQ] = useState("");
  const [filterStatus, setFilterStatus] = useState("__all__");
  const [openAsset, setOpenAsset] = useState(null);
  const [editFor, setEditFor] = useState(null);   // null | "new" | asset row
  const [importOpen, setImportOpen] = useState(false);

  // Pending + rejected + cancelled create-requests are merged in as virtual rows
  // so the requester can see them without leaving the page.
  //   pending  → badge amber  "รออนุมัติ"  + drawer with approve/reject/cancel logic
  //   rejected → badge rose   "ปฏิเสธ"     + drawer with edit&resubmit / delete
  //   cancelled→ badge slate  "ยกเลิก"     + drawer with edit&resubmit / delete
  const [requestRows, setRequestRows] = useState([]);
  const [openPendingReq, setOpenPendingReq] = useState(null);
  const [resubmitFor, setResubmitFor] = useState(null);   // request row → opens CreateAssetModal in resubmit mode
  const reload = async () => {
    if (!tenant?.id) return;
    setLoading(true);
    try {
      const [list, pendingRes, rejectedRes, cancelledRes] = await Promise.all([
        window.apiClient.faAssetsList(tenant.id),
        window.apiClient.faCreateReqList(tenant.id, { status: 'pending' }).catch(() => []),
        window.apiClient.faCreateReqList(tenant.id, { status: 'rejected' }).catch(() => []),
        window.apiClient.faCreateReqList(tenant.id, { status: 'cancelled' }).catch(() => []),
      ]);
      setRows(Array.isArray(list) ? list : []);
      const reqs = []
        .concat(Array.isArray(pendingRes) ? pendingRes : [])
        .concat(Array.isArray(rejectedRes) ? rejectedRes : [])
        .concat(Array.isArray(cancelledRes) ? cancelledRes : []);
      setRequestRows(reqs);
    } catch (e) { toast({ kind:"error", msg: e.message || "โหลดข้อมูลไม่สำเร็จ" }); }
    finally { setLoading(false); }
  };
  useEffect(() => { reload(); /* eslint-disable-next-line */ }, [tenant?.id]);

  // Pending + rejected/cancelled requests render alongside real assets.
  // The marker `__request_status__` lets the row choose its badge + actions.
  const mergedRows = useMemo(() => {
    const reqRows = (requestRows || []).map(r => ({
      __pending__: true,
      __request_status__: r.status,
      __request__: r,
      id: r.id,
      asset_code: r.asset_code,
      asset_tag_code: r.asset_tag_code,
      asset_name: r.asset_name,
      asset_category: r.asset_category,
      serial_number: r.serial_number,
      purchase_date: r.purchase_date,
      purchase_price: r.purchase_price,
      current_owner_user_id: r.current_owner_user_id,
      status: r.status === 'pending' ? 'pending_approval'
            : r.status === 'rejected' ? 'rejected_request'
            : 'cancelled_request',
    }));
    return [...reqRows, ...rows];
  }, [rows, requestRows]);
  const pendingCount  = requestRows.filter(r => r.status === 'pending').length;
  const rejectedCount = requestRows.filter(r => r.status === 'rejected').length;

  // Sort state — 3-click cycle: desc → asc → reset (matches PR list pattern)
  const [sort, setSort] = useState({ col: null, dir: null });
  const toggleSort = (col) => {
    setSort(prev => {
      if (prev.col !== col) return { col, dir: "desc" };
      if (prev.dir === "desc") return { col, dir: "asc" };
      return { col: null, dir: null };
    });
  };
  const sortIcon = (col) => sort.col === col ? (sort.dir === "desc" ? "↓" : "↑") : "↕";

  const filtered = useMemo(() => {
    const ql = q.trim().toLowerCase();
    const list = mergedRows.filter(r => {
      if (filterStatus !== "__all__" && r.status !== filterStatus) return false;
      if (!ql) return true;
      return (r.asset_code||"").toLowerCase().includes(ql)
          || (r.asset_tag_code||"").toLowerCase().includes(ql)
          || (r.asset_name||"").toLowerCase().includes(ql)
          || (r.asset_category||"").toLowerCase().includes(ql);
    });
    if (!sort.col) return list;
    const sign = sort.dir === "asc" ? 1 : -1;
    return [...list].sort((a, b) => {
      const va = a[sort.col] || "";
      const vb = b[sort.col] || "";
      // Dates (YYYY-MM-DD) sort lexicographically; same for codes; works for empty strings (push to end)
      if (!va && !vb) return 0;
      if (!va) return 1;
      if (!vb) return -1;
      return String(va).localeCompare(String(vb)) * sign;
    });
  }, [mergedRows, q, filterStatus, sort]);

  const toggleStatus = async (r) => {
    try {
      if (r.status === "active") await window.apiClient.faAssetInactivate(tenant.id, r.id);
      else await window.apiClient.faAssetReactivate(tenant.id, r.id);
      toast({ kind:"success", msg:"เปลี่ยนสถานะแล้ว" });
      reload();
    } catch (e) { toast({ kind:"error", msg: e.message || "ดำเนินการไม่สำเร็จ" }); }
  };

  return (
    <div className="p-6 max-w-[1500px] mx-auto">
      <div className="text-[11px] tracking-wider text-amber-700 font-bold mb-1">⛬ ASSET REGISTER</div>
      <div className="flex items-start justify-between gap-3 mb-3">
        <div>
          <div className="text-[24px] font-bold text-ink-900 leading-tight">Asset Register</div>
          <div className="text-[13px] text-ink-500 mt-1">ทะเบียนหลักของสินทรัพย์ถาวร · สร้าง / แก้ไข / นำเข้าข้อมูล</div>
        </div>
        <div className="flex items-center gap-2">
          {canManage ? (
            <>
              <Button variant="secondary" icon="upload" onClick={()=>setImportOpen(true)}>นำเข้า Excel</Button>
              <Button variant="primary" icon="plus" onClick={()=>setEditFor("new")}>เพิ่มสินทรัพย์</Button>
            </>
          ) : (
            <Badge color="slate" icon="eye">🚫 อ่านอย่างเดียว</Badge>
          )}
        </div>
      </div>

      {!canManage && (
        <div className="rounded-lg border border-amber-200 bg-amber-50/60 px-3 py-2 text-[12px] text-amber-900 mb-3">
          🚫 เฉพาะผู้ดูแลระบบ — เฉพาะ FA Monitor / Admin / Super Admin เท่านั้นที่เพิ่ม / แก้ไข / นำเข้า / เปลี่ยนสถานะสินทรัพย์ได้
        </div>
      )}

      <div className="rounded-xl border border-ink-100 bg-white p-3 mb-3 flex flex-wrap gap-2 items-center">
        <input value={q} onChange={e=>setQ(e.target.value)} placeholder="ค้นหา code / tag / ชื่อ / หมวด…"
          className="h-9 px-3 text-[12.5px] bg-ink-50 border border-ink-200 rounded-lg flex-1 min-w-[280px] focus:border-brand-500 ring-focus"/>
        <Select value={filterStatus} onChange={e=>setFilterStatus(e.target.value)} className="!w-48">
          <option value="__all__">ทุกสถานะ</option>
          <option value="pending_approval">รออนุมัติ</option>
          <option value="rejected_request">ถูกปฏิเสธ</option>
          <option value="cancelled_request">ยกเลิก</option>
          <option value="active">Active</option>
          <option value="inactive">Inactive</option>
        </Select>
        <div className="text-[12px] text-ink-500">
          รวม {filtered.length} รายการ
          {pendingCount > 0 && <span className="text-amber-700 font-semibold"> · รออนุมัติ {pendingCount}</span>}
          {rejectedCount > 0 && <span className="text-rose-700 font-semibold"> · ถูกปฏิเสธ {rejectedCount}</span>}
        </div>
      </div>

      <div className="rounded-xl border border-ink-100 bg-white overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full text-[12.5px]">
            <thead className="bg-ink-50 text-ink-600 text-[11px] uppercase tracking-wider">
              <tr>
                <th className="px-3 py-2 text-left">
                  <button onClick={()=>toggleSort("asset_code")}
                    className="inline-flex items-center gap-1 hover:text-ink-900 transition cursor-pointer uppercase">
                    Asset Code <span className="text-ink-400">{sortIcon("asset_code")}</span>
                  </button>
                </th>
                <th className="px-3 py-2 text-left">ชื่อสินทรัพย์</th>
                <th className="px-3 py-2 text-left">
                  <button onClick={()=>toggleSort("asset_category")}
                    className="inline-flex items-center gap-1 hover:text-ink-900 transition cursor-pointer uppercase">
                    หมวด <span className="text-ink-400">{sortIcon("asset_category")}</span>
                  </button>
                </th>
                <th className="px-3 py-2 text-left">Serial</th>
                <th className="px-3 py-2 text-left">
                  <button onClick={()=>toggleSort("purchase_date")}
                    className="inline-flex items-center gap-1 hover:text-ink-900 transition cursor-pointer uppercase">
                    Purchase Date <span className="text-ink-400">{sortIcon("purchase_date")}</span>
                  </button>
                </th>
                <th className="px-3 py-2 text-left">ผู้ครอบครอง</th>
                <th className="px-3 py-2 text-center">สถานะ</th>
                <th className="px-3 py-2 text-right">Action</th>
              </tr>
            </thead>
            <tbody>
              {loading && <tr><td colSpan={8} className="px-3 py-6 text-center text-ink-500">กำลังโหลด…</td></tr>}
              {!loading && filtered.length === 0 && (
                <tr><td colSpan={8} className="px-3 py-10 text-center text-ink-500">ยังไม่มีสินทรัพย์ — เริ่มต้นด้วย “เพิ่มสินทรัพย์” หรือ “นำเข้า Excel”</td></tr>
              )}
              {filtered.map(r => {
                const reqStatus = r.__request_status__;
                const rowBg = reqStatus === 'pending'  ? 'bg-amber-50/40'
                            : reqStatus === 'rejected' ? 'bg-rose-50/40'
                            : reqStatus === 'cancelled'? 'bg-slate-50/40'
                            : '';
                const badge = reqStatus === 'pending'  ? <Badge color="amber" icon="clock">รออนุมัติ</Badge>
                            : reqStatus === 'rejected' ? <Badge color="rose"  icon="x">ปฏิเสธ</Badge>
                            : reqStatus === 'cancelled'? <Badge color="slate" icon="ban">ยกเลิก</Badge>
                            : <FAStatusBadge status={r.status}/>;
                const myId = currentUser?.id || currentUser?.api_user_id;
                const isMyReq = r.__pending__ && r.__request__?.created_by_user_id === myId;
                return (
                  <tr key={(r.__pending__ ? "req-" : "asset-") + r.id}
                      className={`border-t border-ink-100 hover:bg-ink-50/50 ${rowBg}`}>
                    <td className="px-3 py-2 font-mono font-semibold text-ink-900">{r.asset_code}</td>
                    <td className="px-3 py-2 text-ink-900">{r.asset_name}</td>
                    <td className="px-3 py-2 text-ink-700">{r.asset_category || "—"}</td>
                    <td className="px-3 py-2 font-mono text-ink-600">{r.serial_number || "—"}</td>
                    <td className="px-3 py-2 font-mono text-ink-600">{r.purchase_date ? formatDate(r.purchase_date) : "—"}</td>
                    <td className="px-3 py-2 text-ink-900">{ownerName(r, users)}</td>
                    <td className="px-3 py-2 text-center">{badge}</td>
                    <td className="px-3 py-2 text-right whitespace-nowrap">
                      {r.__pending__ ? (
                        <>
                          <Button variant="ghost" icon="eye" onClick={()=>setOpenPendingReq(r.__request__)}>ดูคำขอ</Button>
                          {/* For rejected/cancelled requests the requester (or admin) can edit&resubmit or delete */}
                          {(reqStatus === 'rejected' || reqStatus === 'cancelled') && (isMyReq || isTenantAdminRole(currentRole)) && (
                            <>
                              <Button variant="ghost" icon="edit" onClick={()=>setResubmitFor(r.__request__)}>แก้ไข & ส่งใหม่</Button>
                              <Button variant="ghost" icon="trash" onClick={async ()=>{
                                if (!confirm(`ลบคำขอ ${r.__request__.request_number} ?\nข้อมูลและไฟล์แนบจะถูกลบถาวร`)) return;
                                try {
                                  await window.apiClient.faCreateReqDelete(tenant.id, r.__request__.id);
                                  toast({ kind:"success", msg:"ลบคำขอแล้ว" });
                                  reload();
                                } catch (e) { toast({ kind:"error", msg: e.message || "ลบไม่สำเร็จ" }); }
                              }}>ลบ</Button>
                            </>
                          )}
                        </>
                      ) : (
                        <>
                          <Button variant="ghost" icon="eye" onClick={()=>setOpenAsset(r)}>ดู</Button>
                          {canManage && (
                            <>
                              <Button variant="ghost" icon="edit" onClick={()=>setEditFor(r)}>แก้ไข</Button>
                              <Button variant="ghost" icon={r.status === "active" ? "ban" : "check"} onClick={()=>toggleStatus(r)}>
                                {r.status === "active" ? "ปิด" : "เปิด"}
                              </Button>
                            </>
                          )}
                        </>
                      )}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>

      {openAsset && (
        <AssetDetailDrawer tenant={tenant} currentRole={currentRole} currentUser={currentUser}
          asset={openAsset} users={users} positions={positions} departments={departments}
          onClose={()=>setOpenAsset(null)} onChanged={reload}/>
      )}
      {openPendingReq && (
        <CreateRequestDetailDrawer tenant={tenant} currentRole={currentRole} currentUser={currentUser}
          request={openPendingReq} users={users}
          onClose={()=>setOpenPendingReq(null)} onChanged={reload}/>
      )}
      {editFor && (
        <CreateAssetModal tenant={tenant} currentUser={currentUser} currentRole={currentRole}
          users={users} positions={positions} departments={departments} divisions={divisions}
          initial={editFor === "new" ? null : editFor}
          onClose={()=>setEditFor(null)} onSaved={reload}/>
      )}
      {resubmitFor && (
        <CreateAssetModal tenant={tenant} currentUser={currentUser} currentRole={currentRole}
          users={users} positions={positions} departments={departments} divisions={divisions}
          resubmitOf={resubmitFor}
          onClose={()=>setResubmitFor(null)} onSaved={reload}/>
      )}
      {importOpen && (
        <ImportAssetsModal tenant={tenant} onClose={()=>setImportOpen(false)} onDone={reload}/>
      )}
    </div>
  );
};

// ===========================================================================
// PAGE 4 — FA REPORT
// ===========================================================================
const FAReportPage = ({ tenant, currentUser, currentRole, users, positions, departments }) => {
  const toast = useToast();
  const [rows, setRows] = useState([]);
  const [loading, setLoading] = useState(false);
  const [q, setQ] = useState("");
  const [filterStatus, setFilterStatus] = useState("active");
  const [filterCategory, setFilterCategory] = useState("__all__");
  const [filterOwner, setFilterOwner] = useState("__all__");
  const [filterDept, setFilterDept] = useState("__all__");
  const [filterLocation, setFilterLocation] = useState("__all__");
  const [purchaseFrom, setPurchaseFrom] = useState("");
  const [purchaseTo, setPurchaseTo] = useState("");
  const [openAsset, setOpenAsset] = useState(null);

  const reload = async () => {
    if (!tenant?.id) return;
    setLoading(true);
    try {
      const list = await window.apiClient.faAssetsList(tenant.id);
      setRows(Array.isArray(list) ? list : []);
    } catch (e) { toast({ kind:"error", msg: e.message || "โหลดข้อมูลไม่สำเร็จ" }); }
    finally { setLoading(false); }
  };
  useEffect(() => { reload(); /* eslint-disable-next-line */ }, [tenant?.id]);

  const categories = useMemo(() => Array.from(new Set(rows.map(r => r.asset_category).filter(Boolean))).sort(), [rows]);
  const locations  = useMemo(() => Array.from(new Set(rows.map(r => r.location).filter(Boolean))).sort(), [rows]);
  const ownerOptions = useMemo(() => {
    const map = new Map();
    rows.forEach(r => { if (r.current_owner_user_id) map.set(r.current_owner_user_id, ownerName(r, users)); });
    return Array.from(map.entries()).map(([id, name]) => ({ id, name }));
  }, [rows, users]);
  const deptOptions = useMemo(() => departments || [], [departments]);

  const filtered = useMemo(() => {
    const ql = q.trim().toLowerCase();
    return rows.filter(r => {
      if (filterStatus !== "__all__" && r.status !== filterStatus) return false;
      if (filterCategory !== "__all__" && r.asset_category !== filterCategory) return false;
      if (filterOwner !== "__all__" && r.current_owner_user_id !== filterOwner) return false;
      if (filterLocation !== "__all__" && r.location !== filterLocation) return false;
      if (filterDept !== "__all__") {
        const dlabel = ownerDepartmentLabel(r, users, positions, departments);
        if (!dlabel.includes((departments.find(d => d.id === filterDept) || {}).name || "__none__")) return false;
      }
      if (purchaseFrom && r.purchase_date && r.purchase_date < purchaseFrom) return false;
      if (purchaseTo && r.purchase_date && r.purchase_date > purchaseTo) return false;
      if (!ql) return true;
      return (r.asset_code||"").toLowerCase().includes(ql)
          || (r.asset_tag_code||"").toLowerCase().includes(ql)
          || (r.asset_name||"").toLowerCase().includes(ql)
          || ownerName(r, users).toLowerCase().includes(ql);
    });
  }, [rows, q, filterStatus, filterCategory, filterOwner, filterDept, filterLocation, purchaseFrom, purchaseTo, users, positions, departments]);

  const exportExcel = () => {
    const headers = [
      "Asset Code","Tag Code","Asset Name","Category","Serial",
      "Owner","Position","Department","Location","Status",
      "Last Transfer","Purchase Date","Purchase Price","Updated",
    ];
    const data = filtered.map(r => [
      r.asset_code, r.asset_tag_code || "", r.asset_name, r.asset_category || "", r.serial_number || "",
      ownerName(r, users), ownerPositionLabel(r, users, positions), ownerDepartmentLabel(r, users, positions, departments),
      r.location || "", r.status,
      r.last_transfer_at ? r.last_transfer_at.slice(0, 10) : "",
      r.purchase_date || "", r.purchase_price ?? "",
      r.updated_at ? r.updated_at.slice(0, 10) : "",
    ]);
    window.downloadCsv(`fa-report-${new Date().toISOString().slice(0,10)}.csv`, headers, data);
    toast({ kind:"success", msg:"ส่งออก Excel แล้ว" });
  };

  return (
    <div className="p-6 max-w-[1500px] mx-auto">
      <div className="text-[11px] tracking-wider text-amber-700 font-bold mb-1">▦ FA REPORT</div>
      <div className="flex items-start justify-between gap-3 mb-3">
        <div>
          <div className="text-[24px] font-bold text-ink-900 leading-tight">FA Report — Current Asset by Owner</div>
          <div className="text-[13px] text-ink-500 mt-1">รายงานสินทรัพย์ปัจจุบันและผู้ครอบครอง · กรองและส่งออก Excel</div>
        </div>
        <div className="flex items-center gap-2">
          <Button variant="secondary" icon="refresh" onClick={reload} disabled={loading}>รีเฟรช</Button>
          <Button variant="primary" icon="fileBarChart" onClick={exportExcel}>ส่งออก Excel</Button>
        </div>
      </div>

      <div className="rounded-xl border border-ink-100 bg-white p-3 mb-3 grid grid-cols-4 gap-2">
        <input value={q} onChange={e=>setQ(e.target.value)} placeholder="ค้นหา…"
          className="col-span-2 h-9 px-3 text-[12.5px] bg-ink-50 border border-ink-200 rounded-lg focus:border-brand-500 ring-focus"/>
        <Select value={filterStatus} onChange={e=>setFilterStatus(e.target.value)}>
          <option value="__all__">ทุกสถานะ</option>
          <option value="active">Active</option>
          <option value="inactive">Inactive</option>
        </Select>
        <Select value={filterCategory} onChange={e=>setFilterCategory(e.target.value)}>
          <option value="__all__">ทุกหมวด</option>
          {categories.map(c => <option key={c} value={c}>{c}</option>)}
        </Select>
        <Select value={filterOwner} onChange={e=>setFilterOwner(e.target.value)}>
          <option value="__all__">ทุกผู้ครอบครอง</option>
          {ownerOptions.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}
        </Select>
        <Select value={filterDept} onChange={e=>setFilterDept(e.target.value)}>
          <option value="__all__">ทุกหน่วยงาน</option>
          {deptOptions.map(d => <option key={d.id} value={d.id}>{d.name}</option>)}
        </Select>
        <Select value={filterLocation} onChange={e=>setFilterLocation(e.target.value)}>
          <option value="__all__">ทุก Location</option>
          {locations.map(l => <option key={l} value={l}>{l}</option>)}
        </Select>
        <div className="col-span-1 flex items-center gap-1">
          {window.ThaiDateInput
            ? <window.ThaiDateInput value={purchaseFrom} onChange={(v)=>setPurchaseFrom(v)}/>
            : <Input type="date" value={purchaseFrom} onChange={e=>setPurchaseFrom(e.target.value)} placeholder="ตั้งแต่"/>}
        </div>
        <div className="col-span-1 flex items-center gap-1">
          {window.ThaiDateInput
            ? <window.ThaiDateInput value={purchaseTo} onChange={(v)=>setPurchaseTo(v)}/>
            : <Input type="date" value={purchaseTo} onChange={e=>setPurchaseTo(e.target.value)} placeholder="ถึง"/>}
        </div>
      </div>

      <div className="rounded-xl border border-ink-100 bg-white overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full text-[12.5px]">
            <thead className="bg-ink-50 text-ink-600 text-[11px] uppercase tracking-wider">
              <tr>
                <th className="px-3 py-2 text-left">Asset Code</th>
                <th className="px-3 py-2 text-left">Tag</th>
                <th className="px-3 py-2 text-left">ชื่อ</th>
                <th className="px-3 py-2 text-left">หมวด</th>
                <th className="px-3 py-2 text-left">Serial</th>
                <th className="px-3 py-2 text-left">ผู้ครอบครอง</th>
                <th className="px-3 py-2 text-left">ตำแหน่ง</th>
                <th className="px-3 py-2 text-left">หน่วยงาน</th>
                <th className="px-3 py-2 text-left">Location</th>
                <th className="px-3 py-2 text-center">สถานะ</th>
                <th className="px-3 py-2 text-left">โอนล่าสุด</th>
                <th className="px-3 py-2 text-left">Purchase Date</th>
                <th className="px-3 py-2 text-right">ราคา</th>
                <th className="px-3 py-2 text-right">Action</th>
              </tr>
            </thead>
            <tbody>
              {loading && <tr><td colSpan={14} className="px-3 py-6 text-center text-ink-500">กำลังโหลด…</td></tr>}
              {!loading && filtered.length === 0 && (
                <tr><td colSpan={14} className="px-3 py-10 text-center text-ink-500">ไม่พบข้อมูลตามตัวกรอง</td></tr>
              )}
              {filtered.map(r => (
                <tr key={r.id} className="border-t border-ink-100 hover:bg-ink-50/50">
                  <td className="px-3 py-2 font-mono font-semibold text-ink-900">{r.asset_code}</td>
                  <td className="px-3 py-2 font-mono text-ink-600">{r.asset_tag_code || "—"}</td>
                  <td className="px-3 py-2 text-ink-900">{r.asset_name}</td>
                  <td className="px-3 py-2 text-ink-700">{r.asset_category || "—"}</td>
                  <td className="px-3 py-2 font-mono text-ink-600">{r.serial_number || "—"}</td>
                  <td className="px-3 py-2 text-ink-900">{ownerName(r, users)}</td>
                  <td className="px-3 py-2 text-ink-700">{ownerPositionLabel(r, users, positions)}</td>
                  <td className="px-3 py-2 text-ink-700">{ownerDepartmentLabel(r, users, positions, departments)}</td>
                  <td className="px-3 py-2 text-ink-700">{r.location || "—"}</td>
                  <td className="px-3 py-2 text-center"><FAStatusBadge status={r.status}/></td>
                  <td className="px-3 py-2 font-mono text-ink-600">{r.last_transfer_at ? formatDate(r.last_transfer_at.slice(0,10)) : "—"}</td>
                  <td className="px-3 py-2 font-mono text-ink-600">{r.purchase_date ? formatDate(r.purchase_date) : "—"}</td>
                  <td className="px-3 py-2 text-right font-mono">{r.purchase_price !== null && isFinite(r.purchase_price) ? formatMoney(r.purchase_price) : "—"}</td>
                  <td className="px-3 py-2 text-right whitespace-nowrap">
                    <Button variant="ghost" icon="eye" onClick={()=>setOpenAsset(r)}>ดู</Button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      {openAsset && (
        <AssetDetailDrawer tenant={tenant} currentRole={currentRole} currentUser={currentUser}
          asset={openAsset} users={users} positions={positions} departments={departments}
          onClose={()=>setOpenAsset(null)} onChanged={reload}/>
      )}
    </div>
  );
};

// ===========================================================================
// CREATE-REQUEST DETAIL DRAWER  (for approver to inspect before approving)
// ===========================================================================
const CreateRequestDetailDrawer = ({ tenant, currentRole, currentUser, request, users, onClose, onChanged }) => {
  const toast = useToast();
  const [detail, setDetail] = useState(request);
  const [loading, setLoading] = useState(false);
  const [act, setAct] = useState(null);  // null | 'approve' | 'reject' | 'cancel'
  const [comment, setComment] = useState("");
  const [busy, setBusy] = useState(false);
  const isApprover = request.approver_user_id === (window.apiClient.getMyUserId ? window.apiClient.getMyUserId() : null);

  const reload = async () => {
    if (!request?.id) return;
    setLoading(true);
    try {
      const d = await window.apiClient.faCreateReqGet(tenant.id, request.id);
      setDetail(d);
    } catch (e) { toast({ kind:"error", msg: e.message || "โหลดไม่สำเร็จ" }); }
    finally { setLoading(false); }
  };
  useEffect(() => { reload(); /* eslint-disable-next-line */ }, [request?.id]);

  const downloadAtt = async (att) => {
    try {
      const blob = await window.apiClient.faCreateReqDownloadAttachmentBlob(tenant.id, request.id, att.id);
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url; a.download = att.filename;
      document.body.appendChild(a); a.click(); a.remove();
      setTimeout(() => URL.revokeObjectURL(url), 1000);
    } catch (e) { toast({ kind:"error", msg: e.message || "ดาวน์โหลดไม่สำเร็จ" }); }
  };
  // Inline preview — fetch blob (auth-headered) then open in modal
  const [preview, setPreview] = useState(null);
  const previewAtt = async (att) => {
    try {
      const blob = await window.apiClient.faCreateReqDownloadAttachmentBlob(tenant.id, request.id, att.id);
      const url = URL.createObjectURL(blob);
      setPreview({ url, contentType: att.content_type || blob.type, filename: att.filename, att });
    } catch (e) { toast({ kind:"error", msg: e.message || "เปิดดูไม่สำเร็จ" }); }
  };
  const closePreview = () => {
    if (preview?.url) { try { URL.revokeObjectURL(preview.url); } catch {} }
    setPreview(null);
  };

  // Generic action runner. Approve uses this directly (1-click); reject/cancel
  // go through the comment-prompt step first then call this on confirm.
  const runAct = async (actType, commentValue) => {
    if (actType === "reject" && !(commentValue || "").trim()) {
      toast({ kind:"error", msg:"กรุณาระบุเหตุผลในการปฏิเสธ" }); return;
    }
    setBusy(true);
    try {
      if (actType === "approve") await window.apiClient.faCreateReqApprove(tenant.id, request.id, commentValue || "");
      if (actType === "reject")  await window.apiClient.faCreateReqReject(tenant.id, request.id, commentValue || "");
      if (actType === "cancel")  await window.apiClient.faCreateReqCancel(tenant.id, request.id, commentValue || "");
      toast({ kind:"success", msg: actType === "approve" ? "อนุมัติคำขอแล้ว · สินทรัพย์ถูกสร้างเรียบร้อย" : "ดำเนินการแล้ว" });
      onChanged && onChanged();
      onClose && onClose();
    } catch (e) { toast({ kind:"error", msg: e.message || "ดำเนินการไม่สำเร็จ" }); }
    finally { setBusy(false); }
  };
  // Kept for the comment-prompt step (reject / cancel)
  const submitAct = () => runAct(act, comment);

  if (!detail) return null;

  return (
    <Drawer open={true} onClose={onClose}
      title={`คำขอเพิ่มสินทรัพย์ ${detail.request_number}`}
      subtitle={`${detail.asset_code} · ${detail.asset_name}`}
      width={640}>
      <div className="flex items-center gap-2 mb-3">
        <Badge color={
          detail.status === "pending" ? "amber" :
          detail.status === "approved" ? "emerald" :
          detail.status === "rejected" ? "rose" : "slate"
        } icon={
          detail.status === "pending" ? "clock" :
          detail.status === "approved" ? "checkCircle" :
          detail.status === "rejected" ? "x" : "ban"
        }>
          {detail.status === "pending" ? "รออนุมัติ" :
           detail.status === "approved" ? "อนุมัติแล้ว" :
           detail.status === "rejected" ? "ปฏิเสธ" : "ยกเลิก"}
        </Badge>
        <div className="ml-auto text-[11px] text-ink-500">{formatDateTime(detail.created_at)}</div>
      </div>

      <div className="grid grid-cols-2 gap-3 text-[12.5px] mb-3">
        <KV label="Asset Code" value={detail.asset_code}/>
        <KV label="Asset Tag Code" value={detail.asset_tag_code || "—"}/>
        <KV label="ชื่อ" value={detail.asset_name}/>
        <KV label="หมวด" value={detail.asset_category || "—"}/>
        <KV label="Serial" value={detail.serial_number || "—"}/>
        <KV label="Brand / Model" value={[detail.brand, detail.model].filter(Boolean).join(" / ") || "—"}/>
        <KV label="Purchase Date" value={detail.purchase_date ? formatDate(detail.purchase_date) : "—"}/>
        <KV label="Purchase Price" value={detail.purchase_price !== null && isFinite(detail.purchase_price) ? formatMoney(detail.purchase_price) : "—"}/>
        <KV label="ผู้ครอบครองที่จะกำหนด" value={ownerName({ current_owner_user_id: detail.current_owner_user_id }, users)}/>
        <KV label="Location" value={detail.location || "—"}/>
        <KV label="ผู้ขอ" value={ownerName({ current_owner_user_id: detail.created_by_user_id }, users)}/>
        <KV label="ผู้อนุมัติ" value={ownerName({ current_owner_user_id: detail.approver_user_id }, users)}/>
        {(detail.description || detail.remark) && (
          <div className="col-span-2 rounded-lg border border-ink-100 bg-ink-50/60 p-3">
            <div className="text-[10.5px] uppercase tracking-wider text-ink-500 font-semibold mb-1">รายละเอียด / หมายเหตุ</div>
            <div className="whitespace-pre-wrap">{detail.description || detail.remark}</div>
          </div>
        )}
        {detail.requester_comment && (
          <div className="col-span-2 rounded-lg border border-blue-100 bg-blue-50/50 p-3 text-blue-900">
            <div className="text-[10.5px] uppercase tracking-wider text-blue-700 font-semibold mb-1">ความคิดเห็นจากผู้ขอ</div>
            <div className="whitespace-pre-wrap">{detail.requester_comment}</div>
          </div>
        )}
        {detail.approver_comment && (
          <div className="col-span-2 rounded-lg border border-amber-200 bg-amber-50/50 p-3 text-amber-900">
            <div className="text-[10.5px] uppercase tracking-wider text-amber-700 font-semibold mb-1">ความคิดเห็นจากผู้อนุมัติ</div>
            <div className="whitespace-pre-wrap">{detail.approver_comment}</div>
          </div>
        )}
      </div>

      <div className="text-[11px] uppercase tracking-wider text-ink-500 font-semibold mb-1.5">ไฟล์แนบ</div>
      {(detail.attachments || []).length === 0 ? (
        <EmptyHint icon="paperclip" text="ไม่มีไฟล์แนบ"/>
      ) : (detail.attachments).map(att => (
        <div key={att.id} className="flex items-center gap-3 px-3 py-2 mb-1.5 rounded-lg border border-ink-100 bg-white">
          <Icon name="paperclip" size={14} className="text-ink-500"/>
          <div className="flex-1 min-w-0">
            <div className="text-[12.5px] text-ink-900 truncate">{att.filename}</div>
            <div className="text-[10.5px] text-ink-500">
              {(FA_ATT_TYPES.find(t => t.code === att.attachment_type)?.label) || att.attachment_type}
              {" · "}{formatBytes(att.file_size || 0)}
            </div>
          </div>
          <Button variant="ghost" icon="eye" onClick={()=>previewAtt(att)}>ดูตัวอย่าง</Button>
          <Button variant="ghost" icon="download" onClick={()=>downloadAtt(att)}>โหลด</Button>
        </div>
      ))}

      {/* Action footer */}
      {(detail.status === "rejected" || detail.status === "cancelled") && (() => {
        const myId = currentUser?.id || currentUser?.api_user_id;
        const isOwnRequest = myId && detail.created_by_user_id === myId;
        if (!isOwnRequest) return null;
        return (
          <div className="mt-4 border-t border-ink-100 pt-3 flex items-center gap-2 justify-end">
            <span className="mr-auto text-[11.5px] text-ink-500">
              ℹ คำขอนี้{detail.status === "rejected" ? "ถูกปฏิเสธ" : "ถูกยกเลิก"} — แก้ไขแล้วส่งใหม่ หรือ ลบทิ้ง
            </span>
            <Button variant="ghost" icon="trash" onClick={async ()=>{
              if (!confirm(`ลบคำขอ ${detail.request_number} ?\nข้อมูลและไฟล์แนบจะถูกลบถาวร`)) return;
              try {
                await window.apiClient.faCreateReqDelete(tenant.id, detail.id);
                toast({ kind:"success", msg:"ลบคำขอแล้ว" });
                onChanged && onChanged();
                onClose && onClose();
              } catch (e) { toast({ kind:"error", msg: e.message || "ลบไม่สำเร็จ" }); }
            }}>ลบรายการ</Button>
            <Button variant="primary" icon="edit" onClick={()=>{
              // Hand off to the requester's page; they'll see the resubmit modal via setResubmitFor.
              // Here in the drawer we just close — the caller can listen to onChanged → re-open via row.
              onClose && onClose();
              toast({ kind:"info", msg:"เปิดหน้า Asset Register แล้วกด \"แก้ไข & ส่งใหม่\" ในแถวที่ปฏิเสธ" });
            }}>แก้ไข & ส่งใหม่</Button>
          </div>
        );
      })()}
      {detail.status === "pending" && (
        <div className="mt-4 border-t border-ink-100 pt-3">
          {act ? (
            <div className="space-y-2">
              <Field label={`ความคิดเห็น ${act === "reject" ? "*" : "(ถ้ามี)"}`}>
                <Textarea rows={3} value={comment} onChange={e=>setComment(e.target.value)}/>
              </Field>
              <div className="flex justify-end gap-2">
                <Button variant="ghost" onClick={()=>{ setAct(null); setComment(""); }}>ยกเลิก</Button>
                <Button variant={act === "approve" ? "primary" : "danger"}
                  icon={act === "approve" ? "checkCircle" : act === "reject" ? "x" : "ban"}
                  onClick={submitAct} disabled={busy}>
                  {busy ? "กำลังบันทึก…" :
                   act === "approve" ? "ยืนยันอนุมัติ" :
                   act === "reject" ? "ยืนยันปฏิเสธ" : "ยืนยันยกเลิก"}
                </Button>
              </div>
            </div>
          ) : (() => {
            const myId = currentUser?.id || currentUser?.api_user_id;
            const isOwnRequest = myId && detail.created_by_user_id === myId;
            return (
              <div className="flex items-center gap-2 justify-end">
                {isOwnRequest ? (
                  <>
                    <span className="mr-auto text-[11.5px] text-ink-500">
                      ℹ คุณเป็นผู้สร้างคำขอนี้ — ยกเลิกได้ แต่อนุมัติ/ปฏิเสธไม่ได้
                    </span>
                    <Button variant="ghost" icon="ban" onClick={()=>setAct("cancel")}>ยกเลิกคำขอ</Button>
                  </>
                ) : (
                  <>
                    <Button variant="ghost" icon="x" onClick={()=>setAct("reject")} disabled={busy}>ปฏิเสธ</Button>
                    <Button variant="primary" icon="checkCircle" onClick={()=>runAct("approve", "")} disabled={busy}>
                      {busy ? "กำลังอนุมัติ…" : "อนุมัติ"}
                    </Button>
                  </>
                )}
              </div>
            );
          })()}
        </div>
      )}

      <FAFilePreviewModal preview={preview} onClose={closePreview}
        onDownload={() => { if (preview?.att) downloadAtt(preview.att); }}/>
    </Drawer>
  );
};

// ===========================================================================
// PAGE 5 — MY FA APPROVAL  (combines pending create-requests + pending transfers)
// ===========================================================================
const MyFAApprovalPage = ({ tenant, currentUser, currentRole, users, positions, departments }) => {
  const toast = useToast();
  const [createReqs, setCreateReqs] = useState([]);
  const [transfers, setTransfers] = useState([]);
  const [loading, setLoading] = useState(false);
  const [filterStatus, setFilterStatus] = useState("pending");
  const [openCreateReq, setOpenCreateReq] = useState(null);
  const [actTransfer, setActTransfer] = useState(null);   // { transfer, mode }
  const myUserId = currentUser?.id || currentUser?.api_user_id;

  const reload = async () => {
    if (!tenant?.id) return;
    setLoading(true);
    try {
      const [crs, trs] = await Promise.all([
        window.apiClient.faCreateReqList(tenant.id, { scope: "approver", status: filterStatus === "__all__" ? "" : filterStatus }),
        window.apiClient.faTransfersList(tenant.id, { scope: "incoming",  status: filterStatus === "__all__" ? "" : filterStatus }),
      ]);
      setCreateReqs(Array.isArray(crs) ? crs : []);
      setTransfers(Array.isArray(trs) ? trs : []);
    } catch (e) { toast({ kind:"error", msg: e.message || "โหลดไม่สำเร็จ" }); }
    finally { setLoading(false); }
  };
  useEffect(() => { reload(); /* eslint-disable-next-line */ }, [tenant?.id, filterStatus]);

  const pendingCreateCount = createReqs.filter(r => r.status === "pending").length;
  const pendingTransferCount = transfers.filter(t => t.status === "pending").length;

  return (
    <div className="p-6 max-w-[1400px] mx-auto">
      <div className="text-[11px] tracking-wider text-amber-700 font-bold mb-1">✓ MY FA APPROVAL</div>
      <div className="flex items-start justify-between gap-3 mb-3">
        <div>
          <div className="text-[24px] font-bold text-ink-900 leading-tight">My FA Approval</div>
          <div className="text-[13px] text-ink-500 mt-1">รวมงานที่รออนุมัติ — ทั้งคำขอเพิ่มสินทรัพย์ใหม่ และคำขอโอนสินทรัพย์ที่คุณเป็นผู้ครอบครอง</div>
        </div>
        <div className="flex items-center gap-2">
          <Select value={filterStatus} onChange={e=>setFilterStatus(e.target.value)} className="!w-44">
            <option value="pending">เฉพาะรอดำเนินการ</option>
            <option value="__all__">ทุกสถานะ</option>
            <option value="approved">อนุมัติแล้ว</option>
            <option value="confirmed">โอนสำเร็จ</option>
            <option value="rejected">ปฏิเสธ</option>
            <option value="cancelled">ยกเลิก</option>
          </Select>
          <Button variant="secondary" icon="refresh" onClick={reload} disabled={loading}>รีเฟรช</Button>
        </div>
      </div>

      <div className="grid grid-cols-2 gap-3 mb-4">
        <KpiCard tone="amber" label="คำขอเพิ่มสินทรัพย์รออนุมัติ" value={pendingCreateCount}/>
        <KpiCard tone="amber" label="คำขอโอนสินทรัพย์รอยืนยัน" value={pendingTransferCount}/>
      </div>

      {/* SECTION 1 — Create-requests */}
      <div className="rounded-xl border border-ink-100 bg-white overflow-hidden mb-4">
        <div className="px-4 py-2.5 border-b border-ink-100 flex items-center gap-2">
          <Icon name="package" size={14} className="text-amber-700"/>
          <div className="text-[13px] font-semibold text-ink-900">คำขอเพิ่มสินทรัพย์ใหม่ (Create Asset Requests)</div>
          <span className="text-[11px] text-ink-500">— ที่คุณเป็นผู้อนุมัติ</span>
          <span className="ml-auto text-[11px] text-ink-500">{createReqs.length} รายการ</span>
        </div>
        <div className="overflow-x-auto">
          <table className="w-full text-[12.5px]">
            <thead className="bg-ink-50 text-ink-600 text-[11px] uppercase tracking-wider">
              <tr>
                <th className="px-3 py-2 text-left">เลขที่คำขอ</th>
                <th className="px-3 py-2 text-left">วันที่</th>
                <th className="px-3 py-2 text-left">Asset Code</th>
                <th className="px-3 py-2 text-left">ชื่อ</th>
                <th className="px-3 py-2 text-left">ผู้ขอ</th>
                <th className="px-3 py-2 text-center">ไฟล์แนบ</th>
                <th className="px-3 py-2 text-center">สถานะ</th>
                <th className="px-3 py-2 text-right">Action</th>
              </tr>
            </thead>
            <tbody>
              {loading && <tr><td colSpan={8} className="px-3 py-6 text-center text-ink-500">กำลังโหลด…</td></tr>}
              {!loading && createReqs.length === 0 && (
                <tr><td colSpan={8} className="px-3 py-8 text-center text-ink-500">ไม่มีคำขอ</td></tr>
              )}
              {createReqs.map(r => (
                <tr key={r.id} className="border-t border-ink-100 hover:bg-ink-50/50">
                  <td className="px-3 py-2 font-mono font-semibold text-ink-900">{r.request_number}</td>
                  <td className="px-3 py-2 font-mono text-ink-600">{r.created_at?.slice(0,10)}</td>
                  <td className="px-3 py-2 font-mono text-ink-700">{r.asset_code}</td>
                  <td className="px-3 py-2 text-ink-900 truncate max-w-[280px]">{r.asset_name}</td>
                  <td className="px-3 py-2 text-ink-700">{ownerName({ current_owner_user_id: r.created_by_user_id }, users)}</td>
                  <td className="px-3 py-2 text-center text-ink-600">{r.attachment_count || 0}</td>
                  <td className="px-3 py-2 text-center">
                    <Badge color={
                      r.status === "pending" ? "amber" :
                      r.status === "approved" ? "emerald" :
                      r.status === "rejected" ? "rose" : "slate"
                    }>
                      {r.status === "pending" ? "รออนุมัติ" :
                       r.status === "approved" ? "อนุมัติแล้ว" :
                       r.status === "rejected" ? "ปฏิเสธ" : "ยกเลิก"}
                    </Badge>
                  </td>
                  <td className="px-3 py-2 text-right">
                    <Button variant={r.status === "pending" ? "primary" : "ghost"} icon="eye" onClick={()=>setOpenCreateReq(r)}>
                      {r.status === "pending" ? "ตรวจ / อนุมัติ" : "ดู"}
                    </Button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      {/* SECTION 2 — Incoming transfer requests */}
      <div className="rounded-xl border border-ink-100 bg-white overflow-hidden">
        <div className="px-4 py-2.5 border-b border-ink-100 flex items-center gap-2">
          <Icon name="send" size={14} className="text-amber-700"/>
          <div className="text-[13px] font-semibold text-ink-900">คำขอโอนสินทรัพย์ (Transfer Requests)</div>
          <span className="text-[11px] text-ink-500">— ที่คุณเป็นผู้ครอบครองปัจจุบัน</span>
          <span className="ml-auto text-[11px] text-ink-500">{transfers.length} รายการ</span>
        </div>
        <div className="overflow-x-auto">
          <table className="w-full text-[12.5px]">
            <thead className="bg-ink-50 text-ink-600 text-[11px] uppercase tracking-wider">
              <tr>
                <th className="px-3 py-2 text-left">เลขที่คำขอ</th>
                <th className="px-3 py-2 text-left">วันที่</th>
                <th className="px-3 py-2 text-left">สินทรัพย์</th>
                <th className="px-3 py-2 text-left">ผู้ขอ</th>
                <th className="px-3 py-2 text-left">เหตุผล</th>
                <th className="px-3 py-2 text-center">สถานะ</th>
                <th className="px-3 py-2 text-right">Action</th>
              </tr>
            </thead>
            <tbody>
              {loading && <tr><td colSpan={7} className="px-3 py-6 text-center text-ink-500">กำลังโหลด…</td></tr>}
              {!loading && transfers.length === 0 && (
                <tr><td colSpan={7} className="px-3 py-8 text-center text-ink-500">ไม่มีคำขอโอน</td></tr>
              )}
              {transfers.map(t => (
                <tr key={t.id} className="border-t border-ink-100 hover:bg-ink-50/50">
                  <td className="px-3 py-2 font-mono font-semibold text-ink-900">{t.transfer_request_number}</td>
                  <td className="px-3 py-2 font-mono text-ink-600">{t.request_date}</td>
                  <td className="px-3 py-2">
                    <div className="text-ink-900">{t.asset_code_snapshot}</div>
                    <div className="text-[11px] text-ink-500 truncate max-w-[260px]">{t.asset_name_snapshot}</div>
                  </td>
                  <td className="px-3 py-2 text-ink-700">{ownerName({ current_owner_user_id: t.to_owner_user_id || t.created_by_user_id }, users)}</td>
                  <td className="px-3 py-2 text-ink-700 truncate max-w-[260px]">{t.transfer_reason || "—"}</td>
                  <td className="px-3 py-2 text-center"><FATransferBadge status={t.status}/></td>
                  <td className="px-3 py-2 text-right whitespace-nowrap">
                    {t.status === "pending" ? (
                      <>
                        <Button variant="primary" icon="checkCircle" onClick={()=>setActTransfer({ transfer: t, mode: "confirm" })}>ยืนยัน</Button>
                        <Button variant="ghost" icon="x" onClick={()=>setActTransfer({ transfer: t, mode: "reject" })}>ปฏิเสธ</Button>
                      </>
                    ) : <span className="text-ink-400">—</span>}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      {openCreateReq && (
        <CreateRequestDetailDrawer tenant={tenant} currentRole={currentRole} currentUser={currentUser}
          request={openCreateReq} users={users}
          onClose={()=>setOpenCreateReq(null)} onChanged={reload}/>
      )}
      {actTransfer && (
        <ConfirmTransferModal tenant={tenant} transfer={actTransfer.transfer} mode={actTransfer.mode} users={users}
          onClose={()=>setActTransfer(null)} onDone={reload}/>
      )}
    </div>
  );
};

// ---------------------------------------------------------------------------
// Expose page components on window — workspace.jsx renders by name
// ---------------------------------------------------------------------------
Object.assign(window, {
  AssetTrackingPage, AssetTransferRequestPage, AssetRegisterPage, FAReportPage,
  MyFAApprovalPage,
  // Shared preview modal (used by suppliers drawer too)
  FAFilePreviewModal,
});
