/* =========================================================
   Customers — the Customer Context Engine's front door.

   This page answers the framework's first questions in product
   form: WHERE does enterprise data go in (CSV import: loyalty,
   POS, CRM exports — any columns), WHO is this customer, WHAT
   do we already know (imported facts + facts learned on calls,
   with provenance), and WHAT will Mikaka use on the next
   conversation (the exact context brief).

   Backend: /outbound/contacts (list/search),
   /outbound/contacts/import (bulk upsert, metadata merges),
   /outbound/contacts/{id}/profile (facts + brief + calls).
   ========================================================= */

const CUST_PHONE_HEADERS = ["phone", "phone number", "mobile", "mobile number", "msisdn", "phone_e164", "telephone", "tel", "number", "contact"];
const CUST_NAME_HEADERS = ["name", "full name", "full_name", "customer", "customer name", "client", "contact name"];
const CUST_COMPANY_HEADERS = ["company", "organisation", "organization", "business"];

const custNormalizePhone = (raw) => {
  const cleaned = String(raw || "").replace(/[^\d+]/g, "");
  const digits = cleaned.replace(/\D/g, "");
  if (digits.length < 7) return null;
  if (cleaned.startsWith("+")) return cleaned;
  if (digits.startsWith("0") && digits.length === 10) return `+254${digits.slice(1)}`;
  if (digits.startsWith("254")) return `+${digits}`;
  return `+${digits}`;
};

const custParseCsvRows = (text) => {
  // Minimal CSV: handles quoted cells with commas and doubled quotes.
  const rows = [];
  let row = [], cell = "", inQuotes = false;
  const src = String(text || "");
  for (let i = 0; i < src.length; i++) {
    const ch = src[i];
    if (inQuotes) {
      if (ch === '"' && src[i + 1] === '"') { cell += '"'; i++; }
      else if (ch === '"') inQuotes = false;
      else cell += ch;
    } else if (ch === '"') inQuotes = true;
    else if (ch === ",") { row.push(cell); cell = ""; }
    else if (ch === "\n" || ch === "\r") {
      if (ch === "\r" && src[i + 1] === "\n") i++;
      row.push(cell); cell = "";
      if (row.some((c) => String(c).trim())) rows.push(row);
      row = [];
    } else cell += ch;
  }
  row.push(cell);
  if (row.some((c) => String(c).trim())) rows.push(row);
  return rows;
};

// Any labelled column beyond phone/name/email/company rides along as a
// customer fact (loyalty_tier, average_basket, last_visit, ...) — that IS the
// enterprise data the context engine personalizes conversations with.
const custProfilesFromCsv = (text) => {
  const rows = custParseCsvRows(text);
  if (!rows.length) return { profiles: [], columns: [] };
  const headers = rows[0].map((h) => String(h || "").trim().toLowerCase());
  const hasHeader = headers.some((h) => CUST_PHONE_HEADERS.includes(h) || CUST_NAME_HEADERS.includes(h) || h === "email");
  const dataRows = hasHeader ? rows.slice(1) : rows;
  const findIdx = (names) => headers.findIndex((h) => names.includes(h));
  const phoneIdx = hasHeader ? findIdx(CUST_PHONE_HEADERS) : 1;
  const nameIdx = hasHeader ? findIdx(CUST_NAME_HEADERS) : 0;
  const emailIdx = hasHeader ? headers.indexOf("email") : -1;
  const companyIdx = hasHeader ? findIdx(CUST_COMPANY_HEADERS) : -1;
  const knownIdx = new Set([phoneIdx, nameIdx, emailIdx, companyIdx].filter((i) => i >= 0));
  const factColumns = hasHeader
    ? headers.map((h, i) => (!h || knownIdx.has(i) ? null : h.replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, ""))).filter(Boolean)
    : [];
  const profiles = dataRows
    .map((row, idx) => {
      const phone = custNormalizePhone(String((phoneIdx >= 0 ? row[phoneIdx] : "") || row[1] || row[0] || "").trim());
      if (!phone) return null;
      const fullName = String((nameIdx >= 0 ? row[nameIdx] : row[0]) || "").trim();
      const [firstName, ...rest] = fullName.split(/\s+/).filter(Boolean);
      const facts = { source: "customer_import" };
      if (hasHeader) {
        headers.forEach((h, i) => {
          if (!h || knownIdx.has(i)) return;
          const key = h.replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
          const val = String(row[i] || "").trim();
          if (key && val) facts[key] = val;
        });
      }
      return {
        external_ref: `import-${idx + 1}`,
        first_name: firstName || null,
        last_name: rest.join(" ") || null,
        full_name: fullName || null,
        phone_e164: phone,
        email: emailIdx >= 0 ? String(row[emailIdx] || "").trim() || null : null,
        company: companyIdx >= 0 ? String(row[companyIdx] || "").trim() || null : null,
        timezone: "Africa/Nairobi",
        metadata: facts,
      };
    })
    .filter(Boolean);
  return { profiles, columns: factColumns };
};

