/* AAU CRM — Marketing shared widgets: TimeControl, CompareLineChart,
   Heatmap, AlertBanner, SummaryTable, SourceBadge. Exposes on window. */

// ---- period state hook (per-page; consistent control everywhere) ----
// now backed by the shared resolvePeriod() so the user can step back through history
function useTimeRange(init = '30d') {
  const isoOf = d => { const x = new Date(d); return x.getFullYear() + '-' + ('0' + (x.getMonth() + 1)).slice(-2) + '-' + ('0' + x.getDate()).slice(-2); };
  const [period, setPeriodRaw] = useState(init);
  const [offset, setOffset] = useState(0);
  const [from, setFrom] = useState(isoOf(new Date(NOW.getFullYear(), NOW.getMonth(), NOW.getDate() - 29)));
  const [to, setTo] = useState(isoOf(NOW));
  const [compare, setCompare] = useState(true);
  const [cmpMode, setCmpMode] = useState('prev');
  // mốc so sánh tùy chọn (khi cmpMode === 'custom')
  const [cfrom, setCfrom] = useState(isoOf(new Date(NOW.getFullYear(), NOW.getMonth(), NOW.getDate() - 59)));
  const [cto, setCto] = useState(isoOf(new Date(NOW.getFullYear(), NOW.getMonth(), NOW.getDate() - 30)));
  const cur = resolvePeriod(period, offset, { from, to });
  // kỳ so sánh phụ thuộc cmpMode: kỳ liền trước · cùng kỳ năm trước · mốc tùy chọn
  let prev;
  if (cmpMode === 'custom') {
    prev = resolvePeriod('custom', 0, { from: cfrom, to: cto });
  } else if (cmpMode === 'year') {
    const yf = new Date(cur.from), yt = new Date(cur.to);
    yf.setFullYear(yf.getFullYear() - 1); yt.setFullYear(yt.getFullYear() - 1);
    prev = resolvePeriod('custom', 0, { from: yf, to: yt });
  } else {
    prev = resolvePeriod(period, offset - 1, { from, to });
  }
  const setPeriod = p => { setPeriodRaw(p); setOffset(0); };
  // nhảy tới một ngày bất kỳ ở chế độ 'Hôm nay' (offset = số ngày lệch so với hôm nay, không quá 0)
  const goToDate = ds => { const d = new Date(ds); const days = Math.round((new Date(d.getFullYear(), d.getMonth(), d.getDate()) - NOW) / 86400000); setOffset(Math.min(0, days)); };
  return {
    period, setPeriod, offset, setOffset, from, setFrom, to, setTo,
    compare, setCompare, cmpMode, setCmpMode, cfrom, setCfrom, cto, setCto,
    cur, prev, goToDate,
    curLabel: cur.label, scale: periodScale(period, offset),
    step: d => setOffset(o => Math.min(0, o + d)), reset: () => setOffset(0),
  };
}
const PERIOD_LABEL = { today: 'Hôm nay', '7d': '7 ngày qua', '30d': '30 ngày qua', month: 'Tháng này', custom: 'Tùy chọn' };
const CMP_LABEL = { prev: 'Kỳ liền trước', year: 'Cùng kỳ năm trước', custom: 'Mốc tùy chọn' };

