/* global React, Icon, StatusChip, Avatar, PageHeader, Drawer, DrawerHead, Tabs, Meta, Banner, SOURCES, MAPPINGS, PEOPLE, etb, useActionDrawer, useToast */
const { useState: useStateH } = React;

const HARM_HELP = {
  title: "Data Harmonizer",
  purpose: "Where raw bank extracts become controlled source snapshots: intake, schema validation, failed-row triage, field mapping, and reconciliation back to the GL — all before any workpaper trusts a number.",
  first: "Look for red source cards (validation failed) and the failed-row count. Mapped does not mean reconciled; reconciled does not mean rule-evidenced.",
  terms: [
    ["Source snapshot", "A hashed, dated capture of an extract — the immutable thing the workpaper cites."],
    ["Schema validation", "Checks each row against the expected contract before it can be mapped."],
    ["Mapping confidence", "System's certainty that a source field belongs to a target cell."],
    ["Reconciliation", "Source totals tied back to the general ledger / control total."],
  ],
  next: [
    "Open a source card to inspect its snapshot, validation, mapping and lineage.",
    "Triage failed rows — reject, fix, or request re-extract.",
    "Approve a mapping (maker-checker) to advance it toward reconciliation.",
  ],
  connections: [
    "Failed rows and breaks open as Exceptions.",
    "Approved, reconciled sources feed the risk workpapers.",
    "Published lineage is what Reg Reporting cites at the export gate.",
  ],
  guardrail: "Uploaded does not mean official. Synthetic sources are internal review data and can never feed an official return.",
};

function Harmonizer({ go, info }) {
  const [tab, setTab] = useStateH("Sources");
  const [drawer, setDrawer] = useStateH(null);   // source object
  const [triage, setTriage] = useStateH(null);    // failed-row source
  const [actionNode, openAction] = useActionDrawer();

  return (
    <div className="main-inner">
      <PageHeader
        eyebrow="Data foundation"
        title="Data Harmonizer"
        onInfo={() => info(HARM_HELP)}
        right={<React.Fragment>
          <button className="btn btn-ghost btn-sm" onClick={() => openAction({
            title: "Publish lineage",
            sub: "Internal lineage snapshot",
            chip: <StatusChip s="REVIEW_PENDING" />,
            banner: <span><b>Lineage package staged.</b> Reconciled sources can be cited by workpaper cells after failed rows and mapping checks are cleared.</span>,
            rows: [["Sources", SOURCES.length + " snapshots"], ["Failed rows", SOURCES.reduce((a, s) => a + s.fails, 0) + " still blocking"], ["Destination", "Export Gate lineage check"], ["Owner", "Dawit Bekele"]],
            guardrail: "Publishing lineage records internal review state only. It does not write export artifacts or unlock official reporting.",
          })}><Icon name="gitBranch" size={15} /> Publish lineage</button>
          <button className="btn btn-primary btn-sm" onClick={() => openAction({
            title: "Add source",
            sub: "Source intake contract",
            chip: <StatusChip s="SYNTHETIC" />,
            banner: <span><b>Source intake drawer opened.</b> Add-source is represented as a typed fixture contract in this build.</span>,
            rows: [["Accepted source", "Static fixture snapshot"], ["Required metadata", "Owner, source system, method, hash, row count"], ["Validation", "Schema check before mapping"], ["Next action", "Create or update fixture data"]],
            items: [
              { title: "No live connector", body: "Bank systems are not connected in Sprint 1.", icon: "plug" },
              { title: "Controlled source register", body: "This environment uses typed source contracts for review.", icon: "database" },
              { title: "No official feed", body: "Synthetic data cannot feed official returns.", icon: "lock" },
            ],
            primary: "Understood",
          })}><Icon name="upload" size={15} /> Add source</button>
        </React.Fragment>}
      />

      {/* stage stepper */}
      <div className="card" style={{ padding: "4px 6px", marginBottom: 20, display: "flex", overflowX: "auto" }}>
        {[["Source intake", "done"], ["Validation", "fail"], ["Mapping", "active"], ["Reconciliation", "todo"], ["Rule evidence", "todo"], ["Approval", "todo"], ["Publish lineage", "todo"]].map(([s, st], i, arr) => {
          const tone = { done: ["var(--green)", "#fff", "check"], fail: ["var(--red)", "#fff", "alert"], active: ["var(--ink)", "var(--lime)", "clock"], todo: ["var(--surface-2)", "var(--ink-4)", ""] }[st];
          return (
            <div key={s} className="center gap8" style={{ padding: "9px 14px", flex: "0 0 auto" }}>
              <span style={{ width: 22, height: 22, borderRadius: 50, background: tone[0], color: tone[1], display: "grid", placeItems: "center", border: st === "todo" ? "1.5px solid var(--border-dark)" : "none" }}>
                {tone[2] ? <Icon name={tone[2]} size={12} /> : <span style={{ fontSize: 11, fontWeight: 700 }}>{i + 1}</span>}
              </span>
              <span style={{ fontSize: 12.5, fontWeight: st === "active" ? 700 : 500, color: st === "todo" ? "var(--ink-3)" : "var(--ink)" }}>{s}</span>
              {i < arr.length - 1 && <Icon name="chevR" size={13} className="muted" style={{ marginLeft: 6 }} />}
            </div>
          );
        })}
      </div>

      <div className="seg-ctl" style={{ marginBottom: 16 }}>
        {["Sources", "Mapping", "Reconciliation"].map(t => (
          <button key={t} className={tab === t ? "on" : ""} onClick={() => setTab(t)}>{t}</button>
        ))}
      </div>

      {tab === "Sources" && <SourcesTab onOpen={setDrawer} onTriage={setTriage} />}
      {tab === "Mapping" && <MappingTab info={info} />}
      {tab === "Reconciliation" && <ReconTab go={go} />}

      <SourceDrawer source={drawer} onClose={() => setDrawer(null)} onTriage={(s) => { setDrawer(null); setTriage(s); }} go={go} />
      <TriageDrawer source={triage} onClose={() => setTriage(null)} go={go} />
      {actionNode}
    </div>
  );
}

