// Main app — TOC sidebar (or top bar on mobile), progress, cards, summary modal.

const STORAGE_KEY = 'xiaojing-feedback-v1';

function loadState() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (!raw) return { states: {}, notes: {} };
    const parsed = JSON.parse(raw);
    return { states: parsed.states || {}, notes: parsed.notes || {} };
  } catch { return { states: {}, notes: {} }; }
}
function saveState(s) {
  try { localStorage.setItem(STORAGE_KEY, JSON.stringify(s)); } catch {}
}

// Flatten cards for numbering and total count
function flattenCards() {
  const out = [];
  CONTENT.sections.forEach(sec => {
    sec.cards.forEach(card => {
      out.push({ ...card, sectionId: sec.id, sectionLabel: sec.eyebrow });
    });
  });
  return out;
}

function ProgressBar({ done, total }) {
  const pct = total ? (done / total) * 100 : 0;
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 12, minWidth: 0, flex: 1 }}>
      <div style={{
        flex: 1, height: 4, background: T.rule, borderRadius: 999, overflow: 'hidden',
        minWidth: 80, maxWidth: 240,
      }}>
        <div style={{
          width: `${pct}%`, height: '100%', background: T.accent,
          transition: 'width 300ms ease',
        }} />
      </div>
      <span style={{
        fontSize: 12, color: T.inkMuted, whiteSpace: 'nowrap',
        fontFamily: '"SF Mono", ui-monospace, monospace',
        fontVariantNumeric: 'tabular-nums',
      }}>
        {done} / {total}
      </span>
    </div>
  );
}

function TOC({ activeSection, states, onNavigate, mobile, onClose }) {
  return (
    <nav style={{
      display: 'flex', flexDirection: 'column', gap: 2,
      padding: mobile ? '16px 20px 40px' : '0',
    }}>
      {CONTENT.sections.map((sec) => {
        const sectionCards = sec.cards;
        const sectionDone = sectionCards.filter(c => states[c.id]).length;
        const isActive = activeSection === sec.id;
        return (
          <div key={sec.id}>
            <a
              href={`#section-${sec.id}`}
              onClick={(e) => {
                e.preventDefault();
                onNavigate(sec.id);
                if (onClose) onClose();
              }}
              style={{
                display: 'flex', alignItems: 'flex-start', gap: 10,
                padding: '10px 12px', borderRadius: 8,
                textDecoration: 'none',
                color: isActive ? T.ink : T.inkMuted,
                background: isActive ? T.bg : 'transparent',
                transition: 'all 120ms ease',
                fontSize: 14, lineHeight: 1.4,
              }}
            >
              <span style={{
                fontSize: 11, fontFamily: '"SF Mono", ui-monospace, monospace',
                color: T.inkFaint, marginTop: 1, flexShrink: 0,
                fontVariantNumeric: 'tabular-nums',
              }}>
                {String(sectionDone).padStart(2, '0')}/{String(sectionCards.length).padStart(2, '0')}
              </span>
              <span style={{ fontWeight: isActive ? 500 : 400 }}>{sec.eyebrow}</span>
            </a>
          </div>
        );
      })}
    </nav>
  );
}