function TimeControl({ t }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    const h = e => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', h);
    return () => document.removeEventListener('mousedown', h);
  }, [open]);
  const cmpVal = t.compare ? t.cmpMode : 'off';
  const onCmp = (v) => { if (v === 'off') { t.setCompare(false); } else { t.setCompare(true); t.setCmpMode(v); } };
  const isCustom = t.period === 'custom';
  const isToday = t.period === 'today';
  const atNow = t.offset === 0;
  const curISO = (() => { const d = t.cur.from; return d.getFullYear() + '-' + ('0' + (d.getMonth() + 1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2); })();
  const todayISO = NOW.getFullYear() + '-' + ('0' + (NOW.getMonth() + 1)).slice(-2) + '-' + ('0' + NOW.getDate()).slice(-2);
  const jumpList = Array.from({ length: 6 }).map((_, i) => resolvePeriod(t.period, -i, { from: t.from, to: t.to }));
  return (
    <div className="row aic g8 mktbar pnav">
      <Seg value={t.period} onChange={t.setPeriod} options={[
        { value: 'today', label: 'Hôm nay' }, { value: '7d', label: '7N' },
        { value: '30d', label: '30N' }, { value: 'month', label: 'Tháng' }, { value: 'custom', label: 'Tùy chọn' },
      ]} />
      {isCustom ? (
        <div className="row aic g6">
          <input type="date" className="input pnav-date" value={t.from} onChange={e => t.setFrom(e.target.value)} />
          <span className="subtle t12">→</span>
          <input type="date" className="input pnav-date" value={t.to} onChange={e => t.setTo(e.target.value)} />
        </div>
      ) : isToday ? (
        // chế độ Ngày: lịch chọn bất kỳ ngày nào để xem ads của đúng ngày đó
        <div className="pnav-step">
          <button className="pnav-arrow" title="Ngày trước" onClick={() => t.step(-1)}><Icon name="chevronLeft" size={15} /></button>
          <label className="pnav-cur" title="Chọn ngày xem ads" style={{ position: 'relative', cursor: 'pointer' }}>
            <Icon name="calendar" size={13} /><span className="pnav-lbl">{t.cur.label}</span>
            <input type="date" max={todayISO} value={curISO} onChange={e => e.target.value && t.goToDate(e.target.value)}
              style={{ position: 'absolute', inset: 0, opacity: 0, cursor: 'pointer', width: '100%', height: '100%' }} />
          </label>
          <button className="pnav-arrow" title="Ngày sau" disabled={atNow} onClick={() => t.step(1)}><Icon name="chevronRight" size={15} /></button>
        </div>
      ) : (
        <div className="pnav-step" ref={ref}>
          <button className="pnav-arrow" title="Kỳ trước" onClick={() => t.step(-1)}><Icon name="chevronLeft" size={15} /></button>
          <button className="pnav-cur" onClick={() => setOpen(o => !o)} title="Chọn nhanh kỳ">
            <Icon name="calendar" size={13} /><span className="pnav-lbl">{t.cur.label}</span><Icon name="chevronDown" size={13} />
          </button>
          <button className="pnav-arrow" title="Kỳ sau" disabled={atNow} onClick={() => t.step(1)}><Icon name="chevronRight" size={15} /></button>
          {open && (
            <div className="pnav-pop">
              <div className="pnav-pop-h">Tra cứu lịch sử · {t.cur.kind}</div>
              {jumpList.map(j => (
                <button key={j.offset} className={'pnav-pop-i' + (j.offset === t.offset ? ' on' : '')} onClick={() => { t.setOffset(j.offset); setOpen(false); }}>
                  <span>{j.label}</span>
                  {j.offset === 0 && <span className="pnav-tag">hiện tại</span>}
                  {j.offset === t.offset && j.offset !== 0 && <Icon name="check" size={13} />}
                </button>
              ))}
            </div>
          )}
        </div>
      )}
      {!isCustom && !atNow && <button className="pnav-reset" onClick={t.reset}><Icon name="refresh" size={12} />Về hiện tại</button>}
      <Select value={cmpVal} onChange={onCmp} style={{ width: 168 }} options={[
        { value: 'off', label: 'Không so sánh' },
        { value: 'prev', label: 'vs Kỳ trước' },
        { value: 'year', label: 'vs Cùng kỳ' },
        { value: 'custom', label: 'vs Tùy chọn' },
      ]} />
      {t.compare && t.cmpMode === 'custom' && (
        // mốc so sánh tùy chọn
        <div className="row aic g6" title="Mốc thời gian so sánh">
          <span className="subtle t12">so với</span>
          <input type="date" className="input pnav-date" value={t.cfrom} onChange={e => t.setCfrom(e.target.value)} />
          <span className="subtle t12">→</span>
          <input type="date" className="input pnav-date" value={t.cto} onChange={e => t.setCto(e.target.value)} />
        </div>
      )}
    </div>
  );
}

