// page-errorlog.jsx — 錯誤日誌（NEW，1:1 對齊設計檔，2026-05-10）
// 設計檔結構：4 KPI / filter tabs / Error table / ErrorDetail panel / ComposeModal
// 儲存：localStorage 'errorlog_entries_v1'（純前端，未來可同步 D1）
// 重要 export：window.ErrorLogPage
(function(){
  const T = window.STOCK_TOKENS;

  const SEVERITY = {
    error: { label: 'ERROR', c: 'var(--down)', b: 'var(--down-bg)' },
    warn: { label: 'WARN', c: 'var(--accent)', b: 'rgba(217,148,22,.12)' },
    info: { label: 'INFO', c: 'var(--accent-2)', b: 'rgba(37,99,235,.12)' },
  };
  const STATUS_MAP = {
    open: { l: '未處理', c: 'var(--down)' },
    investigating: { l: '處理中', c: 'var(--accent)' },
    resolved: { l: '已解決', c: 'var(--up)' },
  };
  const LS_KEY = 'errorlog_entries_v1';

  function loadEntries() {
    try { return JSON.parse(localStorage.getItem(LS_KEY) || '[]'); }
    catch { return []; }
  }
  function saveEntries(entries) {
    localStorage.setItem(LS_KEY, JSON.stringify(entries));
  }

  function ErrorLogPage() {
    const [entries, setEntries] = React.useState(loadEntries);
    const [selected, setSelected] = React.useState(null);
    const [composing, setComposing] = React.useState(false);
    const [filter, setFilter] = React.useState('all');

    React.useEffect(() => { saveEntries(entries); }, [entries]);

    const sel = selected ? entries.find(e => e.id === selected) : null;
    const filtered = filter === 'all' ? entries : entries.filter(e => e.status === filter);
    const counts = {
      all: entries.length,
      open: entries.filter(e => e.status === 'open').length,
      investigating: entries.filter(e => e.status === 'investigating').length,
      resolved: entries.filter(e => e.status === 'resolved').length,
    };

    function addEntry(entry) {
      const id = `ERR-${new Date().toISOString().slice(0, 10).replace(/-/g, '')}-${String(entries.length + 1).padStart(3, '0')}`;
      const userEmail = localStorage.getItem('stocksense_user_email_v1') || '王小明';
      const newEntry = {
        id,
        ts: new Date().toISOString().replace('T', ' ').slice(0, 19),
        who: userEmail,
        severity: 'error',
        status: 'open',
        ...entry,
      };
      setEntries([newEntry, ...entries]);
      setComposing(false);
      setSelected(newEntry.id);
    }
    function updateStatus(id, status) {
      setEntries(entries.map(e => e.id === id ? { ...e, status } : e));
    }
    function deleteEntry(id) {
      setEntries(entries.filter(e => e.id !== id));
      if (selected === id) setSelected(null);
    }

    return (
      <div style={{ padding: 16, maxWidth: 1400, margin: '0 auto' }}>
        <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', paddingBottom: 16, borderBottom: '1px solid var(--line)' }}>
          <div>
            <div className="mono" style={{ fontSize: 11, color: 'var(--fg-3)', letterSpacing: '.1em' }}>
              SYSTEM · ERROR REPORT · ADMIN ONLY
            </div>
            <div style={{ fontSize: 22, fontWeight: 600, color: 'var(--fg-0)', marginTop: 4 }}>錯誤日誌</div>
            <div style={{ fontSize: 12.5, color: 'var(--fg-2)', marginTop: 2 }}>
              貼上遇到的錯誤、Console 訊息、操作步驟。可一鍵複製整份回報交給 Claude 修復。
            </div>
          </div>
          <button className="btn-primary btn" onClick={() => setComposing(true)}>＋ 新增錯誤回報</button>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12, marginTop: 16 }}>
          <Kpi label="全部" value={counts.all} sub="所有錯誤回報" />
          <Kpi label="未處理" value={counts.open} sub="待修復" cls="down" />
          <Kpi label="處理中" value={counts.investigating} sub="調查中" cls="flat" />
          <Kpi label="已解決" value={counts.resolved} sub="本月累計" cls="up" />
        </div>

        <div style={{ display: 'flex', gap: 16, borderBottom: '1px solid var(--line)', marginTop: 16 }}>
          {[
            { id: 'all', l: '全部' },
            { id: 'open', l: '未處理' },
            { id: 'investigating', l: '處理中' },
            { id: 'resolved', l: '已解決' },
          ].map(t => (
            <button key={t.id} onClick={() => setFilter(t.id)} style={{
              background: 'transparent', border: 'none', cursor: 'pointer', padding: '10px 0',
              color: filter === t.id ? 'var(--fg-0)' : 'var(--fg-3)',
              borderBottom: `2px solid ${filter === t.id ? 'var(--accent)' : 'transparent'}`,
              fontSize: 13,
            }}>
              {t.l} <span className="mono" style={{ color: 'var(--fg-4)', marginLeft: 4, fontSize: 11 }}>{counts[t.id]}</span>
            </button>
          ))}
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: sel ? '1fr 480px' : '1fr', gap: 12, marginTop: 16 }}>
          <div className="panel" style={{ overflow: 'hidden' }}>
            <table>
              <thead>
                <tr>
                  <th style={{ width: 90 }}>狀態</th>
                  <th style={{ width: 170 }}>ID / 時間</th>
                  <th>標題</th>
                  <th style={{ width: 130 }}>頁面</th>
                  <th style={{ width: 120 }}>回報者</th>
                  <th style={{ width: 70 }}>等級</th>
                </tr>
              </thead>
              <tbody>
                {filtered.length === 0 && (
                  <tr><td colSpan={6} style={{ padding: 32, textAlign: 'center', color: 'var(--fg-3)' }}>沒有符合的錯誤回報</td></tr>
                )}
                {filtered.map(e => {
                  const s = SEVERITY[e.severity];
                  const st = STATUS_MAP[e.status];
                  return (
                    <tr key={e.id} onClick={() => setSelected(e.id)} style={{ cursor: 'pointer', background: selected === e.id ? 'var(--bg-3)' : null }}>
                      <td>
                        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 11.5 }}>
                          <span style={{ width: 6, height: 6, borderRadius: '50%', background: st.c }}></span>
                          {st.l}
                        </span>
                      </td>
                      <td>
                        <div className="mono" style={{ fontSize: 11, color: 'var(--fg-1)' }}>{e.id}</div>
                        <div className="mono" style={{ fontSize: 10, color: 'var(--fg-3)' }}>{e.ts}</div>
                      </td>
                      <td style={{ color: 'var(--fg-0)' }}>{e.title}</td>
                      <td style={{ fontSize: 12, color: 'var(--fg-2)' }}>{e.page}</td>
                      <td style={{ fontSize: 12, color: 'var(--fg-2)' }}>{e.who}</td>
                      <td>
                        <span className="mono" style={{
                          padding: '2px 8px', borderRadius: 2, fontSize: 10, fontWeight: 600,
                          background: s.b, color: s.c, letterSpacing: '.06em',
                        }}>{s.label}</span>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
          {sel && <ErrorDetail entry={sel} onClose={() => setSelected(null)} onStatus={s => updateStatus(sel.id, s)} onDelete={() => deleteEntry(sel.id)} />}
        </div>

        {composing && <ComposeModal onClose={() => setComposing(false)} onSubmit={addEntry} />}
      </div>
    );
  }
  window.ErrorLogPage = ErrorLogPage;

  function Kpi({ label, value, sub, cls }) {
    return (
      <div className="panel" style={{ padding: 14 }}>
        <div className="mono" style={{ fontSize: 9.5, color: 'var(--fg-3)', letterSpacing: '.08em' }}>{label}</div>
        <div className={`num ${cls || ''}`} style={{ fontSize: 26, fontWeight: 600, marginTop: 4, color: cls ? null : 'var(--fg-0)' }}>{value}</div>
        <div style={{ fontSize: 11, color: 'var(--fg-2)', marginTop: 2 }}>{sub}</div>
      </div>
    );
  }

  function ErrorDetail({ entry, onClose, onStatus, onDelete }) {
    const [copied, setCopied] = React.useState(false);
    const s = SEVERITY[entry.severity];
    const st = STATUS_MAP[entry.status];

    function buildClaudePrompt() {
      return `請協助修復以下錯誤：

【錯誤 ID】${entry.id}
【回報時間】${entry.ts}
【頁面】${entry.page}
【嚴重度】${s.label}
【標題】${entry.title}

【詳細內容】
${entry.body}

請定位到對應的檔案與程式碼，分析原因並提供修復方案。`;
    }
    function copyPrompt() {
      navigator.clipboard.writeText(buildClaudePrompt()).then(() => {
        setCopied(true);
        setTimeout(() => setCopied(false), 1800);
      });
    }

    return (
      <div className="panel" style={{ position: 'sticky', top: 16, height: 'fit-content', maxHeight: 'calc(100vh - 32px)', overflow: 'auto' }}>
        <div className="panel-h">
          <span className="label">錯誤詳情</span>
          <button onClick={onClose} className="btn-ghost btn" style={{ padding: 0, fontSize: 14 }}>✕</button>
        </div>
        <div style={{ padding: 18 }}>
          <div className="mono" style={{ fontSize: 11, color: 'var(--fg-3)', marginBottom: 6 }}>{entry.id}</div>
          <div style={{ fontSize: 16, fontWeight: 600, color: 'var(--fg-0)', marginBottom: 4, lineHeight: 1.4 }}>{entry.title}</div>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginBottom: 14, flexWrap: 'wrap' }}>
            <span className="mono" style={{ padding: '2px 8px', borderRadius: 2, fontSize: 10, fontWeight: 600, background: s.b, color: s.c }}>{s.label}</span>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 11.5 }}>
              <span style={{ width: 6, height: 6, borderRadius: '50%', background: st.c }}></span>
              {st.l}
            </span>
            <span className="mono" style={{ fontSize: 10.5, color: 'var(--fg-3)' }}>{entry.ts}</span>
          </div>

          <DetailRow label="頁面" value={entry.page} />
          <DetailRow label="回報者" value={entry.who} mono />

          <div className="mono" style={{ fontSize: 10, color: 'var(--fg-3)', letterSpacing: '.08em', marginTop: 16, marginBottom: 6 }}>內容 / Console 訊息</div>
          <pre className="mono" style={{
            background: 'var(--bg-2)', border: '1px solid var(--line)', borderRadius: 3, padding: 12,
            fontSize: 11.5, color: 'var(--fg-1)', lineHeight: 1.55, whiteSpace: 'pre-wrap', wordBreak: 'break-word',
            maxHeight: 280, overflow: 'auto', margin: 0,
          }}>{entry.body}</pre>

          <div style={{ marginTop: 16, padding: 12, background: 'var(--bg-2)', borderRadius: 3, borderLeft: '2px solid var(--accent)' }}>
            <div className="mono" style={{ fontSize: 10, color: 'var(--accent)', letterSpacing: '.08em', marginBottom: 6 }}>↗ 交給 CLAUDE 修復</div>
            <div style={{ fontSize: 11.5, color: 'var(--fg-2)', lineHeight: 1.5, marginBottom: 8 }}>
              一鍵複製整份回報（含格式化的 prompt），貼到 Claude 對話即可開始修復。
            </div>
            <button className="btn-primary btn" style={{ width: '100%', justifyContent: 'center' }} onClick={copyPrompt}>
              {copied ? '✓ 已複製到剪貼簿' : '📋 複製 Claude 修復 Prompt'}
            </button>
          </div>

          <div className="mono" style={{ fontSize: 10, color: 'var(--fg-3)', letterSpacing: '.08em', marginTop: 16, marginBottom: 6 }}>狀態</div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6 }}>
            {Object.entries(STATUS_MAP).map(([k, v]) => (
              <button key={k} onClick={() => onStatus(k)} className="btn" style={{
                borderColor: entry.status === k ? v.c : null,
                color: entry.status === k ? v.c : null,
                background: entry.status === k ? 'var(--bg-2)' : null,
              }}>{v.l}</button>
            ))}
          </div>

          <button className="btn" style={{ marginTop: 12, width: '100%', justifyContent: 'center', color: 'var(--down)', borderColor: 'var(--down)' }} onClick={onDelete}>
            🗑 刪除回報
          </button>
        </div>
      </div>
    );
  }

  function DetailRow({ label, value, mono }) {
    return (
      <div style={{ display: 'grid', gridTemplateColumns: '70px 1fr', gap: 10, padding: '6px 0', borderBottom: '1px dashed var(--line)' }}>
        <span className="mono" style={{ fontSize: 10, color: 'var(--fg-3)', letterSpacing: '.06em', paddingTop: 2 }}>{(label || '').toUpperCase()}</span>
        <span className={mono ? 'mono' : ''} style={{ fontSize: 12, color: 'var(--fg-1)' }}>{value}</span>
      </div>
    );
  }

  function ComposeModal({ onClose, onSubmit }) {
    const [title, setTitle] = React.useState('');
    const [page, setPage] = React.useState('');
    const [severity, setSeverity] = React.useState('error');
    const [body, setBody] = React.useState('');

    const PAGES = ['盤前簡報', 'AI 推薦', '自選股', '法說會日曆', '法人籌碼', '題材熱度', '熱門新聞', '半月檢討', '權限管理', '錯誤日誌', '其他'];

    function submit() {
      if (!title.trim() || !body.trim()) return;
      onSubmit({ title: title.trim(), page: page || '其他', severity, body: body.trim() });
    }

    return (
      <div style={{
        position: 'fixed', inset: 0, background: 'rgba(0,0,0,.55)', backdropFilter: 'blur(4px)', zIndex: 200,
        display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24,
      }} onClick={onClose}>
        <div className="panel" onClick={e => e.stopPropagation()} style={{ width: '100%', maxWidth: 720, maxHeight: '90vh', overflow: 'auto' }}>
          <div className="panel-h">
            <span className="label">＋ 新增錯誤回報</span>
            <button onClick={onClose} className="btn-ghost btn" style={{ padding: 0, fontSize: 14 }}>✕</button>
          </div>
          <div style={{ padding: 20, display: 'grid', gap: 14 }}>
            <Field label="標題">
              <input placeholder="一句話描述問題（例：拖拉排序未儲存）" value={title} onChange={e => setTitle(e.target.value)} autoFocus style={{ width: '100%' }} />
            </Field>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
              <Field label="發生頁面">
                <select value={page} onChange={e => setPage(e.target.value)} style={{ width: '100%' }}>
                  <option value="">請選擇…</option>
                  {PAGES.map(p => <option key={p} value={p}>{p}</option>)}
                </select>
              </Field>
              <Field label="嚴重度">
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6 }}>
                  {Object.entries(SEVERITY).map(([k, v]) => (
                    <button key={k} type="button" onClick={() => setSeverity(k)} className="btn" style={{
                      borderColor: severity === k ? v.c : null,
                      color: severity === k ? v.c : null,
                      background: severity === k ? v.b : null,
                    }}>{v.label}</button>
                  ))}
                </div>
              </Field>
            </div>
            <Field label="詳細內容 / Console 訊息">
              <textarea
                placeholder={'步驟、預期結果、實際結果、Console 錯誤訊息…\n\n貼越完整，Claude 越能準確定位問題。'}
                rows={10}
                value={body}
                onChange={e => setBody(e.target.value)}
                style={{ width: '100%', fontFamily: T.fontMono, fontSize: 12, lineHeight: 1.6, resize: 'vertical' }}
              />
            </Field>
            <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', paddingTop: 4 }}>
              <button className="btn" onClick={onClose}>取消</button>
              <button className="btn-primary btn" onClick={submit} disabled={!title.trim() || !body.trim()}>送出回報</button>
            </div>
          </div>
        </div>
      </div>
    );
  }

  function Field({ label, children }) {
    return (
      <label style={{ display: 'block' }}>
        <div className="mono" style={{ fontSize: 10, color: 'var(--fg-3)', letterSpacing: '.08em', marginBottom: 4 }}>{(label || '').toUpperCase()}</div>
        {children}
      </label>
    );
  }

})();