const CUST_INTERNAL_KEYS = new Set(["source", "is_repeat", "prior_summary", "prior_reason", "reason", "last_called_ago"]);
const custFactEntries = (obj) =>
  Object.entries(obj || {}).filter(([k]) => k && !k.startsWith("_") && !CUST_INTERNAL_KEYS.has(k));

const CustFactGrid = ({ entries, empty }) => (
  entries.length ? (
    <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))", gap: 8 }}>
      {entries.map(([k, v]) => {
        const value = v && typeof v === "object" && "value" in v ? v.value : v;
        const when = v && typeof v === "object" && v.at ? new Date(v.at).toLocaleDateString() : null;
        return (
          <div key={k} style={{ border: "1px solid var(--border)", borderRadius: 8, padding: "8px 10px" }}>
            <div style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: ".05em", color: "var(--fg-muted)", fontWeight: 600 }}>{String(k).replace(/_/g, " ")}</div>
            <div style={{ fontSize: 13, fontWeight: 600, marginTop: 2, overflowWrap: "anywhere" }}>{String(value)}</div>
            {when ? <div style={{ fontSize: 10.5, color: "var(--fg-faint)", marginTop: 2 }}>learned on a call · {when}</div> : null}
          </div>
        );
      })}
    </div>
  ) : <div style={{ fontSize: 12.5, color: "var(--fg-faint)" }}>{empty}</div>
);