// overlaid 2-line chart: A solid colour, B dashed grey
function CompareLineChart({ data, height = 230, color = '#0084ff', fmt, labels, showB = true, labelA = 'Kỳ này', labelB = 'Kỳ trước' }) {
  const w = 660, h = height, pad = { l: 46, r: 16, t: 16, b: 30 };
  const all = showB ? [...data.cur, ...data.prev] : data.cur;
  const max = Math.max(...all) * 1.12 || 1;
  const iw = w - pad.l - pad.r, ih = h - pad.t - pad.b;
  const n = data.cur.length;
  const x = i => pad.l + (i / (n - 1)) * iw;
  const y = v => pad.t + ih - (v / max) * ih;
  const line = arr => arr.map((v, i) => (i ? 'L' : 'M') + x(i) + ',' + y(v)).join(' ');
  const area = line(data.cur) + ` L${x(n - 1)},${pad.t + ih} L${x(0)},${pad.t + ih} Z`;
  const ticks = 4;
  return (
    <div>
      <svg viewBox={`0 0 ${w} ${h}`} style={{ width: '100%', height }}>
        <defs><linearGradient id="cmpg" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor={color} stopOpacity="0.16" /><stop offset="1" stopColor={color} stopOpacity="0" /></linearGradient></defs>
        {Array.from({ length: ticks + 1 }).map((_, i) => { const v = max * (i / ticks); const yy = y(v); return <g key={i}><line x1={pad.l} y1={yy} x2={w - pad.r} y2={yy} stroke="#ebebeb" /><text x={pad.l - 8} y={yy + 3} textAnchor="end" fontSize="10" fill="#8a8a8a">{fmt ? fmt(v) : Math.round(v)}</text></g>; })}
        <path d={area} fill="url(#cmpg)" />
        {showB && <path d={line(data.prev)} fill="none" stroke="#b9b9b9" strokeWidth="2" strokeDasharray="5 4" strokeLinejoin="round" />}
        <path d={line(data.cur)} fill="none" stroke={color} strokeWidth="2.6" strokeLinejoin="round" strokeLinecap="round" />
        {(labels || []).map((l, i) => i % Math.ceil(n / 8) === 0 && <text key={i} x={x(i)} y={h - 9} textAnchor="middle" fontSize="10" fill="#8a8a8a">{l}</text>)}
      </svg>
      <div className="row aic g16 t12 muted" style={{ paddingLeft: 46 }}>
        <span className="row aic g6"><span style={{ width: 16, height: 3, borderRadius: 2, background: color }} />{labelA}</span>
        {showB && <span className="row aic g6"><span style={{ width: 16, height: 0, borderTop: '2px dashed #b9b9b9' }} />{labelB}</span>}
      </div>
    </div>
  );
}

// posting-time heatmap
function Heatmap({ days, slots, grid, color = '#0084ff' }) {
  const max = Math.max(...grid.flat());
  return (
    <div className="heatwrap">
      <div className="heatgrid" style={{ gridTemplateColumns: `42px repeat(${slots.length}, 1fr)` }}>
        <div className="heat-cell heat-corner" />
        {slots.map(s => <div key={s} className="heat-cell heat-h">{s}</div>)}
        {days.map((d, r) => (
          <React.Fragment key={d}>
            <div className="heat-cell heat-d">{d}</div>
            {grid[r].map((v, c) => {
              const a = 0.08 + 0.92 * (v / max);
              return <div key={c} className="heat-cell heat-v" style={{ background: color, opacity: a, color: a > 0.55 ? '#fff' : 'var(--p-text-secondary)' }} title={d + ' ' + slots[c] + 'h · chỉ số ' + v}>{v}</div>;
            })}
          </React.Fragment>
        ))}
      </div>
    </div>
  );
}

function AlertBanner({ alerts }) {
  if (!alerts || !alerts.length) return null;
  return (
    <div className="col g8 mb16">
      {alerts.map((a, i) => (
        <div key={i} className="mkt-alert" style={{ background: 'var(--p-' + a.tone + '-bg)' }}>
          <Icon name={a.icon} size={17} color={'var(--p-' + a.tone + '-text)'} />
          <div className="f1"><span className="fw6 t13">{a.title}</span><span className="t12 muted" style={{ marginLeft: 8 }}>{a.desc}</span></div>
          {a.cta && <Button size="sm" variant="secondary" iconRight="chevronRight" onClick={() => a.to && navigate(a.to)}>{a.cta}</Button>}
        </div>
      ))}
    </div>
  );
}

