// acquisition-docs.jsx — Checklist configurável, workflow e UI compartilhada (Aquisições + Contratos)
window.NA = window.NA || {};
const { useState: useStateD, useMemo: useMemoD, useCallback: useCallbackD, useRef: useRefD } = React;

const ACQ_DOC_TYPES = {
  proc: { labelPt: "Procuração", labelEn: "Power of attorney", icon: "file-signature" },
  compra: { labelPt: "Contrato de compra", labelEn: "Purchase contract", icon: "file-text" },
  venda: { labelPt: "Contrato de venda", labelEn: "Sale contract", icon: "file-output" },
  fin: { labelPt: "Contrato de financ.", labelEn: "Financing contract", icon: "credit-card" },
  crlv: { labelPt: "CRLV", labelEn: "CRLV", icon: "id-card" },
  rg_cpf: { labelPt: "RG e CPF", labelEn: "ID documents", icon: "user" },
  comp_res: { labelPt: "Comprovante residência", labelEn: "Proof of address", icon: "home" },
  fatura_banco: { labelPt: "Fatura do banco", labelEn: "Bank statement", icon: "receipt" },
  doc_embarcacao: { labelPt: "Documento embarcação", labelEn: "Vessel registration", icon: "anchor" },
};

const DOC_STATUS_ORDER = ["pending", "uploaded", "signed", "archived"];

const DOC_STATUS_META = {
  pending: { kind: "default", labelPt: "Pendente", labelEn: "Pending" },
  uploaded: { kind: "processing", labelPt: "Enviado", labelEn: "Sent" },
  signed: { kind: "success", labelPt: "Assinado", labelEn: "Signed" },
  archived: { kind: "info", labelPt: "Arquivado", labelEn: "Archived" },
};

const ACQ_STATUS_LABELS = {
  pt: {
    in_process: "Em processo", in_settlement: "Em quitação", overdue: "Em atraso",
    in_stock: "Em estoque", settled: "Quitado", sold: "Vendido",
  },
  en: {
    in_process: "In process", in_settlement: "Settling", overdue: "Overdue",
    in_stock: "In stock", settled: "Settled", sold: "Sold",
  },
};

/** Checklist por tipo de veículo — docs obrigatórios e gates de status */
const ACQ_DOC_CHECKLIST_BY_VEH_TYPE = {
  car: {
    all: ["proc", "compra", "crlv", "rg_cpf", "comp_res", "fin", "venda", "fatura_banco"],
    required: ["proc", "compra", "crlv", "rg_cpf", "comp_res"],
    gates: {
      in_settlement: { docs: ["proc"], minStatus: "uploaded" },
      in_stock: { docs: ["proc", "compra"], minStatus: "signed" },
      settled: { docs: ["proc", "compra"], minStatus: "signed" },
      sold: { docs: ["proc", "compra", "venda"], minStatus: "signed" },
    },
  },
  moto: {
    all: ["proc", "compra", "crlv", "rg_cpf", "comp_res", "fin", "venda", "fatura_banco"],
    required: ["proc", "compra", "crlv", "rg_cpf", "comp_res"],
    gates: {
      in_settlement: { docs: ["proc"], minStatus: "uploaded" },
      in_stock: { docs: ["proc", "compra"], minStatus: "signed" },
      settled: { docs: ["proc", "compra"], minStatus: "signed" },
      sold: { docs: ["proc", "compra", "venda"], minStatus: "signed" },
    },
  },
  jet: {
    all: ["proc", "compra", "doc_embarcacao", "rg_cpf", "comp_res", "venda", "fatura_banco"],
    required: ["proc", "compra", "doc_embarcacao", "rg_cpf", "comp_res"],
    gates: {
      in_settlement: { docs: ["proc"], minStatus: "uploaded" },
      in_stock: { docs: ["proc", "compra", "doc_embarcacao"], minStatus: "signed" },
      settled: { docs: ["proc", "compra"], minStatus: "signed" },
      sold: { docs: ["proc", "compra", "venda"], minStatus: "signed" },
    },
  },
};

const VEH_TYPE_LABELS = {
  pt: { car: "Carro", moto: "Moto", jet: "Jet-Ski" },
  en: { car: "Car", moto: "Motorcycle", jet: "Jet-Ski" },
};

