// Overview.jsx — 二维俯瞰网格（纵轴：时间尺 / 地点序 · 横轴：本子）
// 由 Claude Design「坐标模型共识」原型重建到生产数据模型。覆层叠加，不改现有流程。
// 列归属用现有 noteInNotebook（含子本子下钻）；纵轴时间用 import_ts/date 真实刻度。
const { useState: useStateOv } = React;

// 时间值（毫秒）：date "2021.10.14" / "2026.6.9"（容许不补零）+ time "16:00"
function ovTval(n) {
  const p = String(n.date || '').split('.').map(x => parseInt(x, 10));
  if (!p[0]) return 0;
  const tm = /^(\d{1,2}):(\d{2})/.exec(n.time || '');
  return new Date(p[0], (p[1] || 1) - 1, p[2] || 1, tm ? +tm[1] : 12, tm ? +tm[2] : 0).getTime();
}

const OV_GUTTER = 60;   // 左侧时间/地点标尺宽
const OV_COLW = 152;    // 每个本子列宽

// 一张笔记卡（列内）
function OvChip({ note, dim, onOpen, style }) {
  const color = note._capLanding ? 'var(--flame)' : ((window.CITY_LINE && window.CITY_LINE[note.city]) || 'var(--ink-3)');
  return (
    <button className={'ov-chip' + (dim ? ' dim' : '') + (note._capLanding ? ' cap' : '')} style={style} onClick={() => onOpen(note._ref || note.id)}
      title={(note._capLanding ? '录入落点 · ' : '') + note.title + ' · ' + note.date + (note.city ? ' · ' + note.city : '')}>
      <span className="ov-chip-dot" style={{ background: color }}></span>
      <span className="ov-chip-body">
        <span className="ov-chip-title">{note.title}</span>
        <span className="ov-chip-meta"><i>{String(note.date || '').slice(2)}</i>{note.city && note.city !== '未标注' ? ' · ' + note.city : ''}</span>
      </span>
    </button>
  );
}