function SourceBadge({ src, size = 22, showLabel }) {
  const c = AAU.mktChannelById(src); if (!c) return null;
  return <span className="row aic g8"><span className="center" style={{ width: size, height: size, borderRadius: 6, background: c.color, color: '#fff', fontSize: size * 0.4, fontWeight: 700, flexShrink: 0 }}>{c.short[0]}</span>{showLabel && <span className="t13 fw5">{c.label}</span>}</span>;
}

// the cross-dimension Summary table (Course / Channel / Campaign / Class)
function SummaryTable({ dim }) {
  const { rows, total } = AAU.mktSummary(dim);
  const cplAlert = AAU.mktBudget.cplAlert;
  const cell = (r) => (
    <tr key={r.key} className={r.isTotal ? 'sum-total' : ''}>
      <td className="fw6">{r.label}</td>
      <td className="num">{r.spend ? AAU.fmtVNDm(r.spend) : '—'}</td>
      <td className="num">{AAU.fmtNum(r.messages)}</td>
      <td className="num"><span className="sla-ok">{r.leadsOrg}</span> <span className="subtle">/</span> <span style={{ color: '#0084ff' }}>{r.leadsAds}</span></td>
      <td className="num fw6">{r.leads}</td>
      <td className="num" style={{ color: r.cpl && r.cpl > cplAlert ? '#c4320a' : undefined }}>{r.cpl ? AAU.fmtVND(r.cpl) : '—'}</td>
      <td className="num">{r.costMsg ? AAU.fmtVND(r.costMsg) : '—'}</td>
      <td className="num">{r.won}</td>
      <td className="num">{r.cac ? AAU.fmtVNDm(r.cac) : '—'}</td>
    </tr>
  );
  return (
    <div className="tbl-wrap">
      <table className="tbl sum-tbl"><thead><tr>
        <th>{dim === 'course' ? 'Khóa học' : dim === 'channel' ? 'Kênh' : dim === 'campaign' ? 'Campaign' : 'Lớp khai giảng'}</th>
        <th className="num">Ngân sách</th><th className="num">Msg</th>
        <th className="num">Lead (org/ads)</th><th className="num">Σ Lead</th>
        <th className="num">CPL</th><th className="num">Cost/Msg</th><th className="num">Won</th><th className="num">CAC</th>
      </tr></thead>
      <tbody>{rows.map(cell)}{cell(total)}</tbody></table>
    </div>
  );
}

// reusable Sync control — shows last-sync time, spins on click, supports realtime badge
function SyncButton({ label = 'Đồng bộ', since = '12 phút trước', realtime = false, onSync = null }) {
  const [syncing, setSyncing] = useState(false);
  const [last, setLast] = useState(since);
  const go = async () => {
    if (syncing) return;
    setSyncing(true);
    try {
      if (onSync) await onSync();                                   // gọi API thật
      else await new Promise(r => setTimeout(r, 1100));             // nút demo
      setLast('vừa xong');
    } catch (e) { setLast('lỗi: ' + (e && e.message || e)); }
    finally { setSyncing(false); }
  };
  return (
    <button className={'sync-btn' + (realtime ? ' realtime' : '')} onClick={go} disabled={syncing} title="Kéo dữ liệu mới nhất qua API">
      <Icon name="refresh" size={14} className={syncing ? 'spin' : ''} />
      <span className="sync-lbl">{syncing ? 'Đang đồng bộ…' : label}</span>
      {realtime ? <span className="sync-dot" /> : null}
      <span className="sync-time">{realtime ? 'realtime' : last}</span>
    </button>
  );
}

Object.assign(window, { useTimeRange, TimeControl, CompareLineChart, Heatmap, AlertBanner, SourceBadge, SummaryTable, SyncButton, PERIOD_LABEL, CMP_LABEL });