const CustProfileDrawer = ({ contactId, onClose, onGo }) => {
  const [profile, setProfile] = useState(null);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    let live = true;
    setLoading(true); setProfile(null);
    api.outbound.getCustomerProfile(contactId)
      .then((p) => { if (live) setProfile(p); })
      .catch(() => {})
      .finally(() => { if (live) setLoading(false); });
    return () => { live = false; };
  }, [contactId]);

  const contact = profile?.contact || {};
  const imported = custFactEntries(contact.metadata);
  const learned = custFactEntries(contact.enrichments);
  const brief = profile?.next_call_brief || {};
  const briefFacts = Object.entries(brief.known_facts || {});
  return (
    <div style={{ position: "fixed", inset: 0, zIndex: 90, display: "flex", justifyContent: "flex-end" }}>
      <div style={{ position: "absolute", inset: 0, background: "rgba(0,0,0,0.35)" }} onClick={onClose}/>
      <div className="card" style={{ position: "relative", width: "min(560px, 94vw)", height: "100%", overflowY: "auto", borderRadius: 0, padding: 24 }}>
        <div className="row between" style={{ marginBottom: 4 }}>
          <div>
            <div className="h3" style={{ fontSize: 18 }}>{contact.full_name || contact.phone_e164 || "Customer"}</div>
            <div style={{ fontSize: 12.5, color: "var(--fg-muted)" }}>{contact.phone_e164}{contact.company ? ` · ${contact.company}` : ""}{contact.email ? ` · ${contact.email}` : ""}</div>
          </div>
          <button className="btn btn-ghost btn-sm" onClick={onClose}><Icon name="x" size={14}/></button>
        </div>
        {loading ? <div style={{ fontSize: 13, color: "var(--fg-muted)", marginTop: 16 }}>Loading profile…</div> : (
          <div className="stack gap-3" style={{ marginTop: 14 }}>
            <div>
              <div style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: ".07em", color: "var(--fg-muted)", fontWeight: 700, marginBottom: 8 }}>What you told us — imported data</div>
              <CustFactGrid entries={imported} empty="No imported facts yet — include extra columns in your CSV (loyalty tier, average basket, last visit…) and they land here."/>
            </div>
            <div>
              <div style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: ".07em", color: "var(--fg-muted)", fontWeight: 700, marginBottom: 8 }}>What conversations taught us</div>
              <CustFactGrid entries={learned} empty="Nothing learned yet — after each analysed call, durable facts the customer states are remembered here automatically."/>
            </div>
            <div className="card card-pad" style={{ background: "var(--bg-sunken, rgba(0,0,0,0.03))", border: "1px dashed var(--border)" }}>
              <div style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: ".07em", color: "var(--fg-muted)", fontWeight: 700, marginBottom: 6 }}>Next-call brief — what Mikaka will use</div>
              {briefFacts.length ? (
                <>
                  <div style={{ fontSize: 12.5, color: "var(--fg-muted)", marginBottom: 8 }}>
                    On the next conversation (inbound or campaign), the agent receives these facts with a hard rule:
                    personalize with one or two of them, and never ask the customer for anything listed.
                  </div>
                  <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
                    {briefFacts.map(([k, v]) => (
                      <span key={k} style={{ fontSize: 12, border: "1px solid var(--border)", borderRadius: 999, padding: "3px 10px" }}>
                        <span style={{ color: "var(--fg-muted)" }}>{k.replace(/_/g, " ")}:</span> <b>{String(v)}</b>
                      </span>
                    ))}
                  </div>
                </>
              ) : (
                <div style={{ fontSize: 12.5, color: "var(--fg-faint)" }}>No usable facts yet — import data or let a first conversation happen.</div>
              )}
            </div>
            <div>
              <div style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: ".07em", color: "var(--fg-muted)", fontWeight: 700, marginBottom: 8 }}>
                Analysed conversations{profile?.campaign_answers ? ` · ${profile.campaign_answers} campaign answer${profile.campaign_answers === 1 ? "" : "s"}` : ""}
              </div>
              {(profile?.analysed_calls || []).length ? (
                <div className="stack gap-2">
                  {(profile.analysed_calls || []).map((cl) => (
                    <div key={cl.call_id} style={{ borderLeft: "2px solid var(--border)", paddingLeft: 10 }}>
                      <div style={{ fontSize: 11, color: "var(--fg-faint)" }}>
                        {cl.created_at ? new Date(cl.created_at).toLocaleDateString() : ""} · {cl.direction || "call"} · {String(cl.intent_category || "").replace(/_/g, " ")} → {String(cl.outcome || "").replace(/_/g, " ")}
                      </div>
                      {(cl.needs_identified || []).length ? (
                        <div style={{ fontSize: 12.5, color: "var(--fg-muted)" }}>Needs: {(cl.needs_identified || []).join(", ")}</div>
                      ) : null}
                    </div>
                  ))}
                </div>
              ) : <div style={{ fontSize: 12.5, color: "var(--fg-faint)" }}>No analysed conversations with this customer yet.</div>}
            </div>
            <button className="btn btn-accent" style={{ alignSelf: "flex-start" }} onClick={() => onGo && onGo("outbound")}>
              <Icon name="zap" size={14}/> Run an intelligence campaign
            </button>
          </div>
        )}
      </div>
    </div>
  );
};