function docStatusRank(status) {
  const i = DOC_STATUS_ORDER.indexOf(status || "pending");
  return i >= 0 ? i : 0;
}

function docMeetsMinStatus(docStatus, minStatus) {
  return docStatusRank(docStatus) >= docStatusRank(minStatus);
}

function getChecklistConfig(vehType) {
  return ACQ_DOC_CHECKLIST_BY_VEH_TYPE[vehType] || ACQ_DOC_CHECKLIST_BY_VEH_TYPE.car;
}

function getDocTypeLabel(docType, lang) {
  const d = ACQ_DOC_TYPES[docType];
  if (!d) return docType;
  return lang === "en" ? d.labelEn : d.labelPt;
}

function getDocStatusLabel(status, lang) {
  const m = DOC_STATUS_META[status] || DOC_STATUS_META.pending;
  return lang === "en" ? m.labelEn : m.labelPt;
}

function mergeDocsWithChecklist(vehType, dbDocs) {
  const cfg = getChecklistConfig(vehType);
  const byType = {};
  (dbDocs || []).forEach(d => {
    if (!byType[d.doc_type] || new Date(d.updated_at || d.created_at) > new Date(byType[d.doc_type].updated_at || byType[d.doc_type].created_at)) {
      byType[d.doc_type] = d;
    }
  });
  return cfg.all.map(docType => ({
    docType,
    required: cfg.required.includes(docType),
    label: docType,
    record: byType[docType] || null,
    status: byType[docType]?.status || "pending",
    fileUrl: byType[docType]?.file_url || null,
    storagePath: byType[docType]?.storage_path || null,
    id: byType[docType]?.id || null,
  }));
}

function checkStatusGate(newStatus, vehType, dbDocs, lang) {
  const cfg = getChecklistConfig(vehType);
  const gate = cfg.gates[newStatus];
  if (!gate) return { ok: true, missing: [] };
  const merged = mergeDocsWithChecklist(vehType, dbDocs);
  const missing = [];
  gate.docs.forEach(docType => {
    const item = merged.find(m => m.docType === docType);
    const status = item?.status || "pending";
    if (!docMeetsMinStatus(status, gate.minStatus)) {
      missing.push({
        docType,
        label: getDocTypeLabel(docType, lang || "pt"),
        current: status,
        required: gate.minStatus,
        requiredLabel: getDocStatusLabel(gate.minStatus, lang || "pt"),
      });
    }
  });
  const L = lang || "pt";
  const statusLabel = (ACQ_STATUS_LABELS[L] || ACQ_STATUS_LABELS.pt)[newStatus] || newStatus;
  if (missing.length) {
    const names = missing.map(m => `${m.label} (${getDocStatusLabel(m.current, L)} → ${m.requiredLabel})`).join(", ");
    return {
      ok: false,
      missing,
      message: L === "pt"
        ? `Não é possível avançar para "${statusLabel}": documentos obrigatórios incompletos — ${names}.`
        : `Cannot advance to "${statusLabel}": required documents incomplete — ${names}.`,
    };
  }
  return { ok: true, missing: [] };
}

function computeDocCompliance(vehType, dbDocs) {
  const cfg = getChecklistConfig(vehType);
  const merged = mergeDocsWithChecklist(vehType, dbDocs);
  const required = merged.filter(m => m.required);
  const signed = required.filter(m => docMeetsMinStatus(m.status, "signed")).length;
  const uploaded = required.filter(m => docMeetsMinStatus(m.status, "uploaded")).length;
  const pending = required.filter(m => m.status === "pending").length;
  return {
    total: required.length,
    signed,
    uploaded,
    pending,
    pct: required.length ? Math.round((signed / required.length) * 100) : 100,
    items: merged,
  };
}

function canAdvanceDocStatus(current, next) {
  const cur = docStatusRank(current);
  const nxt = docStatusRank(next);
  return nxt === cur + 1 || (current === "uploaded" && next === "signed") || (current === "signed" && next === "archived");
}

function isPreviewableImage(url, path) {
  const s = (path || url || "").toLowerCase();
  return /\.(jpe?g|png|webp|gif)(\?|$)/i.test(s);
}

function isPreviewablePdf(url, path) {
  const s = (path || url || "").toLowerCase();
  return /\.pdf(\?|$)/i.test(s);
}