function SummaryModal({ open, onClose, cards, states, notes }) {
  const [copied, setCopied] = React.useState(false);
  const [tab, setTab] = React.useState('markdown');

  const summary = React.useMemo(() => {
    const byState = { agree: [], disagree: [], skip: [], add: [], untouched: [] };
    cards.forEach((card) => {
      const s = states[card.id];
      const n = notes[card.id];
      const entry = { card, note: n };
      if (s) byState[s].push(entry);
      else if (n) byState.add.push(entry);
      else byState.untouched.push(entry);
    });
    return byState;
  }, [cards, states, notes]);

  const total = cards.length;
  const done = total - summary.untouched.length;

  const markdown = React.useMemo(() => {
    const lines = [];
    lines.push(`# 晓静的反馈（${new Date().toLocaleString('zh-CN')}）`);
    lines.push('');
    lines.push(`已反馈 ${done} / ${total} 段。`);
    lines.push('');

    const section = (label, list, emoji) => {
      if (!list.length) return;
      lines.push(`## ${emoji} ${label}（${list.length}）`);
      lines.push('');
      list.forEach(({ card, note }) => {
        lines.push(`- **${card.title}**${card.sectionLabel ? `  · _${card.sectionLabel}_` : ''}`);
        if (note) lines.push(`  > ${note.replace(/\n/g, '\n  > ')}`);
      });
      lines.push('');
    };

    section('不对 / 不是我意思', summary.disagree, '❌');
    section('我想补充', summary.add, '➕');
    section('这条对', summary.agree, '✅');
    section('不重要 / 跳过', summary.skip, '🤔');

    if (summary.untouched.length) {
      lines.push(`## ⏳ 还没看（${summary.untouched.length}）`);
      lines.push('');
      summary.untouched.forEach(({ card }) => {
        lines.push(`- ${card.title}`);
      });
      lines.push('');
    }
    return lines.join('\n');
  }, [summary, done, total]);

  const json = React.useMemo(() => {
    const entries = cards.map((card) => ({
      id: card.id,
      title: card.title,
      section: card.sectionLabel,
      state: states[card.id] || null,
      note: notes[card.id] || null,
    }));
    return JSON.stringify({
      generated_at: new Date().toISOString(),
      total,
      done,
      entries,
    }, null, 2);
  }, [cards, states, notes, total, done]);

  const text = tab === 'markdown' ? markdown : json;

  if (!open) return null;

  const copy = async () => {
    try {
      await navigator.clipboard.writeText(text);
      setCopied(true);
      setTimeout(() => setCopied(false), 1500);
    } catch {}
  };

  const download = () => {
    const blob = new Blob([text], { type: tab === 'markdown' ? 'text/markdown' : 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `xiaojing-feedback.${tab === 'markdown' ? 'md' : 'json'}`;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div
      onClick={onClose}
      style={{
        position: 'fixed', inset: 0, zIndex: 100,
        background: 'rgba(20,16,12,0.45)',
        backdropFilter: 'blur(6px)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        padding: 20,
      }}
    >
      <div
        onClick={(e) => e.stopPropagation()}
        style={{
          background: T.paper, borderRadius: 16,
          width: '100%', maxWidth: 720, maxHeight: '88vh',
          display: 'flex', flexDirection: 'column',
          boxShadow: '0 24px 64px rgba(0,0,0,0.25)',
          overflow: 'hidden',
        }}
      >
        <div style={{
          padding: '22px 28px 18px',
          borderBottom: `1px solid ${T.ruleSoft}`,
          display: 'flex', alignItems: 'center', gap: 16,
        }}>
          <div style={{ flex: 1 }}>
            <h3 style={{ margin: 0, fontSize: 20, fontWeight: 600, color: T.ink }}>
              你的反馈汇总
            </h3>
            <div style={{ fontSize: 13, color: T.inkMuted, marginTop: 4 }}>
              已反馈 {done} / {total} 段 · 复制文本发微信给哥哥就行
            </div>
          </div>
          <button onClick={onClose} style={{
            width: 36, height: 36, borderRadius: 8,
            border: `1px solid ${T.rule}`, background: 'transparent',
            cursor: 'pointer', color: T.inkMuted,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontFamily: 'inherit',
          }}>
            <svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/></svg>
          </button>
        </div>

        {/* Tabs */}
        <div style={{
          padding: '12px 28px 0',
          borderBottom: `1px solid ${T.ruleSoft}`,
          display: 'flex', gap: 4,
        }}>
          {['markdown', 'json'].map(k => (
            <button key={k} onClick={() => setTab(k)} style={{
              padding: '8px 14px', border: 'none',
              background: 'transparent',
              color: tab === k ? T.ink : T.inkMuted,
              fontWeight: tab === k ? 500 : 400,
              fontSize: 13, cursor: 'pointer',
              borderBottom: `2px solid ${tab === k ? T.ink : 'transparent'}`,
              marginBottom: -1, fontFamily: 'inherit',
            }}>
              {k === 'markdown' ? '可读文本' : 'JSON（结构化）'}
            </button>
          ))}
        </div>

        {/* Content */}
        <div style={{
          flex: 1, overflow: 'auto',
          padding: '18px 28px',
        }}>
          <pre style={{
            margin: 0,
            fontFamily: '"SF Mono", "JetBrains Mono", ui-monospace, Menlo, monospace',
            fontSize: 13, lineHeight: 1.65,
            color: T.ink,
            whiteSpace: 'pre-wrap', wordBreak: 'break-word',
          }}>{text}</pre>
        </div>

        {/* Actions */}
        <div style={{
          padding: '14px 28px 20px',
          borderTop: `1px solid ${T.ruleSoft}`,
          display: 'flex', gap: 10, flexWrap: 'wrap',
        }}>
          <button onClick={copy} style={{
            flex: 1, minWidth: 120,
            minHeight: 44, padding: '0 18px',
            background: copied ? T.accent : T.ink,
            color: '#fff', border: 'none', borderRadius: 10,
            fontSize: 15, fontWeight: 500, cursor: 'pointer',
            fontFamily: 'inherit',
          }}>
            {copied ? '已复制 ✓' : '复制全部文本'}
          </button>
          <button onClick={download} style={{
            minHeight: 44, padding: '0 18px',
            background: 'transparent', color: T.ink,
            border: `1px solid ${T.rule}`, borderRadius: 10,
            fontSize: 15, fontWeight: 500, cursor: 'pointer',
            fontFamily: 'inherit',
          }}>
            下载文件
          </button>
        </div>
      </div>
    </div>
  );
}

function App() {
  const [{ states, notes }, setData] = React.useState(loadState);
  const [activeSection, setActiveSection] = React.useState(CONTENT.sections[0].id);
  const [summaryOpen, setSummaryOpen] = React.useState(false);
  const [tocOpen, setTocOpen] = React.useState(false);
  const [isMobile, setIsMobile] = React.useState(() => window.innerWidth < 900);

  React.useEffect(() => {
    const onResize = () => setIsMobile(window.innerWidth < 900);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);

  const allCards = React.useMemo(flattenCards, []);
  const total = allCards.length;
  const done = allCards.filter(c => states[c.id] || notes[c.id]).length;

  React.useEffect(() => {
    saveState({ states, notes });
  }, [states, notes]);

  const setCardState = (id, s) => {
    setData(prev => {
      const next = { ...prev.states };
      if (s === null) delete next[id]; else next[id] = s;
      return { states: next, notes: prev.notes };
    });
  };
  const setCardNote = (id, n) => {
    setData(prev => {
      const next = { ...prev.notes };
      if (!n) delete next[id]; else next[id] = n;
      return { states: prev.states, notes: next };
    });
  };

  const navigate = (sectionId) => {
    setActiveSection(sectionId);
    const el = document.getElementById(`section-${sectionId}`);
    if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
  };

  // IntersectionObserver to update TOC active section
  React.useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        const visible = entries
          .filter(e => e.isIntersecting)
          .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top);
        if (visible[0]) {
          const id = visible[0].target.id.replace('section-', '');
          setActiveSection(id);
        }
      },
      { rootMargin: '-80px 0px -60% 0px', threshold: 0 }
    );
    CONTENT.sections.forEach(sec => {
      const el = document.getElementById(`section-${sec.id}`);
      if (el) observer.observe(el);
    });
    return () => observer.disconnect();
  }, []);

  let cardIndex = -1;

  const reset = () => {
    if (confirm('清空所有反馈？（刚刚输入的文本也会一起清掉）')) {
      setData({ states: {}, notes: {} });
    }
  };

  return (
    <div style={{
      minHeight: '100vh', background: T.bgDeep,
      color: T.ink,
    }}>
      {/* Top bar */}
      <header style={{
        position: 'sticky', top: 0, zIndex: 30,
        background: 'rgba(243, 239, 230, 0.88)',
        backdropFilter: 'blur(12px)',
        borderBottom: `1px solid ${T.rule}`,
      }}>
        <div style={{
          maxWidth: 1280, margin: '0 auto',
          padding: '14px clamp(16px, 3vw, 32px)',
          display: 'flex', alignItems: 'center', gap: 16,
        }}>
          {isMobile && (
            <button onClick={() => setTocOpen(true)} style={{
              width: 40, height: 40, borderRadius: 8,
              border: `1px solid ${T.rule}`, background: T.paper,
              cursor: 'pointer', flexShrink: 0,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: T.ink,
            }}>
              <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
                <path d="M2 4h12M2 8h12M2 12h12" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/>
              </svg>
            </button>
          )}
          <div style={{ minWidth: 0, flexShrink: 1 }}>
            <div style={{
              fontSize: 11, color: T.inkFaint, letterSpacing: 0.8,
              fontFamily: '"SF Mono", ui-monospace, monospace',
              textTransform: 'uppercase',
            }}>
              晓静方案
            </div>
            <div style={{
              fontSize: 14, fontWeight: 500, color: T.ink,
              whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
            }}>
              AI 改造初步方案 · 反馈页
            </div>
          </div>
          <div style={{ flex: 1, display: 'flex', justifyContent: 'flex-end', gap: 12, alignItems: 'center', minWidth: 0 }}>
            {!isMobile && <ProgressBar done={done} total={total} />}
            <button onClick={() => setSummaryOpen(true)} style={{
              minHeight: 40, padding: '0 16px',
              background: T.ink, color: '#fff',
              border: 'none', borderRadius: 999,
              fontSize: 13.5, fontWeight: 500, cursor: 'pointer',
              fontFamily: 'inherit', flexShrink: 0,
              display: 'inline-flex', alignItems: 'center', gap: 6,
            }}>
              生成反馈汇总
              {done > 0 && (
                <span style={{
                  background: 'rgba(255,255,255,0.18)',
                  padding: '2px 7px', borderRadius: 999,
                  fontSize: 11, fontVariantNumeric: 'tabular-nums',
                }}>{done}</span>
              )}
            </button>
          </div>
        </div>
        {isMobile && (
          <div style={{
            padding: '0 clamp(16px, 3vw, 32px) 10px',
            maxWidth: 1280, margin: '0 auto',
          }}>
            <ProgressBar done={done} total={total} />
          </div>
        )}
      </header>

      {/* Body */}
      <div style={{
        maxWidth: 1280, margin: '0 auto',
        padding: 'clamp(20px, 4vw, 40px) clamp(16px, 3vw, 32px) 120px',
        display: 'grid',
        gridTemplateColumns: isMobile ? '1fr' : '220px 1fr',
        gap: isMobile ? 0 : 48,
        alignItems: 'start',
      }}>
        {/* Sidebar */}
        {!isMobile && (
          <aside style={{
            position: 'sticky', top: 88,
            maxHeight: 'calc(100vh - 108px)',
            overflow: 'auto',
          }}>
            <div style={{
              fontSize: 11, color: T.inkFaint, letterSpacing: 1,
              fontFamily: '"SF Mono", ui-monospace, monospace',
              textTransform: 'uppercase',
              padding: '4px 12px 10px',
            }}>目录</div>
            <TOC
              activeSection={activeSection}
              states={states}
              onNavigate={navigate}
            />
            <button onClick={reset} style={{
              marginTop: 24, width: '100%',
              padding: '10px 12px',
              background: 'transparent', color: T.inkFaint,
              border: `1px dashed ${T.rule}`, borderRadius: 8,
              fontSize: 12, cursor: 'pointer',
              fontFamily: 'inherit',
            }}>
              清空所有反馈
            </button>
          </aside>
        )}

        {/* Main */}
        <main style={{ minWidth: 0 }}>
          {/* Intro block */}
          <section style={{ marginBottom: 48, padding: '8px 4px 0' }}>
            <div style={{
              fontSize: 12, color: T.inkFaint, letterSpacing: 1,
              fontFamily: '"SF Mono", ui-monospace, monospace',
              textTransform: 'uppercase', marginBottom: 14,
            }}>
              致晓静 · {new Date().toLocaleDateString('zh-CN')}
            </div>
            <h1 style={{
              margin: '0 0 18px', fontSize: 'clamp(32px, 5vw, 44px)',
              fontWeight: 500, letterSpacing: -1,
              color: T.ink, lineHeight: 1.15,
            }}>
              {CONTENT.title}
            </h1>
            <p style={{
              margin: '0 0 12px', fontSize: 17, lineHeight: 1.75,
              color: T.inkMuted, maxWidth: 620,
            }}>
              {CONTENT.subtitle}
            </p>
            <div style={{
              marginTop: 20, padding: '14px 18px',
              background: T.paper, border: `1px solid ${T.rule}`,
              borderRadius: 12, maxWidth: 620,
              fontSize: 14.5, lineHeight: 1.7, color: T.inkMuted,
            }}>
              <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
                <span style={{
                  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                  width: 22, height: 22, borderRadius: 6,
                  background: T.bg, color: T.ink, fontSize: 13,
                  flexShrink: 0, marginTop: 1,
                }}>?</span>
                <div>
                  每张卡片下面有四个按钮：<b style={{ color: T.accent }}>对</b> / <b style={{ color: T.warn }}>不是我意思</b> / <b style={{ color: T.neutral }}>不重要</b> / <b style={{ color: T.add }}>补充</b>。
                  点一下会变色，再点一下取消。标 <span style={{ color: T.star }}>⭐</span> 的是关键段落，优先看。
                  全部看完（或者你觉得差不多了）点右上角「生成反馈汇总」，复制发微信给哥哥就行。
                </div>
              </div>
            </div>
          </section>

          {/* Sections */}
          {CONTENT.sections.map((sec) => (
            <section
              key={sec.id}
              id={`section-${sec.id}`}
              data-screen-label={sec.eyebrow}
              style={{ marginBottom: 56, scrollMarginTop: 100 }}
            >
              <div style={{ marginBottom: 22, padding: '0 4px' }}>
                <div style={{
                  fontSize: 11, color: T.inkFaint, letterSpacing: 1,
                  fontFamily: '"SF Mono", ui-monospace, monospace',
                  textTransform: 'uppercase', marginBottom: 6,
                }}>
                  {sec.eyebrow}
                </div>
                <h2 style={{
                  margin: '0 0 8px', fontSize: 'clamp(24px, 3.2vw, 30px)',
                  fontWeight: 500, letterSpacing: -0.5,
                  color: T.ink, lineHeight: 1.25,
                }}>
                  {sec.title}
                </h2>
                {sec.intro && (
                  <p style={{
                    margin: 0, fontSize: 15.5, lineHeight: 1.7,
                    color: T.inkMuted, maxWidth: 640,
                  }}>
                    {sec.intro}
                  </p>
                )}
              </div>
              {sec.cards.map((card) => {
                cardIndex += 1;
                return (
                  <FeedbackCard
                    key={card.id}
                    card={{ ...card, sectionLabel: sec.eyebrow }}
                    state={states[card.id] || null}
                    note={notes[card.id] || ''}
                    index={cardIndex}
                    onState={(s) => setCardState(card.id, s)}
                    onNote={(n) => setCardNote(card.id, n)}
                  />
                );
              })}
            </section>
          ))}

          {/* Footer CTA */}
          <div style={{
            marginTop: 40, padding: 'clamp(28px, 5vw, 44px)',
            background: T.paper, border: `1px solid ${T.rule}`,
            borderRadius: 16, textAlign: 'center',
          }}>
            <div style={{
              fontSize: 11, color: T.inkFaint, letterSpacing: 1,
              fontFamily: '"SF Mono", ui-monospace, monospace',
              textTransform: 'uppercase', marginBottom: 10,
            }}>
              看完了
            </div>
            <h3 style={{
              margin: '0 0 10px', fontSize: 22, fontWeight: 500,
              color: T.ink, letterSpacing: -0.3,
            }}>
              点一下生成反馈汇总
            </h3>
            <p style={{
              margin: '0 auto 22px', fontSize: 15, color: T.inkMuted,
              lineHeight: 1.7, maxWidth: 440,
            }}>
              {done} / {total} 段已反馈。没看完也能生成——未反馈的段落会单独列出来。
            </p>
            <button onClick={() => setSummaryOpen(true)} style={{
              minHeight: 48, padding: '0 28px',
              background: T.ink, color: '#fff', border: 'none',
              borderRadius: 999, fontSize: 15, fontWeight: 500,
              cursor: 'pointer', fontFamily: 'inherit',
            }}>
              生成反馈汇总 →
            </button>
          </div>
        </main>
      </div>

      {/* Mobile TOC drawer */}
      {isMobile && tocOpen && (
        <div
          onClick={() => setTocOpen(false)}
          style={{
            position: 'fixed', inset: 0, zIndex: 50,
            background: 'rgba(20,16,12,0.45)',
            backdropFilter: 'blur(4px)',
          }}
        >
          <div
            onClick={(e) => e.stopPropagation()}
            style={{
              position: 'absolute', top: 0, left: 0, bottom: 0,
              width: 'min(280px, 82vw)',
              background: T.paper,
              boxShadow: '2px 0 16px rgba(0,0,0,0.1)',
              overflow: 'auto',
            }}
          >
            <div style={{
              padding: '20px 20px 8px',
              display: 'flex', alignItems: 'center', justifyContent: 'space-between',
              borderBottom: `1px solid ${T.ruleSoft}`,
            }}>
              <span style={{
                fontSize: 11, color: T.inkFaint, letterSpacing: 1,
                fontFamily: '"SF Mono", ui-monospace, monospace',
                textTransform: 'uppercase',
              }}>目录</span>
              <button onClick={() => setTocOpen(false)} style={{
                width: 32, height: 32, borderRadius: 6,
                border: 'none', background: T.bg, cursor: 'pointer',
                color: T.inkMuted,
              }}>
                <svg width="12" height="12" viewBox="0 0 16 16" fill="none" style={{ verticalAlign: 'middle' }}>
                  <path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/>
                </svg>
              </button>
            </div>
            <TOC
              activeSection={activeSection}
              states={states}
              onNavigate={navigate}
              onClose={() => setTocOpen(false)}
              mobile
            />
            <div style={{ padding: '0 20px 20px' }}>
              <button onClick={() => { reset(); setTocOpen(false); }} style={{
                width: '100%', padding: '10px 12px',
                background: 'transparent', color: T.inkFaint,
                border: `1px dashed ${T.rule}`, borderRadius: 8,
                fontSize: 12, cursor: 'pointer', fontFamily: 'inherit',
              }}>
                清空所有反馈
              </button>
            </div>
          </div>
        </div>
      )}

      <SummaryModal
        open={summaryOpen}
        onClose={() => setSummaryOpen(false)}
        cards={allCards}
        states={states}
        notes={notes}
      />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