/* ---------- Sources tab ---------- */
function SourcesTab({ onOpen, onTriage }) {
  const [filter, setFilter] = useStateH("All");
  const failed = SOURCES.filter(s => s.state === "VALIDATION_FAILED");
  const fils = ["All", "Reconciled", "Failed", "Synthetic"];
  const match = s => filter === "All" || (filter === "Reconciled" && s.state === "RECONCILED") || (filter === "Failed" && s.state === "VALIDATION_FAILED") || (filter === "Synthetic" && s.synthetic);
  const list = SOURCES.filter(match);
  return (
    <React.Fragment>
      {failed.length > 0 && (
        <div style={{ marginBottom: 16 }}>
          <Banner kind="red" icon="alert">
            <b>{failed.reduce((a, s) => a + s.fails, 0)} rows failed schema validation</b> across {failed.length} sources. Triage before these can be mapped — open a red card to review failed rows.
          </Banner>
        </div>
      )}
      <div className="center gap8 wrap mb12">{fils.map(f => <button key={f} className={"chip chip-lg " + (filter === f ? "chip-ink" : "chip-neutral")} style={{ cursor: "pointer" }} onClick={() => setFilter(f)}>{f}</button>)}</div>
      {list.length === 0
        ? <StateView kind="empty" icon="inbox" title={"No " + filter.toLowerCase() + " sources"} body="No source snapshots match this filter for the current cycle. Add a source or clear the filter to see all." action="Clear filter" onAction={() => setFilter("All")} />
        : <div className="grid g2" style={{ gap: 14 }}>
        {list.map(s => {
          const p = PEOPLE[s.owner];
          return (
            <div key={s.id} className="card" style={{ padding: "16px 18px", cursor: "pointer" }}
              onClick={() => onOpen(s)}>
              <div className="between" style={{ alignItems: "flex-start" }}>
                <div className="center gap10" style={{ minWidth: 0, flex: "1 1 auto" }}>
                  <span style={{ width: 32, height: 32, borderRadius: 8, background: "var(--surface-2)", border: "1px solid var(--border)", display: "grid", placeItems: "center", color: "var(--ink-2)", flex: "0 0 auto" }}>
                    <Icon name={s.synthetic ? "flask" : "database"} size={16} />
                  </span>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontWeight: 700, fontSize: 13.5, letterSpacing: "-.01em", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{s.name}</div>
                    <div className="muted" style={{ fontSize: 11.5, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{s.system} · {s.method}</div>
                  </div>
                </div>
                <StatusChip s={s.state} />
              </div>
              <div className="between" style={{ marginTop: 14, fontSize: 12 }}>
                <div className="center gap16">
                  <span className="muted">Rows <b className="tnum" style={{ color: "var(--ink)" }}>{s.rows.toLocaleString()}</b></span>
                  <span className="muted">Hash <span className="mono" style={{ color: "var(--ink-2)" }}>{s.hash}</span></span>
                  <span className="muted">{s.date}</span>
                </div>
              </div>
              <div className="between" style={{ marginTop: 12, paddingTop: 12, borderTop: "1px solid var(--border)" }}>
                <span className="center gap6" style={{ fontSize: 12 }}><Avatar name={p.name} size={20} /><span className="muted">{p.name}</span></span>
                {s.fails > 0
                  ? <button className="btn btn-ghost btn-sm" style={{ color: "var(--red)", borderColor: "var(--red-line)" }} onClick={(e) => { e.stopPropagation(); onTriage(s); }}><Icon name="alert" size={13} /> <span>Triage {s.fails} rows</span></button>
                  : <span className="jump">Inspect <Icon name="arrowR" size={13} /></span>}
              </div>
            </div>
          );
        })}
      </div>}
    </React.Fragment>
  );
}

/* ---------- Mapping tab (canvas) ---------- */
function MappingTab({ info }) {
  const [toastNode, showToast] = useToast();
  return (
    <div className="card card-pad">
      <div className="panel-h"><h3>Mapping canvas</h3><span className="sub">Source field → workpaper / cell target · confidence-scored</span>
        <div className="right"><button className="btn btn-ghost btn-sm" onClick={() => showToast("Mapping suggestions generated from fixture contracts")}><Icon name="zap" size={14} /> Auto-suggest all</button></div>
      </div>
      <table className="tbl">
        <thead><tr><th>Source field</th><th></th><th>Target cell</th><th className="num">Confidence</th><th>State</th><th></th></tr></thead>
        <tbody>
          {MAPPINGS.map((m, i) => {
            const tone = m.conf >= 90 ? "green" : m.conf >= 70 ? "amber" : "red";
            return (
              <tr key={i} className="click">
                <td><span className="mono" style={{ fontSize: 12.5 }}>{m.src}</span></td>
                <td style={{ width: 30, color: "var(--ink-4)" }}><Icon name="arrowR" size={15} /></td>
                <td style={{ fontWeight: 600 }}>{m.tgt}</td>
                <td className="num">
                  <span className="center gap8" style={{ justifyContent: "flex-end" }}>
                    <span className="bar" style={{ width: 54 }}><span className={tone === "green" ? "" : tone === "amber" ? "" : ""} style={{ width: m.conf + "%", background: tone === "green" ? "var(--green)" : tone === "amber" ? "var(--amber)" : "var(--red)" }} /></span>
                    <b className="tnum">{m.conf}%</b>
                  </span>
                </td>
                <td><StatusChip s={m.state} /></td>
                <td className="num">
                  {m.state === "REVIEW_PENDING"
                    ? <button className="btn btn-dark btn-sm" onClick={() => showToast("Mapping sent to checker")}>Approve</button>
                    : m.state === "VALIDATION_FAILED"
                      ? <button className="btn btn-ghost btn-sm" style={{ color: "var(--red)", borderColor: "var(--red-line)" }} onClick={() => showToast("Mapping fix opened for " + m.src)}>Fix</button>
                      : <button className="btn btn-quiet btn-sm" onClick={() => showToast("Mapping review opened for " + m.src)}>Review</button>}
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
      <div className="banner banner-amber" style={{ marginTop: 16 }}>
        <Icon name="info" size={18} className="ic" />
        <div>A mapping below 70% confidence raises an exception and cannot auto-advance. Approving a mapping is a <b>maker-checker</b> action recorded in the audit trail.</div>
      </div>
      {toastNode}
    </div>
  );
}

/* ---------- Reconciliation tab ---------- */
function ReconTab({ go }) {
  const [brk, setBrk] = useStateH(null);
  const rows = [
    { item: "Deposits ledger → ALM/LCR", src: 184230, gl: 184230, diff: 0, state: "RECONCILED" },
    { item: "HQLA securities → LCR Level 1/2", src: 30790, gl: 30790, diff: 0, state: "RECONCILED" },
    { item: "Money-market deals → ALM inflows", src: 4300, gl: 4300, diff: 0, state: "RECONCILED" },
    { item: "Off-balance notional → Credit", src: 3920, gl: 3924.2, diff: -4.2, state: "VALIDATION_FAILED" },
    { item: "FX position → NOP workpaper", src: 612, gl: 612, diff: 0, state: "MAPPED" },
  ];
  return (
    <div className="card">
      <div className="panel-h" style={{ padding: "18px 22px 0" }}><h3>Reconciliation</h3><span className="sub">Source total tied to general-ledger control total (Br '000)</span></div>
      <table className="tbl" style={{ marginTop: 8 }}>
        <thead><tr><th>Reconciliation line</th><th className="num">Source total</th><th className="num">GL control</th><th className="num">Variance</th><th>State</th><th></th></tr></thead>
        <tbody>
          {rows.map((r, i) => (
            <tr key={i} className="click">
              <td style={{ fontWeight: 600 }}>{r.item}</td>
              <td className="num tnum">{etb(r.src)}</td>
              <td className="num tnum">{etb(r.gl, r.diff ? 1 : 0)}</td>
              <td className="num tnum" style={{ color: r.diff ? "var(--red)" : "var(--green-ink)", fontWeight: 700 }}>{r.diff ? etb(r.diff, 1) : "0.00"}</td>
              <td><StatusChip s={r.state} /></td>
              <td className="num">{r.diff ? <button className="btn btn-ghost btn-sm" style={{ color: "var(--red)", borderColor: "var(--red-line)" }} onClick={() => setBrk(r)}>Open break</button> : <Icon name="checkCirc" size={17} style={{ color: "var(--green)" }} />}</td>
            </tr>
          ))}
        </tbody>
      </table>
      {brk && <Drawer open={!!brk} onClose={() => setBrk(null)} wide>
        <DrawerHead title="Reconciliation break" sub={brk.item} chip={<StatusChip s={brk.state} />} onClose={() => setBrk(null)} />
        <div className="drawer-body">
          <Banner kind="red" icon="alert"><b>Source ties out to the GL by {etb(Math.abs(brk.diff), 1)} '000.</b> The break must be investigated and cleared before this line can feed the workpaper.</Banner>
          <div className="mt16"><Meta rows={[
            ["Source total", <span className="tnum">{etb(brk.src)} '000</span>],
            ["GL control total", <span className="tnum">{etb(brk.gl, 1)} '000</span>],
            ["Variance", <span className="tnum" style={{ color: "var(--red)", fontWeight: 700 }}>{etb(brk.diff, 1)} '000</span>],
            ["Likely cause", "Timing — off-balance notional booked after GL cut-off"],
            ["Owner", "Yonas Alemu · Credit Risk"],
          ]} /></div>
          <div className="section-label mt20 mb8">Resolution</div>
          {["Accept GL as control (adjust source snapshot)", "Accept source (raise GL adjustment request)", "Investigate — request re-extract"].map((o, i) => (
            <label key={i} className="cl" style={{ cursor: "pointer" }}><input type="radio" name="recon" defaultChecked={i === 2} style={{ marginRight: 6 }} /><span style={{ fontSize: 13, fontWeight: 500 }}>{o}</span></label>
          ))}
        </div>
        <div className="drawer-foot">
          <button className="btn btn-ghost" onClick={() => { setBrk(null); go("exceptions"); }}><Icon name="arrowR" size={14} /> Open as exception</button>
          <button className="btn btn-primary" style={{ marginLeft: "auto" }} onClick={() => setBrk(null)}>Resolve break</button>
        </div>
      </Drawer>}
    </div>
  );
}
function SourceDrawer({ source, onClose, onTriage, go }) {
  const [tab, setTab] = useStateH("Snapshot");
  React.useEffect(() => { if (source) setTab("Snapshot"); }, [source]);
  if (!source) return null;
  const p = PEOPLE[source.owner];
  return (
    <Drawer open={!!source} onClose={onClose} wide>
      <DrawerHead title={source.name} sub={source.system + " · " + source.method} chip={<StatusChip s={source.state} />} onClose={onClose} />
      <Tabs tabs={["Snapshot", "Validation", "Mapping", "Lineage"]} active={tab} onChange={setTab} />
      <div className="drawer-body">
        {tab === "Snapshot" && <React.Fragment>
          {source.synthetic && <div style={{ marginBottom: 16 }}><Banner kind="indigo" icon="flask"><b>Synthetic test source.</b> Used to test workflow only — not bank-confirmed production data. It can never feed an official return.</Banner></div>}
          <Meta rows={[
            ["Source system", source.system],
            ["Integration method", source.method],
            ["Snapshot hash", <span className="mono">{source.hash}</span>],
            ["Captured", source.date],
            ["Row count", <span className="tnum">{source.rows.toLocaleString()}</span>],
            ["Failed rows", source.fails > 0 ? <span style={{ color: "var(--red)" }}>{source.fails}</span> : "0"],
            ["Owner", <span className="center gap8"><Avatar name={p.name} size={20} /> {p.name} · {p.role}</span>],
          ]} />
        </React.Fragment>}

        {tab === "Validation" && (source.fails > 0
          ? <React.Fragment>
              <Banner kind="red" icon="alert"><b>{source.fails} rows failed schema validation.</b> These rows cannot be mapped until triaged.</Banner>
              <div className="mt16">
                <div className="section-label mb8">Sample failures</div>
                {[["Row 4471", "Null residual maturity date"], ["Row 5188", "Currency code 'EBR' not in ISO list"], ["Row 7720", "Notional negative on guarantee record"]].map(([r, m], i) => (
                  <div key={i} className="cl"><span className="cl-ic" style={{ background: "var(--red-soft)", color: "var(--red)" }}><Icon name="alert" size={15} /></span>
                    <div className="grow"><div style={{ fontWeight: 600, fontSize: 13 }}>{r}</div><div className="muted" style={{ fontSize: 12 }}>{m}</div></div></div>
                ))}
              </div>
            </React.Fragment>
          : <div className="center gap10" style={{ padding: "24px 0", color: "var(--green-ink)" }}><Icon name="checkCirc" size={20} /><b>All rows passed schema validation.</b></div>)}

        {tab === "Mapping" && <div>
          <div className="section-label mb8">Field mappings from this source</div>
          {MAPPINGS.slice(0, 3).map((m, i) => (
            <div key={i} className="evi-row">
              <span className="ic-wrap"><Icon name="link" size={15} /></span>
              <div className="grow"><div className="t mono" style={{ fontSize: 12.5 }}>{m.src} → {m.tgt}</div><div className="d">Confidence {m.conf}%</div></div>
              <StatusChip s={m.state} />
            </div>
          ))}
        </div>}

        {tab === "Lineage" && <div>
          <div className="section-label mb12">Where this source flows</div>
          {["Snapshot captured & hashed", "Schema validated", "Mapped to workpaper cells", "Reconciled to GL control", "Cited by NBE return cells"].map((s, i) => {
            const done = i < (source.state === "RECONCILED" ? 4 : source.state === "MAPPED" ? 3 : 2);
            return (
              <div key={i} className="center gap12" style={{ padding: "8px 0" }}>
                <span style={{ width: 22, height: 22, borderRadius: 50, background: done ? "var(--green)" : "var(--surface-2)", color: done ? "#fff" : "var(--ink-4)", display: "grid", placeItems: "center", border: done ? "none" : "1.5px solid var(--border-dark)" }}>{done ? <Icon name="check" size={12} /> : <span style={{ width: 5, height: 5, borderRadius: 50, background: "var(--ink-4)" }} />}</span>
                <span style={{ fontSize: 13, color: done ? "var(--ink)" : "var(--ink-3)", fontWeight: done ? 600 : 500 }}>{s}</span>
              </div>
            );
          })}
        </div>}
      </div>
      <div className="drawer-foot">
        {source.fails > 0 && <button className="btn btn-ghost" style={{ color: "var(--red)", borderColor: "var(--red-line)" }} onClick={() => onTriage(source)}><Icon name="alert" size={15} /> Triage failed rows</button>}
        <button className="btn btn-dark" style={{ marginLeft: "auto" }} onClick={() => go("exceptions")}>Open exceptions <Icon name="arrowR" size={14} /></button>
      </div>
    </Drawer>
  );
}

/* ---------- Triage drawer (failed rows) ---------- */
function TriageDrawer({ source, onClose, go }) {
  const [toastNode, showToast] = useToast();
  if (!source) return null;
  const rows = [
    { r: "4471", issue: "Null residual maturity date", field: "LOAN_RESID_MAT" },
    { r: "5188", issue: "Currency code 'EBR' invalid", field: "CCY_CODE" },
    { r: "7720", issue: "Negative notional on guarantee", field: "GTEE_NOTIONAL" },
    { r: "9043", issue: "Counterparty ID not in master", field: "CPTY_ID" },
  ];
  return (
    <Drawer open={!!source} onClose={onClose} wide>
      <DrawerHead title="Failed-row triage" sub={source.name} chip={<StatusChip s="VALIDATION_FAILED" />} onClose={onClose} />
      <div className="drawer-body">
        <Banner kind="red" icon="alert"><b>{source.fails} rows</b> failed the schema contract. Resolve each by rejecting, fixing inline, or requesting a re-extract.</Banner>
        <table className="tbl" style={{ marginTop: 14 }}>
          <thead><tr><th>Row</th><th>Issue</th><th>Field</th><th></th></tr></thead>
          <tbody>
            {rows.map((r, i) => (
              <tr key={i}>
                <td className="mono">{r.r}</td>
                <td>{r.issue}</td>
                <td><span className="mono" style={{ fontSize: 12 }}>{r.field}</span></td>
                <td className="num"><div className="center gap6" style={{ justifyContent: "flex-end" }}>
                  <button className="btn btn-quiet btn-sm" onClick={() => showToast("Row " + r.r + " marked for inline fix")}>Fix</button>
                  <button className="btn btn-ghost btn-sm" onClick={() => showToast("Row " + r.r + " rejected from this snapshot")}>Reject</button>
                </div></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      <div className="drawer-foot">
        <button className="btn btn-ghost" onClick={() => showToast("Re-extract request queued for source owner")}><Icon name="refresh" size={15} /> Request re-extract</button>
        <button className="btn btn-primary" style={{ marginLeft: "auto" }} onClick={() => showToast("Validation rerun staged on fixture rows")}>Resolve &amp; re-validate</button>
      </div>
      {toastNode}
    </Drawer>
  );
}

window.Harmonizer = Harmonizer;
