// Management Dashboard - KPI cards + donut + bar + line + drill-down

const DashboardPage = ({ tenant, period, setPeriod, tasks, taskHistory, subprocesses, users, positions, departments, divisions, mainProcesses, processes, onGoMatrix, tweaks }) => {
  const [statusFilter, setStatusFilter] = useState(null); // drill-down
  const [deptFilter, setDeptFilter] = useState(null);
  const [divFilter, setDivFilter] = useState(null);

  const THAI_MONTHS = ["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."];
  const periodLabel = `${THAI_MONTHS[period.month-1]} ${period.year+543}`;
  const ymKey = `${period.year}-${String(period.month).padStart(2,"0")}`;

  // ---- Build "period tasks": one task instance per sub-process for the selected month ----
  // Source: taskHistory (for daily/weekly/monthly/quarterly) + tasks snapshot (current, ad-hoc)
  const periodTasks = useMemo(() => {
    const out = [];
    subprocesses.forEach(sp => {
      const hist = taskHistory?.[sp.id] || [];
      if (sp.frequency === "daily") {
        // For daily — count all instances in that month and roll up to a single "rep" status
        const monthEntries = hist.filter(h => h.date.slice(0,7) === ymKey);
        if (monthEntries.length === 0) return;
        // For the dashboard, treat each daily instance as its own task so KPIs reflect day-level counts
        monthEntries.forEach(h => {
          out.push({ sub_process_id: sp.id, status: h.status, due_date: h.date, updated: h.updated, overdue: false, frequency: sp.frequency });
        });
      } else if (sp.frequency === "weekly") {
        const monthEntries = hist.filter(h => h.date.slice(0,7) === ymKey);
        monthEntries.forEach(h => {
          out.push({ sub_process_id: sp.id, status: h.status, due_date: h.date, updated: h.updated, overdue: false, frequency: sp.frequency });
        });
      } else if (sp.frequency === "monthly" || sp.frequency === "quarterly") {
        const match = hist.find(h => h.date.slice(0,7) === ymKey);
        if (match) {
          out.push({ sub_process_id: sp.id, status: match.status, due_date: match.date, updated: match.updated, overdue: false, frequency: sp.frequency });
        }
      } else {
        // ad-hoc — pull instances within the month
        const monthEntries = hist.filter(h => h.date.slice(0,7) === ymKey);
        monthEntries.forEach(h => {
          out.push({ sub_process_id: sp.id, status: h.status, due_date: h.date, updated: h.updated, overdue: false, frequency: sp.frequency });
        });
      }
    });
    return out;
  }, [subprocesses, taskHistory, ymKey]);

  // Apply division/department filter to periodTasks
  const filteredTasks = useMemo(() => {
    return periodTasks.filter(t => {
      const sp = subprocesses.find(s => s.id === t.sub_process_id);
      if (!sp) return false;
      const pos = positions.find(p => p.id === sp.R);
      if (!pos) return false;
      if (divFilter && pos.division_id !== divFilter) return false;
      if (deptFilter && pos.department_id !== deptFilter) return false;
      return true;
    });
  }, [periodTasks, subprocesses, positions, divFilter, deptFilter]);

  // KPI counts
  const counts = useMemo(() => {
    const total = filteredTasks.length;
    const by = { blank:0, P:0, A:0, C:0, S:0, overdue:0 };
    filteredTasks.forEach(t => {
      by[t.status] = (by[t.status] || 0) + 1;
      if (t.overdue && t.status !== "S") by.overdue++;
    });
    return { total, ...by };
  }, [filteredTasks]);

  const completionRate = counts.total ? Math.round(counts.S / counts.total * 100) : 0;

  // status distribution (donut)
  const donut = [
    { k:"S", l:"สำเร็จ", v:counts.S, color:"#10b981" },
    { k:"A", l:"รอตรวจสอบ", v:counts.A, color:"#7c3aed" },
    { k:"P", l:"รอจัดทำ", v:counts.P, color:"#3b82f6" },
    { k:"C", l:"มี Comment", v:counts.C, color:"#f59e0b" },
    { k:"blank", l:"ยังไม่ถึงกำหนด", v:counts.blank, color:"#cbd5e1" },
  ];

  // dept completion (bar)
  const deptStats = useMemo(() => {
    const map = {};
    filteredTasks.forEach(t => {
      const sp = subprocesses.find(s => s.id === t.sub_process_id);
      if (!sp) return;
      const pos = positions.find(p => p.id === sp.R);
      if (!pos) return;
      const d = departments.find(dp => dp.id === pos.department_id);
      if (!d) return;
      if (!map[d.id]) map[d.id] = { id:d.id, name:d.name, short:d.short, total:0, s:0, c:0, a:0, p:0, b:0 };
      map[d.id].total++;
      if (t.status==="S") map[d.id].s++;
      else if (t.status==="C") map[d.id].c++;
      else if (t.status==="A") map[d.id].a++;
      else if (t.status==="P") map[d.id].p++;
      else map[d.id].b++;
    });
    return Object.values(map).map(d => ({ ...d, pct: d.total ? Math.round(d.s/d.total*100) : 0 })).sort((a,b)=>b.pct-a.pct);
  }, [filteredTasks, subprocesses, positions, departments]);

  // monthly trend — compute from taskHistory across the last 6 months
  const trend = useMemo(() => {
    const months = [];
    for (let i = 5; i >= 0; i--) {
      const d = new Date(period.year, period.month - 1, 1);
      d.setMonth(d.getMonth() - i);
      const key = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,"0")}`;
      let total = 0, s = 0;
      subprocesses.forEach(sp => {
        const hist = taskHistory?.[sp.id] || [];
        hist.filter(h => h.date.slice(0,7) === key).forEach(h => {
          const pos = positions.find(p => p.id === sp.R);
          if (divFilter && pos?.division_id !== divFilter) return;
          if (deptFilter && pos?.department_id !== deptFilter) return;
          total++; if (h.status === "S") s++;
        });
      });
      months.push({ m: THAI_MONTHS[d.getMonth()], key, rate: total ? Math.round(s/total*100) : 0, total });
    }
    return months;
  }, [taskHistory, subprocesses, positions, period, divFilter, deptFilter]);

  // Top 10 waiting approval
  const waitingApproval = useMemo(() => {
    return filteredTasks.filter(t=>t.status==="A").slice(0,10).map(t => {
      const sp = subprocesses.find(s=>s.id===t.sub_process_id);
      const r = positions.find(p=>p.id===sp?.R);
      const a = positions.find(p=>p.id===sp?.A);
      const rUser = users.find(u=>u.positions.includes(sp?.R));
      const aUser = users.find(u=>u.positions.includes(sp?.A));
      return { ...t, sp, r, a, rUser, aUser };
    });
  }, [filteredTasks, subprocesses, positions, users]);

  // filtered drill-down list
  const drillRows = useMemo(() => {
    return filteredTasks.filter(t => {
      if (statusFilter && t.status !== statusFilter) return false;
      return true;
    }).map(t => {
      const sp = subprocesses.find(s=>s.id===t.sub_process_id);
      const proc = processes.find(p=>p.id===sp?.process_id);
      const mp = mainProcesses.find(m=>m.id===sp?.main_process_id);
      const r = positions.find(p=>p.id===sp?.R);
      const a = positions.find(p=>p.id===sp?.A);
      const rUser = users.find(u=>u.positions.includes(sp?.R));
      const aUser = users.find(u=>u.positions.includes(sp?.A));
      return { task:t, sp, proc, mp, r, a, rUser, aUser };
    });
  }, [filteredTasks, statusFilter, subprocesses, processes, mainProcesses, positions, users]);

  const hasAnyFilter = divFilter || deptFilter || statusFilter;

  return (
    <div className="p-6 space-y-5">
      <PageHeader
        eyebrow={`${tenant.company_short} · ${periodLabel}`}
        title="Management Dashboard"
        subtitle="ภาพรวมสถานะการจัดทำงานตามหลัก RACI Matrix"
        right={<>
          <Button icon="download" variant="secondary" onClick={()=>{
            downloadCsv(`${tenant.tenant_code}_dashboard_${period.year}-${String(period.month).padStart(2,"0")}.csv`,
              ["Sub-process","Main Process","Process","R","A","Due","Status","Last Update"],
              drillRows.map(r => [r.sp.name, r.mp?.name, r.proc?.name, r.rUser?.full_name||"", r.aUser?.full_name||"", r.task.due_date, STATUS_META[r.task.status]?.label, r.task.updated||""]));
          }}>ส่งออกรายงาน</Button>
          <Button icon="arrowRight" onClick={()=>onGoMatrix()}>เปิด RACI Matrix</Button>
        </>}
      />

      {/* Filter bar */}
      <div className="bg-white rounded-2xl border border-ink-100 px-4 py-3 flex items-center gap-3 flex-wrap">
        <div className="flex items-center gap-2 text-[12px] text-ink-500">
          <Icon name="filter" size={13} className="text-ink-400"/>
          <span className="font-semibold uppercase tracking-wider text-[10.5px] text-ink-500">ตัวกรอง</span>
        </div>

        {/* Period */}
        <div className="flex items-center gap-1.5 h-9 px-2.5 bg-ink-50 border border-ink-200 rounded-lg text-[12.5px]">
          <Icon name="calendar" size={12} className="text-ink-500"/>
          <select value={period.month} onChange={e=>setPeriod(p=>({...p, month:+e.target.value}))} className="bg-transparent font-medium focus:outline-none">
            {THAI_MONTHS.map((m,i)=><option key={i} value={i+1}>{m}</option>)}
          </select>
          <select value={period.year} onChange={e=>setPeriod(p=>({...p, year:+e.target.value}))} className="bg-transparent font-mono font-medium focus:outline-none">
            {(() => { const cy = new Date().getFullYear(); return [cy-2, cy-1, cy, cy+1]; })().map(y=><option key={y} value={y}>{y+543}</option>)}
          </select>
        </div>

        {/* Division */}
        <Select value={divFilter || ""} onChange={e=>{ setDivFilter(e.target.value || null); setDeptFilter(null); }} className="!w-[170px]">
          <option value="">ทุก Division</option>
          {divisions.map(d => <option key={d.id} value={d.id}>{d.name}</option>)}
        </Select>

        {/* Department */}
        <Select value={deptFilter || ""} onChange={e=>setDeptFilter(e.target.value || null)} className="!w-[180px]">
          <option value="">ทุก Department</option>
          {departments.filter(d => !divFilter || d.division_id === divFilter).map(d => <option key={d.id} value={d.id}>{d.name}</option>)}
        </Select>

        {hasAnyFilter && (
          <button onClick={()=>{ setStatusFilter(null); setDivFilter(null); setDeptFilter(null); }}
            className="text-[12px] text-brand-600 hover:text-brand-700 font-medium flex items-center gap-1">
            <Icon name="x" size={12}/>ล้างตัวกรองทั้งหมด
          </button>
        )}

        <div className="ml-auto text-[11.5px] text-ink-500 font-mono">
          {filteredTasks.length} / {periodTasks.length} งาน
        </div>
      </div>

      {/* KPI strip */}
      <div className="grid grid-cols-2 lg:grid-cols-4 xl:grid-cols-8 gap-3">
        <KpiCard icon="table" tone="indigo" label="งานทั้งหมด" value={counts.total} trend={`ใน${periodLabel}`} onClick={()=>setStatusFilter(null)}/>
        <KpiCard icon="clock" tone="slate" label="ยังไม่ถึงกำหนด" value={counts.blank} trend="พร้อมจัดทำในอนาคต" onClick={()=>setStatusFilter("blank")} active={statusFilter==="blank"}/>
        <KpiCard icon="play" tone="sky" label="รอจัดทำ (P)" value={counts.P} trend="ผู้รับผิดชอบ R" onClick={()=>setStatusFilter("P")} active={statusFilter==="P"}/>
        <KpiCard icon="checkCircle" tone="violet" label="รอตรวจสอบ (A)" value={counts.A} trend="ผู้ตรวจสอบ A" onClick={()=>setStatusFilter("A")} active={statusFilter==="A"}/>
        <KpiCard icon="message" tone="amber" label="แก้ไข (C)" value={counts.C} trend="มี Comment" onClick={()=>setStatusFilter("C")} active={statusFilter==="C"}/>
        <KpiCard icon="checkCircle" tone="emerald" label="สำเร็จ (S)" value={counts.S} trend={`${completionRate}% completion`} onClick={()=>setStatusFilter("S")} active={statusFilter==="S"}/>
        <KpiCard icon="alert" tone="rose" label="เลยกำหนด" value={counts.overdue} trend="ต้องเร่งดำเนินการ"/>
        <KpiCard icon="trending" tone="indigo" label="Completion Rate" value={completionRate + "%"} trend={`ของ${periodLabel}`}/>
      </div>

      {/* charts row */}
      <div className="grid grid-cols-12 gap-4">
        {/* Donut */}
        <div className="col-span-12 lg:col-span-4 bg-white rounded-2xl border border-ink-100 p-5">
          <div className="flex items-center justify-between mb-3">
            <div>
              <div className="text-[13.5px] font-semibold text-ink-900">การกระจายสถานะ</div>
              <div className="text-[11.5px] text-ink-500">งานทั้งหมด {counts.total} รายการ</div>
            </div>
            <Icon name="pie" size={14} className="text-ink-400"/>
          </div>
          <DonutChart data={donut} total={counts.total} center={completionRate + "%"} centerLabel="Completion"/>
          <div className="mt-3 space-y-1.5">
            {donut.map(d => {
              const pct = counts.total ? Math.round(d.v/counts.total*100) : 0;
              return (
                <button key={d.k} onClick={()=>setStatusFilter(statusFilter===d.k?null:d.k)} className={`w-full flex items-center justify-between gap-3 px-2 py-1 rounded-md text-left transition ${statusFilter===d.k?"bg-ink-100":"hover:bg-ink-50"}`}>
                  <div className="flex items-center gap-2 min-w-0">
                    <span className="w-2.5 h-2.5 rounded-sm shrink-0" style={{background:d.color}}/>
                    <span className="text-[12px] text-ink-700 truncate">{d.l}</span>
                  </div>
                  <div className="flex items-center gap-2 font-mono">
                    <span className="text-[12px] font-semibold text-ink-900 w-6 text-right">{d.v}</span>
                    <span className="text-[11px] text-ink-500 w-9 text-right">{pct}%</span>
                  </div>
                </button>
              );
            })}
          </div>
        </div>

        {/* Bar - departments */}
        <div className="col-span-12 lg:col-span-5 bg-white rounded-2xl border border-ink-100 p-5">
          <div className="flex items-center justify-between mb-3">
            <div>
              <div className="text-[13.5px] font-semibold text-ink-900">Completion rate ตามฝ่าย</div>
              <div className="text-[11.5px] text-ink-500">เปรียบเทียบความสำเร็จของแต่ละ Department</div>
            </div>
            <Icon name="bar" size={14} className="text-ink-400"/>
          </div>
          <div className="space-y-2.5">
            {deptStats.slice(0, 8).map(d => (
              <button key={d.id} onClick={()=>setDeptFilter(deptFilter===d.id?null:d.id)} className="w-full text-left">
                <div className="flex items-center justify-between text-[12px] mb-1">
                  <div className="flex items-center gap-2">
                    <span className="w-7 h-5 rounded text-[10px] font-bold text-ink-700 bg-ink-100 flex items-center justify-center">{d.short}</span>
                    <span className="text-ink-800 font-medium truncate">{d.name}</span>
                  </div>
                  <div className="flex items-center gap-2 font-mono">
                    <span className="text-ink-500 text-[11px]">{d.s}/{d.total}</span>
                    <span className={`font-semibold ${d.pct>=80?"text-emerald-600":d.pct>=50?"text-amber-600":"text-rose-600"}`}>{d.pct}%</span>
                  </div>
                </div>
                <div className="h-2 bg-ink-100 rounded-full overflow-hidden flex">
                  <div className="bg-emerald-500" style={{width:`${(d.s/d.total)*100}%`}}/>
                  <div className="bg-violet-500" style={{width:`${(d.a/d.total)*100}%`}}/>
                  <div className="bg-amber-500" style={{width:`${(d.c/d.total)*100}%`}}/>
                  <div className="bg-blue-500" style={{width:`${(d.p/d.total)*100}%`}}/>
                  <div className="bg-ink-300" style={{width:`${(d.b/d.total)*100}%`}}/>
                </div>
              </button>
            ))}
          </div>
          <div className="mt-3 pt-3 border-t border-ink-100 flex items-center gap-3 flex-wrap text-[10.5px] text-ink-500">
            <LegendDot color="bg-emerald-500" label="S สำเร็จ"/>
            <LegendDot color="bg-violet-500" label="A รอตรวจสอบ"/>
            <LegendDot color="bg-amber-500" label="C แก้ไข"/>
            <LegendDot color="bg-blue-500" label="P รอจัดทำ"/>
            <LegendDot color="bg-ink-300" label="ยังไม่ถึงกำหนด"/>
          </div>
        </div>

        {/* Trend + ranking */}
        <div className="col-span-12 lg:col-span-3 space-y-4">
          <div className="bg-white rounded-2xl border border-ink-100 p-5">
            <div className="flex items-center justify-between mb-2">
              <div>
                <div className="text-[13.5px] font-semibold text-ink-900">Trend Completion</div>
                <div className="text-[11.5px] text-ink-500">6 เดือนล่าสุด</div>
              </div>
              <Icon name="trending" size={14} className="text-ink-400"/>
            </div>
            <LineChart data={trend} width={260} height={120}/>
          </div>

          <div className="bg-white rounded-2xl border border-ink-100 p-4">
            <div className="text-[13.5px] font-semibold text-ink-900 mb-2">Top 3 ฝ่ายที่สำเร็จสูงสุด</div>
            <div className="space-y-2">
              {deptStats.slice(0,3).map((d,i) => (
                <div key={d.id} className="flex items-center gap-2">
                  <div className={`w-6 h-6 rounded-md text-white font-bold text-[11px] flex items-center justify-center ${i===0?"bg-amber-500":i===1?"bg-ink-400":"bg-amber-700"}`}>#{i+1}</div>
                  <div className="flex-1 text-[12px] text-ink-800 truncate">{d.name}</div>
                  <div className="font-mono text-[12px] font-semibold text-emerald-600">{d.pct}%</div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>

      {/* Lower row: waiting approval + drilldown list */}
      <div className="grid grid-cols-12 gap-4">
        <div className="col-span-12 lg:col-span-5 bg-white rounded-2xl border border-ink-100 overflow-hidden">
          <div className="px-4 py-3 border-b border-ink-100 flex items-center justify-between">
            <div>
              <div className="text-[13.5px] font-semibold text-ink-900">Top {waitingApproval.length} งานรอตรวจสอบ</div>
              <div className="text-[11.5px] text-ink-500">งานที่รอการ Approve โดยผู้ตรวจสอบ (A)</div>
            </div>
            <Badge color="violet" icon="checkCircle">{waitingApproval.length} งาน</Badge>
          </div>
          {waitingApproval.length === 0 ? (
            <EmptyState icon="checkCircle" title="ไม่มีงานรอตรวจสอบ" subtitle="ยอดเยี่ยมเลย!" />
          ) : (
            <div className="divide-y divide-ink-100">
              {waitingApproval.map(t => (
                <div key={t.sub_process_id} className="px-4 py-2.5 hover:bg-ink-50/60 flex items-center gap-3">
                  <RaciBadge kind="A" size="sm"/>
                  <div className="flex-1 min-w-0">
                    <div className="text-[12.5px] font-medium text-ink-900 truncate">{t.sp.name}</div>
                    <div className="text-[10.5px] text-ink-500 truncate">R: {t.rUser?.full_name || "—"} · A: {t.aUser?.full_name || "—"}</div>
                  </div>
                  <div className="text-right">
                    <div className="text-[10.5px] text-ink-500">Due</div>
                    <div className="text-[11px] font-mono text-ink-700">{t.due_date}</div>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>

        {/* drilldown */}
        <div className="col-span-12 lg:col-span-7 bg-white rounded-2xl border border-ink-100 overflow-hidden">
          <div className="px-4 py-3 border-b border-ink-100 flex items-center justify-between gap-3 flex-wrap">
            <div className="flex items-center gap-2">
              <div className="text-[13.5px] font-semibold text-ink-900">รายการงาน (Drill-down)</div>
              {(statusFilter || deptFilter || divFilter) && (
                <button onClick={()=>{ setStatusFilter(null); setDeptFilter(null); setDivFilter(null); }} className="text-[11px] text-brand-600 hover:underline">ล้างตัวกรอง</button>
              )}
            </div>
            <div className="flex items-center gap-1.5 flex-wrap">
              {statusFilter && <Badge color="indigo">สถานะ: {STATUS_META[statusFilter].label}</Badge>}
              {deptFilter && <Badge color="indigo">ฝ่าย: {departments.find(d=>d.id===deptFilter)?.name}</Badge>}
              <Badge color="slate">{drillRows.length} รายการ</Badge>
            </div>
          </div>
          <div className="px-4 py-2 border-b border-ink-100 bg-amber-50/60 text-[11px] text-amber-800 flex items-center gap-2">
            <Icon name="info" size={11} className="shrink-0"/>
            <span>Dashboard นับรวมงานของ <strong>ทุกวัน/ทุกงวด</strong> ในเดือนที่เลือก · งาน <strong>Daily</strong> 1 ตัวจะมีหลาย instances (1 ต่อวัน) · คลิกแถวเพื่อ <strong>เปิดดูใน RACI Matrix ที่วันที่นั้น</strong></span>
          </div>
          <div className="max-h-[440px] overflow-y-auto thin-scroll">
            {drillRows.length === 0 ? (
              <EmptyState title="ไม่พบงานในตัวกรองนี้" subtitle="ลองเปลี่ยนตัวกรองหรือล้างเงื่อนไข"/>
            ) : (
              <table className="w-full text-[12px]">
                <thead className="sticky top-0 z-10 bg-ink-50/80 backdrop-blur">
                  <tr className="text-ink-500 text-[10.5px] uppercase tracking-wider">
                    {["Sub-process","R / A","วันที่ของงวด","Status","Last update",""].map(h=><th key={h} className="text-left font-semibold px-3 py-2 border-b border-ink-200">{h}</th>)}
                  </tr>
                </thead>
                <tbody>
                  {drillRows.map((r, i) => (
                    <tr key={`${r.task.sub_process_id}-${r.task.due_date}-${i}`}
                        onClick={() => onGoMatrix(r.task.due_date)}
                        className="border-b border-ink-100 hover:bg-brand-50/40 cursor-pointer transition group">
                      <td className="px-3 py-2.5">
                        <div className="text-ink-900 font-medium truncate max-w-[260px]">{r.sp.name}</div>
                        <div className="text-[10.5px] text-ink-500 truncate max-w-[260px]">{r.mp?.name} · {r.proc?.name}</div>
                      </td>
                      <td className="px-3 py-2.5">
                        <div className="flex items-center gap-1.5">
                          <Avatar name={r.rUser?.full_name} size={20}/>
                          <span className="text-ink-700 truncate max-w-[120px]">{r.rUser?.full_name || "—"}</span>
                        </div>
                        <div className="text-[10.5px] text-ink-500 mt-0.5">A: {r.aUser?.full_name || "—"}</div>
                      </td>
                      <td className="px-3 py-2.5">
                        <div className="font-mono text-ink-700">{r.task.due_date}</div>
                        <Badge color="slate" className="!text-[9.5px] mt-0.5">{r.task.frequency || r.sp.frequency}</Badge>
                      </td>
                      <td className="px-3 py-2.5"><StatusPill status={r.task.status}/></td>
                      <td className="px-3 py-2.5 font-mono text-[10.5px] text-ink-500">{r.task.updated || "—"}</td>
                      <td className="px-2 py-2.5 text-right">
                        <span className="opacity-0 group-hover:opacity-100 text-[10.5px] text-brand-600 font-medium inline-flex items-center gap-1">เปิดใน Matrix<Icon name="arrowRight" size={11}/></span>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

// ---- Donut Chart (SVG) ----
const DonutChart = ({ data, total, center, centerLabel }) => {
  const size = 180, r = 70, stroke = 22, c = 2*Math.PI*r;
  let acc = 0;
  return (
    <div className="relative flex items-center justify-center" style={{height:size}}>
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="#eef0f6" strokeWidth={stroke}/>
        {data.map((d,i) => {
          if (!total || d.v===0) return null;
          const len = (d.v/total)*c;
          const off = (acc/total)*c;
          acc += d.v;
          return (
            <circle key={i} cx={size/2} cy={size/2} r={r} fill="none" stroke={d.color} strokeWidth={stroke}
              strokeDasharray={`${len} ${c-len}`} strokeDashoffset={-off} transform={`rotate(-90 ${size/2} ${size/2})`} strokeLinecap="butt"/>
          );
        })}
      </svg>
      <div className="absolute inset-0 flex flex-col items-center justify-center">
        <div className="text-[26px] font-bold text-ink-900 font-mono">{center}</div>
        <div className="text-[10.5px] text-ink-500 uppercase tracking-wider">{centerLabel}</div>
      </div>
    </div>
  );
};

// ---- Line Chart (SVG) ----
const LineChart = ({ data, width=260, height=120 }) => {
  const pad = { l:24, r:8, t:10, b:18 };
  const W = width - pad.l - pad.r, H = height - pad.t - pad.b;
  const max = 100, min = 0;
  const xs = (i) => pad.l + (i/(data.length-1))*W;
  const ys = (v) => pad.t + (1 - (v-min)/(max-min))*H;
  const path = data.map((d,i) => `${i===0?"M":"L"}${xs(i)},${ys(d.rate)}`).join(" ");
  const areaPath = `${path} L${xs(data.length-1)},${pad.t+H} L${xs(0)},${pad.t+H} Z`;
  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} className="overflow-visible">
      <defs>
        <linearGradient id="trendGrad" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor="#6366f1" stopOpacity="0.3"/>
          <stop offset="100%" stopColor="#6366f1" stopOpacity="0"/>
        </linearGradient>
      </defs>
      {[0,50,100].map(v => (
        <line key={v} x1={pad.l} x2={pad.l+W} y1={ys(v)} y2={ys(v)} stroke="#eef0f6" strokeDasharray="3 3"/>
      ))}
      <path d={areaPath} fill="url(#trendGrad)"/>
      <path d={path} fill="none" stroke="#6366f1" strokeWidth="2"/>
      {data.map((d,i) => (
        <g key={i}>
          <circle cx={xs(i)} cy={ys(d.rate)} r={3} fill="#fff" stroke="#6366f1" strokeWidth="2"/>
          <text x={xs(i)} y={pad.t+H+12} textAnchor="middle" fontSize="10" fill="#8b96ad" fontFamily="JetBrains Mono">{d.m}</text>
        </g>
      ))}
    </svg>
  );
};

const LegendDot = ({ color, label }) => (
  <span className="inline-flex items-center gap-1"><span className={`w-2 h-2 rounded-sm ${color}`}/><span>{label}</span></span>
);

Object.assign(window, { DashboardPage });