function OverviewGrid({ axis, notes, notebooks, timeFilter, placeFilter, notebookFilter, setNotebookFilter, onOpenNote, onClose }) {
  const [scale, setScale] = useStateOv(1);
  const rowMode = axis === 'place' ? 'place' : 'time';   // 时间/时空 → 时间尺；地点 → 地点序
  const NOW = window.NOW || { date: '2026.06.01', time: '11:15', city: '上海', scene: '家' };

  const cols = (notebooks || []).filter(nb => !nb.parent);   // 横轴 = 顶级本子
  const colIndex = {}; cols.forEach((c, i) => colIndex[c.id] = i);
  // 每条笔记归到哪个顶级本子列（用现有 noteInNotebook，含子本子下钻）
  const colCache = new Map();
  const colOf = n => {
    if (colCache.has(n.id)) return colCache.get(n.id);
    let id = null;
    for (const c of cols) { if (window.noteInNotebook(n, notebooks, c.id)) { id = c.id; break; } }
    colCache.set(n.id, id);
    return id;
  };

  // 行方向收窄（共享过滤器：时间 年/月 / 地点 城/年）。本子方向是横轴，不在此过滤。
  const rows = (notes || []).filter(n => {
    if (rowMode === 'time' && timeFilter.year && n.year !== timeFilter.year) return false;
    if (rowMode === 'time' && timeFilter.month && n.month !== timeFilter.month) return false;
    if (rowMode === 'place' && placeFilter.city && n.city !== placeFilter.city) return false;
    if (rowMode === 'place' && placeFilter.year && n.year !== placeFilter.year) return false;
    return colOf(n);   // 没有本子归属的（极少）不进网格
  });

  const colHas = {}; rows.forEach(n => { const c = colOf(n); if (c) colHas[c] = (colHas[c] || 0) + 1; });
  const totalW = OV_GUTTER + cols.length * OV_COLW;

  const ctx = rowMode === 'place'
    ? (placeFilter.city ? '地点 · ' + placeFilter.city + (placeFilter.year ? ' · ' + placeFilter.year : '') : '地点 · 全部')
    : (timeFilter.year ? '时间 · ' + timeFilter.year + (timeFilter.month ? ' · ' + timeFilter.month : '') : (axis === 'spacetime' ? '时空 · 全部' : '时间 · 全部'));

  // ---------- 列头（横轴本子，点击=锁定/解锁该列） ----------
  const colHeader = (
    <div className="ov-colhead" style={{ width: totalW }}>
      <div className="ov-corner" style={{ width: OV_GUTTER }}>
        {rowMode === 'place' ? '地点' : '时间'}
      </div>
      {cols.map(c => {
        const empty = !colHas[c.id];
        const locked = notebookFilter === c.id;
        return (
          <button key={c.id}
            className={'ov-col' + (empty ? ' empty' : '') + (locked ? ' locked' : '') + (notebookFilter && !locked ? ' faded' : '')}
            style={{ width: OV_COLW }}
            onClick={() => setNotebookFilter(locked ? null : c.id)}
            title={empty ? c.name + ' · 这段没有内容' : '只看「' + c.name + '」'}>
            <Icon name={c.lineIcon || 'book'} size={14} />
            <span className="ov-col-name">{c.name}</span>
            {!empty && <span className="ov-col-cnt">{colHas[c.id]}</span>}
          </button>
        );
      })}
    </div>
  );

  // ============ 时间尺：按真实刻度铺（近→远，往下） ============
  function renderTime() {
    const times = rows.map(ovTval).filter(Boolean);
    const nowMs = ovTval(NOW);
    const tMax = Math.max(nowMs, ...(times.length ? times : [nowMs]));
    const tMin = Math.min(nowMs, ...(times.length ? times : [nowMs]));
    const span = Math.max(864e5, tMax - tMin);
    const yrs = span / (365.25 * 864e5);
    const H = Math.max(560, Math.round(yrs * 200 * scale)) + 80;
    const yOf = ms => 36 + (tMax - ms) / span * (H - 96);

    const y0 = new Date(tMax).getFullYear(), y1 = new Date(tMin).getFullYear();
    const years = [];
    for (let y = y0; y >= y1; y--) years.push(y);

    // 每列内防重叠：同列按 y 排序，过近则下推
    const placed = {};
    cols.forEach(c => placed[c.id] = []);
    [...rows].sort((a, b) => ovTval(b) - ovTval(a)).forEach(n => {
      const cid = colOf(n); const arr = placed[cid]; if (!arr) return;
      let y = yOf(ovTval(n));
      if (arr.length && y - arr[arr.length - 1].y < 40) y = arr[arr.length - 1].y + 40;
      arr.push({ note: n, y });
    });

    const nowY = yOf(nowMs);

    return (
      <div className="ov-canvas" style={{ width: totalW, height: H }}>
        {years.map(y => {
          const yy = yOf(Date.parse(y + '-01-01T00:00'));
          if (yy < 20 || yy > H - 10) return null;
          return (
            <React.Fragment key={y}>
              <div className="ov-yline" style={{ top: yy, width: totalW }}></div>
              <div className="ov-ylabel" style={{ top: yy - 7 }}>{y}</div>
            </React.Fragment>
          );
        })}
        {cols.map(c => (
          <div key={c.id} className={'ov-colguide' + (!colHas[c.id] ? ' empty' : '')}
            style={{ left: OV_GUTTER + colIndex[c.id] * OV_COLW, height: H }}></div>
        ))}
        <div className="ov-nowline" style={{ top: nowY, width: totalW }}>
          <span className="ov-now-tag">现在 · {NOW.city}</span>
        </div>
        {cols.map(c => placed[c.id].map(p => (
          <OvChip key={p.note.id} note={p.note}
            dim={notebookFilter && notebookFilter !== c.id}
            onOpen={onOpenNote}
            style={{ position: 'absolute', top: p.y, left: OV_GUTTER + colIndex[c.id] * OV_COLW + 8, width: OV_COLW - 16 }} />
        )))}
      </div>
    );
  }

  // ============ 地点序：城市分组(行)，组内按时间等间距排 ============
  function renderPlace() {
    const cityList = [...new Set(rows.map(n => n.city).filter(c => c && c !== '未标注'))]
      .sort((a, b) => Math.max(...rows.filter(n => n.city === b).map(ovTval)) - Math.max(...rows.filter(n => n.city === a).map(ovTval)));
    return (
      <div className="ov-place" style={{ width: totalW }}>
        {cityList.map(city => {
          const cityNotes = rows.filter(n => n.city === city);
          const color = (window.CITY_LINE && window.CITY_LINE[city]) || 'var(--ink-3)';
          return (
            <div className="ov-prow" key={city}>
              <div className="ov-pcity" style={{ width: OV_GUTTER }}>
                <span className="ov-pcity-dot" style={{ background: color }}></span>
                <span className="ov-pcity-name" style={{ color }}>{city}</span>
                <span className="ov-pcity-cnt">{cityNotes.length}</span>
              </div>
              {cols.map(c => {
                const cell = cityNotes.filter(n => colOf(n) === c.id).sort((a, b) => ovTval(a) - ovTval(b));
                return (
                  <div key={c.id} className={'ov-pcell' + (notebookFilter && notebookFilter !== c.id ? ' dim' : '')}
                    style={{ width: OV_COLW }}>
                    {cell.map(n => (
                      <OvChip key={n.id} note={n} onOpen={onOpenNote} />
                    ))}
                  </div>
                );
              })}
            </div>
          );
        })}
        {cityList.length === 0 && <div className="ov-empty">这段还没有地点信息</div>}
      </div>
    );
  }

  return (
    <div className="ov" onClick={e => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="ov-panel">
        <div className="ov-head">
          <div>
            <div className="ov-title">俯瞰 · 时空 × 本子</div>
            <div className="ov-sub">{ctx} · 纵轴{rowMode === 'place' ? '地点（按先后）' : '时间（按刻度）'} · 横轴本子 · {rows.length} 则</div>
          </div>
          {rowMode === 'time' && (
            <div className="ov-zoom">
              <span>时间疏密</span>
              <button onClick={() => setScale(s => Math.max(0.6, +(s - 0.3).toFixed(2)))}><Icon name="minus" size={13} /></button>
              <button onClick={() => setScale(s => Math.min(2.4, +(s + 0.3).toFixed(2)))}><Icon name="plus" size={13} /></button>
            </div>
          )}
          <button className="ovg-close" onClick={onClose}><Icon name="x" size={18} /></button>
        </div>
        <div className="ov-scroll">
          {colHeader}
          {rowMode === 'place' ? renderPlace() : renderTime()}
        </div>
        <div className="ov-foot">
          <Icon name="route" size={13} />
          {rowMode === 'place'
            ? '城市为行、本子为列；同城内按先后等距排 — 点本子列只看那一本，点卡片回到那一刻'
            : '时间自上而下按真实刻度，本子分列；「现在」线之上是尚未到来的计划 — 点卡片回到那一刻'}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { OverviewGrid });