function DocStatusTag({ status, lang }) {
  const m = DOC_STATUS_META[status] || DOC_STATUS_META.pending;
  return <window.NA.Tag kind={m.kind} dot>{getDocStatusLabel(status, lang)}</window.NA.Tag>;
}

function DocPreviewModal({ open, url, title, onClose, lang }) {
  if (!open || !url) return null;
  const img = isPreviewableImage(url);
  const pdf = isPreviewablePdf(url);
  return (
    <window.NA.Modal open={open} onClose={onClose} title={title || (lang === "pt" ? "Visualizar documento" : "View document")}
      footer={<window.NA.Button kind="default" onClick={onClose}>{lang === "pt" ? "Fechar" : "Close"}</window.NA.Button>}>
      <div style={{ minHeight: 200, maxHeight: "70vh", overflow: "auto", textAlign: "center" }}>
        {img && <img src={url} alt="" style={{ maxWidth: "100%", borderRadius: 6, border: "1px solid var(--color-border-secondary)" }} />}
        {pdf && !img && (
          <iframe title="preview" src={url} style={{ width: "100%", height: "65vh", border: "1px solid var(--color-border-secondary)", borderRadius: 6 }} />
        )}
        {!img && !pdf && (
          <div className="col gap-12" style={{ padding: 24 }}>
            <window.NA.Icon name="file" size={48} style={{ color: "var(--fg3)", margin: "0 auto" }} />
            <div className="hint">{lang === "pt" ? "Pré-visualização não disponível para este formato." : "Preview not available for this format."}</div>
            <a href={url} target="_blank" rel="noreferrer" className="btn primary sm">{lang === "pt" ? "Abrir arquivo" : "Open file"}</a>
          </div>
        )}
      </div>
    </window.NA.Modal>
  );
}

