// dashboard.jsx — main dashboard screen (live data)

// Approximate normalized (x,y) for each US state in the dot-matrix map (0..1 fractions).
const STATE_COORDS = {
  AL:[0.66,0.74], AK:[0.10,0.93], AZ:[0.22,0.66], AR:[0.55,0.66], CA:[0.10,0.55],
  CO:[0.32,0.50], CT:[0.86,0.36], DE:[0.84,0.45], FL:[0.78,0.82], GA:[0.72,0.71],
  HI:[0.20,0.93], ID:[0.22,0.32], IL:[0.60,0.45], IN:[0.65,0.46], IA:[0.55,0.40],
  KS:[0.48,0.52], KY:[0.67,0.54], LA:[0.55,0.78], ME:[0.92,0.20], MD:[0.82,0.45],
  MA:[0.88,0.32], MI:[0.66,0.34], MN:[0.53,0.28], MS:[0.60,0.74], MO:[0.55,0.55],
  MT:[0.30,0.22], NE:[0.45,0.42], NV:[0.18,0.45], NH:[0.88,0.27], NJ:[0.83,0.40],
  NM:[0.30,0.65], NY:[0.81,0.32], NC:[0.78,0.58], ND:[0.45,0.22], OH:[0.71,0.44],
  OK:[0.48,0.62], OR:[0.13,0.25], PA:[0.78,0.40], RI:[0.88,0.35], SC:[0.76,0.65],
  SD:[0.45,0.32], TN:[0.65,0.61], TX:[0.45,0.78], UT:[0.25,0.46], VT:[0.86,0.25],
  VA:[0.78,0.51], WA:[0.16,0.16], WV:[0.74,0.48], WI:[0.59,0.32], WY:[0.32,0.34],
};

function fmtNumber(num) {
  if (!num) return "";
  const m = String(num).match(/^\+1(\d{3})(\d{3})(\d{4})$/);
  return m ? `(${m[1]}) ${m[2]}-${m[3]}` : num;
}
function fmtDuration(s) {
  if (s == null) return "—";
  const n = Number(s);
  if (!Number.isFinite(n) || n <= 0) return "0:00";
  const m = Math.floor(n / 60), sec = n % 60;
  return `${m}:${String(sec).padStart(2, "0")}`;
}
function fmtRelative(iso) {
  if (!iso) return "";
  const t = new Date(iso).getTime();
  const diffSec = Math.max(0, (Date.now() - t) / 1000);
  if (diffSec < 60) return `${Math.round(diffSec)}s ago`;
  if (diffSec < 3600) return `${Math.round(diffSec / 60)}m ago`;
  if (diffSec < 86400) return `${Math.round(diffSec / 3600)}h ago`;
  return `${Math.round(diffSec / 86400)}d ago`;
}
function fmtPct(n) { return (n == null ? 0 : Math.round(n)) + "%"; }
function fmtDelta(n) {
  if (n == null || isNaN(n)) return "—";
  const sign = n > 0 ? "+" : "";
  return `${sign}${Math.round(n)}%`;
}