const TenantCustomers = ({ onGo }) => {
  const toast = useToast();
  const [contacts, setContacts] = useState([]);
  const [search, setSearch] = useState("");
  const [loading, setLoading] = useState(true);
  const [stats, setStats] = useState(null);
  const [pending, setPending] = useState(null); // parsed CSV awaiting confirm
  const [importing, setImporting] = useState(false);
  const [openContact, setOpenContact] = useState(null);
  const fileRef = useRef(null);

  const loadContacts = (q) => {
    setLoading(true);
    api.outbound.listContacts({ search: q || undefined, page_size: 200 })
      .then((rows) => setContacts(Array.isArray(rows) ? rows : []))
      .catch(() => setContacts([]))
      .finally(() => setLoading(false));
  };
  useEffect(() => { loadContacts(""); }, []);
  useEffect(() => {
    const t = setTimeout(() => loadContacts(search), 350);
    return () => clearTimeout(t);
  }, [search]);
  useEffect(() => {
    api.intelligence.pillars({ days: 30 }).then((p) => setStats(p?.customer || null)).catch(() => {});
  }, []);

  const onFile = (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = () => {
      const { profiles, columns } = custProfilesFromCsv(String(reader.result || ""));
      if (!profiles.length) {
        toast({ title: "Nothing to import", body: "No rows with a usable phone number were found in that file.", kind: "danger" });
      } else {
        setPending({ profiles, columns, name: file.name });
      }
      if (fileRef.current) fileRef.current.value = "";
    };
    reader.readAsText(file);
  };

  const runImport = async () => {
    if (!pending || importing) return;
    setImporting(true);
    try {
      let imported = 0, failed = 0;
      for (let i = 0; i < pending.profiles.length; i += 200) {
        const res = await api.outbound.importCustomerProfiles(pending.profiles.slice(i, i + 200));
        imported += Number(res?.imported || 0); failed += Number(res?.failed || 0);
      }
      toast({ title: "Customer data imported", body: `${imported.toLocaleString()} profiles updated${failed ? `, ${failed} rows skipped` : ""}. Every conversation with them is now context-aware.` });
      setPending(null);
      loadContacts(search);
    } catch (e) {
      toast({ title: "Import failed", body: (e && e.message) || "Please try again.", kind: "danger" });
    } finally {
      setImporting(false);
    }
  };

  const factCount = (c) => custFactEntries(c.metadata).length;
  const learnedCount = (c) => custFactEntries(c.enrichments).length;

  return (
    <div className="page page-mount">
      <div className="row between" style={{ alignItems: "flex-start", flexWrap: "wrap", gap: 12 }}>
        <div>
          <h1 className="display" style={{ fontSize: 28, fontWeight: 600, margin: 0 }}>Customers</h1>
          <p className="page-sub" style={{ maxWidth: 640 }}>
            The context engine. Bring your enterprise data — loyalty, POS, CRM exports — and every
            conversation starts already knowing the customer: no redundant questions, and everything
            they say flows back into their profile.
          </p>
        </div>
        <div className="row gap-2">
          <input ref={fileRef} type="file" accept=".csv,text/csv" style={{ display: "none" }} onChange={onFile}/>
          <button className="btn btn-accent" onClick={() => fileRef.current && fileRef.current.click()}>
            <Icon name="upload" size={14}/> Import customer data (CSV)
          </button>
        </div>
      </div>

      {stats ? (
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(150px, 1fr))", gap: 11, maxWidth: 1020, marginTop: 16 }}>
          {[
            ["Profiles", stats.total_contacts, "customers known"],
            ["New (30d)", stats.new_contacts, "recently added"],
            ["Enriched by calls", stats.enriched_profiles, "conversations taught us something"],
            ["Dormant 60d+", stats.dormant_contacts, "win-back candidates"],
          ].map(([label, value, sub]) => (
            <div key={label} className="card card-pad" style={{ padding: 14 }}>
              <div style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: ".07em", color: "var(--fg-muted)", fontWeight: 600 }}>{label}</div>
              <div className="num" style={{ fontSize: 24, marginTop: 4 }}>{Number(value || 0).toLocaleString()}</div>
              <div style={{ fontSize: 11.5, color: "var(--fg-muted)", marginTop: 2 }}>{sub}</div>
            </div>
          ))}
        </div>
      ) : null}

      {pending ? (
        <div className="card card-pad" style={{ maxWidth: 1020, marginTop: 16, borderLeft: "3px solid var(--mk-accent, #b4552d)" }}>
          <div className="row between" style={{ flexWrap: "wrap", gap: 10 }}>
            <div>
              <div style={{ fontWeight: 600 }}>{pending.name}: {pending.profiles.length.toLocaleString()} customer profiles ready</div>
              <div style={{ fontSize: 12.5, color: "var(--fg-muted)", marginTop: 2 }}>
                {pending.columns.length
                  ? <>Fact columns detected: {pending.columns.slice(0, 8).map((c) => c.replace(/_/g, " ")).join(", ")}{pending.columns.length > 8 ? "…" : ""} — these become facts the agent personalizes with.</>
                  : "Only phone/name columns detected — add columns like loyalty_tier or average_basket for richer context."}
                {" "}Re-imports merge: existing facts are kept, new columns win per-field.
              </div>
            </div>
            <div className="row gap-2">
              <button className="btn btn-ghost" onClick={() => setPending(null)} disabled={importing}>Cancel</button>
              <button className="btn btn-accent" onClick={runImport} disabled={importing}>{importing ? "Importing…" : "Import now"}</button>
            </div>
          </div>
        </div>
      ) : null}

      <div className="card card-pad" style={{ maxWidth: 1020, marginTop: 16 }}>
        <div className="row between" style={{ marginBottom: 12, flexWrap: "wrap", gap: 10 }}>
          <div className="h3">Customer profiles</div>
          <input className="input" style={{ maxWidth: 260 }} placeholder="Search name, phone, company…" value={search} onChange={(e) => setSearch(e.target.value)}/>
        </div>
        {loading ? <div style={{ fontSize: 13, color: "var(--fg-muted)" }}>Loading…</div> : !contacts.length ? (
          <div style={{ fontSize: 13.5, color: "var(--fg-muted)", lineHeight: 1.6, maxWidth: 560 }}>
            No customer profiles yet. Import a CSV with a phone column — any other columns
            (loyalty tier, average basket, last visit, favourite brands…) ride along as facts, and
            from that moment every call with those customers is personalized and every conversation
            enriches their profile.
          </div>
        ) : (
          <div style={{ overflowX: "auto" }}>
            <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 13 }}>
              <thead>
                <tr style={{ textAlign: "left", color: "var(--fg-muted)", fontSize: 11.5, textTransform: "uppercase", letterSpacing: ".05em" }}>
                  <th style={{ padding: "6px 8px" }}>Customer</th>
                  <th style={{ padding: "6px 8px" }}>Phone</th>
                  <th style={{ padding: "6px 8px" }}>Imported facts</th>
                  <th style={{ padding: "6px 8px" }}>Learned on calls</th>
                  <th style={{ padding: "6px 8px" }}>Last contacted</th>
                </tr>
              </thead>
              <tbody>
                {contacts.map((c) => (
                  <tr key={c.id} style={{ borderTop: "1px solid var(--border)", cursor: "pointer" }} onClick={() => setOpenContact(c.id)}>
                    <td style={{ padding: "8px" }}>
                      <b>{c.full_name || "—"}</b>{c.company ? <span style={{ color: "var(--fg-muted)" }}> · {c.company}</span> : null}
                    </td>
                    <td style={{ padding: "8px", whiteSpace: "nowrap" }}>{c.phone_e164}</td>
                    <td style={{ padding: "8px" }}>{factCount(c) ? `${factCount(c)} facts` : <span style={{ color: "var(--fg-faint)" }}>none</span>}</td>
                    <td style={{ padding: "8px" }}>{learnedCount(c) ? <span style={{ color: "var(--mk-success)", fontWeight: 600 }}>{learnedCount(c)} facts</span> : <span style={{ color: "var(--fg-faint)" }}>not yet</span>}</td>
                    <td style={{ padding: "8px", whiteSpace: "nowrap", color: "var(--fg-muted)" }}>{c.last_contacted_at ? new Date(c.last_contacted_at).toLocaleDateString() : "never"}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>

      <div style={{ maxWidth: 1020, marginTop: 14, fontSize: 12.5, color: "var(--fg-muted)", lineHeight: 1.6 }}>
        How the loop works: imported data personalizes the next conversation → the conversation is
        analysed automatically → durable facts return to the profile → the Intelligence page turns it
        all into pillars and recommendations. Nothing here needs manual processing.
      </div>

      {openContact ? <CustProfileDrawer contactId={openContact} onClose={() => setOpenContact(null)} onGo={onGo}/> : null}
    </div>
  );
};