function AcquisitionDocChecklist({
  acquisitionId, vehType = "car", docs = [], lang = "pt", mode = "operational",
  onUpload, onStatusChange, onRefresh, compact = false, canUpload: canUploadProp, canChangeStatus: canChangeStatusProp,
}) {
  const [preview, setPreview] = useStateD(null);
  const [uploadType, setUploadType] = useStateD(null);
  const [busy, setBusy] = useStateD(null);
  const fileRef = useRefD(null);
  const NA = window.NA;
  const cfg = getChecklistConfig(vehType);
  const items = useMemoD(() => mergeDocsWithChecklist(vehType, docs), [vehType, docs]);
  const compliance = useMemoD(() => computeDocCompliance(vehType, docs), [vehType, docs]);

  const openPreview = useCallbackD(async (item) => {
    if (!item.fileUrl && !item.storagePath) return;
    let url = item.fileUrl;
    if (NA.db?.refreshDocumentPreviewUrl && item.storagePath) {
      try {
        url = await NA.db.refreshDocumentPreviewUrl(item.storagePath) || url;
      } catch (e) { /* fallback to stored url */ }
    }
    setPreview({ url, title: getDocTypeLabel(item.docType, lang) });
  }, [lang]);

  const handleFile = async (e) => {
    const file = e.target.files?.[0];
    if (!file || !uploadType || !onUpload) return;
    setBusy(uploadType);
    try {
      await onUpload(uploadType, file);
      onRefresh && onRefresh();
    } catch (err) {
      alert(err.message || err);
    } finally {
      setBusy(null);
      setUploadType(null);
      if (fileRef.current) fileRef.current.value = "";
    }
  };

  const advanceStatus = async (item, nextStatus) => {
    if (!onStatusChange || !item.id) return;
    setBusy(item.docType + nextStatus);
    try {
      await onStatusChange(item.id, nextStatus);
      onRefresh && onRefresh();
    } catch (err) {
      alert(err.message || err);
    } finally {
      setBusy(null);
    }
  };

  if (compact) {
    return (
      <div className="row gap-4" style={{ flexWrap: "wrap", marginTop: 6 }}>
        {items.filter(i => i.required).map(item => (
          <span key={item.docType} className="chip fs-10" title={getDocTypeLabel(item.docType, lang)}
            style={{
              opacity: docMeetsMinStatus(item.status, "signed") ? 1 : 0.65,
              borderColor: item.status === "pending" ? "var(--color-warning-border)" : undefined,
            }}>
            {getDocTypeLabel(item.docType, lang).split(" ")[0]}
            {docMeetsMinStatus(item.status, "signed") ? " ✓" : item.status === "uploaded" ? " ↑" : ""}
          </span>
        ))}
        <span className="text-faint fs-10">{compliance.signed}/{compliance.total}</span>
      </div>
    );
  }

  return (
    <div className="col gap-8">
      {!compact && (
        <div className="row jcsb fs-12 text-muted">
          <span>{VEH_TYPE_LABELS[lang]?.[vehType] || vehType} · {compliance.signed}/{compliance.total} {lang === "pt" ? "assinados" : "signed"}</span>
          <window.NA.Progress value={compliance.pct} style={{ width: 80 }} />
        </div>
      )}

      {items.map(item => {
        const isRequired = cfg.required.includes(item.docType);
        const canSign = (canChangeStatusProp ?? true) && mode === "legal" && item.status === "uploaded";
        const canArchive = (canChangeStatusProp ?? true) && mode === "legal" && item.status === "signed";
        const canUpload = (canUploadProp ?? true) && mode === "operational" && NA.db?.isConfigured?.();
        return (
          <div key={item.docType} style={{
            padding: "10px 0", borderBottom: "1px solid var(--color-border-secondary)",
            opacity: isRequired ? 1 : 0.85,
          }}>
            <div className="row jcsb gap-8" style={{ alignItems: "flex-start" }}>
              <div className="flex-1">
                <div className="row gap-8">
                  <NA.Icon name={(ACQ_DOC_TYPES[item.docType] || {}).icon || "file"} size={14} style={{ color: "var(--fg3)" }} />
                  <span className="fs-13 fw-500">{getDocTypeLabel(item.docType, lang)}</span>
                  {isRequired && <span className="chip fs-10">{lang === "pt" ? "Obrigatório" : "Required"}</span>}
                </div>
                <div style={{ marginTop: 6 }}><DocStatusTag status={item.status} lang={lang} /></div>
              </div>
              <div className="row gap-4" style={{ flexShrink: 0, flexWrap: "wrap", justifyContent: "flex-end" }}>
                {item.fileUrl && (
                  <NA.Button kind="ghost" size="sm" icon="eye" onClick={() => openPreview(item)}>
                    {lang === "pt" ? "Ver" : "View"}
                  </NA.Button>
                )}
                {canUpload && (
                  <NA.Button kind="default" size="sm" icon="upload" disabled={!!busy}
                    onClick={() => { setUploadType(item.docType); fileRef.current?.click(); }}>
                    {busy === item.docType ? "…" : (item.fileUrl ? (lang === "pt" ? "Substituir" : "Replace") : (lang === "pt" ? "Enviar" : "Upload"))}
                  </NA.Button>
                )}
                {canSign && (
                  <NA.Button kind="success" size="sm" icon="pen-line" disabled={!!busy}
                    onClick={() => advanceStatus(item, "signed")}>
                    {lang === "pt" ? "Assinar" : "Sign"}
                  </NA.Button>
                )}
                {canArchive && (
                  <NA.Button kind="default" size="sm" icon="archive" disabled={!!busy}
                    onClick={() => advanceStatus(item, "archived")}>
                    {lang === "pt" ? "Arquivar" : "Archive"}
                  </NA.Button>
                )}
              </div>
            </div>
          </div>
        );
      })}

      <input ref={fileRef} type="file" accept=".pdf,.jpg,.jpeg,.png,.webp,.doc,.docx" style={{ display: "none" }}
        onChange={handleFile} />

      <DocPreviewModal open={!!preview} url={preview?.url} title={preview?.title} onClose={() => setPreview(null)} lang={lang} />
    </div>
  );
}

const AcquisitionDocs = {
  ACQ_DOC_TYPES,
  DOC_STATUS_ORDER,
  DOC_STATUS_META,
  ACQ_DOC_CHECKLIST_BY_VEH_TYPE,
  getChecklistConfig,
  getDocTypeLabel,
  getDocStatusLabel,
  mergeDocsWithChecklist,
  checkStatusGate,
  computeDocCompliance,
  canAdvanceDocStatus,
  docMeetsMinStatus,
  DocStatusTag,
  DocPreviewModal,
  AcquisitionDocChecklist,
};

window.NA.AcquisitionDocs = AcquisitionDocs;
Object.assign(window.NA, {
  DocStatusTag,
  AcquisitionDocChecklist,
});