function Dashboard({ workspace }) {
  const wid = workspace.id;
  const [range, setRange] = React.useState("7d");

  const stats        = useApi(() => API.dashboard.stats(wid, range), [wid, range]);
  const callVolume   = useApi(() => API.dashboard.callVolume(wid, range), [wid, range]);
  const callerMix    = useApi(() => API.dashboard.callerMix(wid, range), [wid, range]);
  const geographic   = useApi(() => API.dashboard.geographic(wid, range), [wid, range]);
  const topNumbers   = useApi(() => API.dashboard.topNumbers(wid, range, 5), [wid, range]);
  const topSources   = useApi(() => API.dashboard.topSources(wid, range, 5), [wid, range]);
  const recentCalls  = useApi(() => API.dashboard.recentCalls(wid, 5), [wid]);

  // Live updates: refresh just the recent-calls + stats panels when any
  // call event fires for this workspace. Cheap; the API is local. We
  // intentionally don't refresh top-numbers/sources/geographic on every
  // event — those move slowly enough to come from the existing 30s window.
  useWorkspaceEvents(wid, React.useCallback((msg) => {
    if (msg.event === "call.ringing" || msg.event === "call.answered" || msg.event === "call.ended") {
      recentCalls.reload();
      if (msg.event === "call.ended") stats.reload();
    }
  }, [recentCalls.reload, stats.reload]));

  const s = stats.data || {};
  const cv = callVolume.data || { labels: [], answered: [], missed: [] };
  const cm = callerMix.data || { firstTimePct: 0, repeatPct: 0, qualifiedCount: 0, qualifiedPct: 0 };

  const kpis = [
    { lbl: "Total calls", val: (s.totalCalls ?? 0).toLocaleString(), delta: fmtDelta(s.deltas?.totalCalls), up: (s.deltas?.totalCalls ?? 0) >= 0,
      spark: cv.answered.length ? cv.answered : [0,0,0,0,0,0,0] },
    { lbl: "Answered", val: fmtPct(s.answeredPct), delta: fmtDelta(s.deltas?.answered), up: (s.deltas?.answered ?? 0) >= 0,
      spark: cv.answered.length ? cv.answered : [0,0,0,0,0,0,0] },
    { lbl: "Avg duration", val: fmtDuration(s.avgDurationSeconds), delta: "—", up: true,
      spark: cv.answered.length ? cv.answered : [0,0,0,0,0,0,0] },
    { lbl: "Unique callers", val: (s.uniqueCallers ?? 0).toLocaleString(), delta: "—", up: true,
      spark: cv.answered.length ? cv.answered : [0,0,0,0,0,0,0] },
  ];

  // Bucket labels for the area chart
  const cvLabels = (cv.labels || []).map((iso) => {
    if (!iso) return "";
    const d = new Date(iso);
    if (range === "1d") return d.getHours() + (d.getHours() >= 12 ? "p" : "a");
    if (range === "7d") return d.toLocaleDateString(undefined, { weekday: "short" });
    return `${d.getMonth() + 1}/${d.getDate()}`;
  });

  // Map dots: filter to states we know coords for
  const mapDots = (geographic.data || [])
    .map((g) => {
      const c = STATE_COORDS[g.state];
      if (!c) return null;
      return { x: c[0], y: c[1], size: Math.max(0.3, g.relativeSize || 0.3) };
    })
    .filter(Boolean);

  // Caller mix donut percent
  const firstPct = Math.round(cm.firstTimePct || 0);

  return (
    <div className="page-inner wide">
      <div className="row between" style={{alignItems:"flex-start", marginBottom: 28}}>
        <div>
          <div className="eyebrow">Overview</div>
          <h1 className="page-title" style={{marginTop:6}}>Hello.</h1>
          <div className="page-sub">Here's what's happening at <span style={{color:"var(--ink)", fontWeight:500}}>{workspace.name}</span> today.</div>
        </div>
        <div className="row g8">
          <div className="seg">
            {["1d","7d","30d"].map(r => (
              <button key={r} className={range === r ? "on" : ""} onClick={() => setRange(r)}>{r === "1d" ? "Today" : r === "7d" ? "7 days" : "30 days"}</button>
            ))}
          </div>
          <button className="btn btn-secondary btn-sm"><I.dl size={13}/> Export</button>
        </div>
      </div>

      {stats.error && <ErrorChip msg={stats.error.message}/>}

      {/* KPIs */}
      <div className="kpi-grid">
        {kpis.map((k, i) => (
          <div key={i} className="kpi">
            <div className="kpi-lbl">{k.lbl}</div>
            <div className="row between" style={{alignItems:"baseline"}}>
              <div className="kpi-val">{stats.loading ? "…" : k.val}</div>
              <div className={"kpi-delta " + (k.up ? "up" : "down")}>{k.delta}</div>
            </div>
            <div style={{marginTop:4, marginLeft:-2, marginRight:-2}}>
              <Sparkline data={k.spark} color={k.up ? "var(--good)" : "var(--bad)"} height={34} />
            </div>
          </div>
        ))}
      </div>

      {/* Main area */}
      <div style={{display:"grid", gridTemplateColumns:"2fr 1fr", gap:16, marginTop:24}}>
        <div className="card">
          <div className="card-h">
            <div>
              <h3>Call volume</h3>
              <div className="sub">Answered vs missed</div>
            </div>
            <div className="row g12">
              <div className="row g8" style={{fontSize:12, color:"var(--ink-3)"}}><span style={{width:8, height:8, borderRadius:2, background:"var(--accent)"}}/>Answered</div>
              <div className="row g8" style={{fontSize:12, color:"var(--ink-3)"}}><span style={{width:8, height:8, borderRadius:2, background:"color-mix(in oklab, var(--bad) 50%, var(--bg-sunken))"}}/>Missed</div>
            </div>
          </div>
          <div className="card-b">
            {callVolume.loading
              ? <Skeleton h={180}/>
              : <AreaChart
                  series={[
                    { name: "Answered", color: "var(--accent)", data: cv.answered },
                    { name: "Missed", color: "color-mix(in oklab, var(--bad) 60%, var(--bg))", data: cv.missed },
                  ]}
                  labels={cvLabels}
                />
            }
          </div>
        </div>

        <div className="card">
          <div className="card-h">
            <div><h3>Caller mix</h3><div className="sub">First-time vs repeat</div></div>
          </div>
          <div className="card-b" style={{display:"flex", flexDirection:"column", gap:20}}>
            <div style={{display:"flex", alignItems:"center", justifyContent:"center", paddingTop:8}}>
              <Donut pct={firstPct} />
            </div>
            <div>
              <div className="row between" style={{padding:"8px 0"}}>
                <div className="row g8"><span style={{width:8, height:8, borderRadius:2, background:"var(--accent)"}}/>First-time</div>
                <div className="num" style={{fontWeight:500}}>{firstPct}%</div>
              </div>
              <div style={{height:".5px", background:"var(--line)"}}/>
              <div className="row between" style={{padding:"8px 0"}}>
                <div className="row g8"><span style={{width:8, height:8, borderRadius:2, background:"var(--ink-5)"}}/>Repeat</div>
                <div className="num" style={{fontWeight:500}}>{Math.round(cm.repeatPct || 0)}%</div>
              </div>
              <div style={{height:".5px", background:"var(--line)"}}/>
              <div className="row between" style={{padding:"8px 0"}}>
                <div className="row g8"><span style={{width:8, height:8, borderRadius:2, background:"var(--good)"}}/>Qualified</div>
                <div className="num" style={{fontWeight:500}}>{cm.qualifiedCount ?? 0} <span style={{color:"var(--ink-4)", fontWeight:400}}>({Math.round(cm.qualifiedPct || 0)}%)</span></div>
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* Map */}
      <div className="card" style={{marginTop:16}}>
        <div className="card-h">
          <div><h3>Geographic distribution</h3><div className="sub">Where callers are dialing from</div></div>
          <div className="row g8" style={{fontSize:12, color:"var(--ink-4)"}}>{mapDots.length} active state{mapDots.length === 1 ? "" : "s"}</div>
        </div>
        <div className="card-b">
          <USMap dots={mapDots} />
        </div>
      </div>

      {/* Top numbers + sources */}
      <div style={{display:"grid", gridTemplateColumns:"1.4fr 1fr", gap:16, marginTop:16}}>
        <div className="card">
          <div className="card-h">
            <div><h3>Top-performing numbers</h3><div className="sub">By call volume · {range === "1d" ? "today" : range === "7d" ? "last 7 days" : "last 30 days"}</div></div>
          </div>
          <table className="table">
            <thead><tr><th>Number</th><th>Campaign</th><th style={{textAlign:"right"}}>Calls</th><th style={{textAlign:"right"}}>Answer rate</th><th style={{textAlign:"right"}}>Avg</th></tr></thead>
            <tbody>
              {topNumbers.loading && <tr><td colSpan="5" style={{textAlign:"center", color:"var(--ink-4)", padding:20}}>Loading…</td></tr>}
              {!topNumbers.loading && (topNumbers.data || []).length === 0 && (
                <tr><td colSpan="5" style={{textAlign:"center", color:"var(--ink-4)", padding:20}}>No data for this range</td></tr>
              )}
              {!topNumbers.loading && (topNumbers.data || []).map((n) => {
                const ar = n.answerRate ?? 0;
                return (
                  <tr key={n.id}>
                    <td className="num" style={{color:"var(--ink)", fontWeight:500}}>{n.friendlyName || fmtNumber(n.number)}</td>
                    <td className="muted">{n.campaign || "—"}</td>
                    <td className="num" style={{textAlign:"right"}}>{n.calls}</td>
                    <td style={{textAlign:"right"}}>
                      <span className={"pill " + (ar >= 85 ? "good" : ar >= 70 ? "info" : "warn")}>{ar}%</span>
                    </td>
                    <td className="num" style={{textAlign:"right"}}>{fmtDuration(n.avgDurationSeconds)}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>

        <div className="card">
          <div className="card-h">
            <div><h3>Top sources</h3><div className="sub">Attribution · {range === "1d" ? "today" : range === "7d" ? "last 7 days" : "last 30 days"}</div></div>
          </div>
          <div className="card-b" style={{display:"flex", flexDirection:"column", gap:14}}>
            {topSources.loading && <div style={{color:"var(--ink-4)", fontSize:13, textAlign:"center", padding:10}}>Loading…</div>}
            {!topSources.loading && (topSources.data || []).length === 0 && (
              <div style={{color:"var(--ink-4)", fontSize:13, textAlign:"center", padding:10}}>No source data</div>
            )}
            {!topSources.loading && (topSources.data || []).map((src, i) => {
              const label = src.source ? src.source.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()) : "Direct";
              return (
                <div key={i}>
                  <div className="row between" style={{marginBottom:6}}>
                    <div style={{fontSize:13, color:"var(--ink-2)", fontWeight:500}}>{label}</div>
                    <div className="num" style={{fontSize:12, color:"var(--ink-4)"}}>{src.calls} call{src.calls === 1 ? "" : "s"} · {src.pct}%</div>
                  </div>
                  <div style={{height:6, background:"var(--bg-sunken)", borderRadius:3, overflow:"hidden"}}>
                    <div style={{height:"100%", width: src.pct + "%", background:"var(--accent)", opacity: 1 - i * 0.15}}/>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      </div>

      {/* Recent calls */}
      <div className="card" style={{marginTop:16}}>
        <div className="card-h">
          <div><h3>Recent calls</h3><div className="sub">Live feed</div></div>
        </div>
        <table className="table">
          <thead><tr><th>Caller</th><th>Location</th><th>To</th><th>Campaign</th><th>Status</th><th style={{textAlign:"right"}}>Duration</th><th style={{textAlign:"right"}}>When</th></tr></thead>
          <tbody>
            {recentCalls.loading && <tr><td colSpan="7" style={{textAlign:"center", color:"var(--ink-4)", padding:20}}>Loading…</td></tr>}
            {!recentCalls.loading && (recentCalls.data || []).length === 0 && (
              <tr><td colSpan="7" style={{textAlign:"center", color:"var(--ink-4)", padding:20}}>No recent calls</td></tr>
            )}
            {!recentCalls.loading && (recentCalls.data || []).map((c) => (
              <tr key={c.id}>
                <td>
                  <div className="row g8">
                    <div className="num" style={{color:"var(--ink)", fontWeight:500}}>{c.callerName || fmtNumber(c.fromNumber || c.callerNumber)}</div>
                    {c.isRepeatCaller && <span className="pill info" style={{height:18, fontSize:10}}>Repeat</span>}
                  </div>
                </td>
                <td className="muted">{[c.callerLocation, c.callerState].filter(Boolean).join(", ") || "—"}</td>
                <td className="num">{c.numberName || "—"}</td>
                <td className="muted">{c.campaign || "—"}</td>
                <td>
                  <span className={"pill " + (c.status === "answered" ? "good" : "bad")}>
                    <span className="dot"/>{c.status === "answered" ? "Answered" : c.status === "voicemail" ? "Voicemail" : "Missed"}
                  </span>
                </td>
                <td className="num" style={{textAlign:"right"}}>{fmtDuration(c.durationSeconds)}</td>
                <td className="muted" style={{textAlign:"right"}}>{fmtRelative(c.startedAt)}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function Donut({ pct }) {
  const r = 52, c = 2 * Math.PI * r;
  const safe = Math.max(0, Math.min(100, pct || 0));
  return (
    <svg width="140" height="140" viewBox="0 0 140 140">
      <circle cx="70" cy="70" r={r} fill="none" stroke="var(--bg-sunken)" strokeWidth="14" />
      <circle cx="70" cy="70" r={r} fill="none" stroke="var(--accent)" strokeWidth="14"
        strokeDasharray={`${(safe/100)*c} ${c}`} strokeLinecap="round"
        transform="rotate(-90 70 70)" />
      <text x="70" y="72" textAnchor="middle" fontFamily="var(--serif)" fontSize="32" fill="var(--ink)" dominantBaseline="middle">{safe}%</text>
      <text x="70" y="92" textAnchor="middle" fontSize="10" fill="var(--ink-4)" letterSpacing="0.05em">FIRST-TIME</text>
    </svg>
  );
}

function Skeleton({ h = 100 }) {
  return <div style={{height:h, background:"var(--bg-sunken)", borderRadius:8, animation:"pulse 1.4s ease-in-out infinite"}}/>;
}

function ErrorChip({ msg }) {
  return (
    <div style={{margin:"12px 0", padding:"10px 14px", background:"rgba(220,38,38,.08)", border:".5px solid rgba(220,38,38,.2)", borderRadius:8, fontSize:13, color:"#B91C1C"}}>
      {msg || "Something went wrong"}
    </div>
  );
}

Object.assign(window, { Dashboard, Skeleton, ErrorChip, fmtNumber, fmtDuration, fmtRelative });
