// app.jsx — 状态、过滤、组装 + Tweaks
const { useState: useStateApp, useMemo: useMemoApp, useEffect: useEffectApp } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "buttonStyle": "seal",
  "paperTexture": "grid",
  "cardLayout": "list"
}/*EDITMODE-END*/;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  const [axis, setAxis] = useStateApp('time');
  const [timeFilter, setTimeFilter] = useStateApp({});
  const [placeFilter, setPlaceFilter] = useStateApp({});
  const [tagFilter, setTagFilter] = useStateApp('all');
  const [notebookFilter, setNotebookFilter] = useStateApp(null);
  const [stCity, setStCity] = useStateApp(null);       // 时空轴城市筛选

  const [openNote, setOpenNote] = useStateApp(null);   // 详情
  const [paperNote, setPaperNote] = useStateApp(null); // 书写视图（新建/编辑都走这里）
  const [metroOpen, setMetroOpen] = useStateApp(false);// 时空地图覆层
  const [contactsOpen, setContactsOpen] = useStateApp(false); // 通讯录
  const [skillsOpen, setSkillsOpen] = useStateApp(false);     // 技能工具箱
  const [shareNote, setShareNote] = useStateApp(null);        // 分享面板
  const [plansOpen, setPlansOpen] = useStateApp(false);       // 订阅档位
  const [inboxOpen, setInboxOpen] = useStateApp(false);       // 采集箱
  const [inboxTick, setInboxTick] = useStateApp(0);           // 采集箱刷新
  const [extraNotes, setExtraNotes] = useStateApp(
    () => (typeof savedNotesRead === 'function' ? savedNotesRead() : []));  // 整理进本子的笔记（localStorage 持久化）

  // 采集箱：手机端经同源 localStorage 收进来的（含演示种子）
  const inboxItems = useMemoApp(() => (typeof getInboxItems === 'function' ? getInboxItems() : []), [inboxTick]);
  // 手机端写入时（storage 事件）实时刷新计数；并在挂载后强制重算一次（规避脚本异步就绪时序）
  useEffectApp(() => {
    setInboxTick(t => t + 1);
    const onStore = e => { if (!e || e.key === INBOX_KEY) setInboxTick(t => t + 1); };
    const onSync  = () => setInboxTick(t => t + 1);
    window.addEventListener('storage', onStore);
    window.addEventListener('popor-inbox-sync', onSync);
    if (typeof startInboxSync === 'function') startInboxSync(5000);
    return () => { window.removeEventListener('storage', onStore); window.removeEventListener('popor-inbox-sync', onSync); };
  }, []);

  function organizeInbox(it) {
    setInboxOpen(false);
    setOpenNote(null);
    const localFallback = () => {
      const note = inboxToPaperNote(it);
      setExtraNotes(e => e.some(x => x.id === note.id) ? e : [note].concat(e));
      if (typeof savedNoteUpsert === 'function') savedNoteUpsert(note);
      setPaperNote(note);
    };
    if (typeof organizeInboxApi === 'function') {
      organizeInboxApi(it).then(note => {
        setExtraNotes(e => e.some(x => x.id === note.id) ? e : [note].concat(e));
        setPaperNote(note);
      }).catch(localFallback);
    } else localFallback();
    ibMarkDone(it.id);
    setInboxTick(t => t + 1);
  }
  function dismissInbox(it) { ibMarkDone(it.id); setInboxTick(t => t + 1); }

  // 书写台关闭时，把编辑后的正文写回（仅持久化已整理的笔记）
  function persistNote(updated) {
    if (!updated || !updated.id) return;
    setExtraNotes(list => {
      if (!list.some(x => x.id === updated.id)) return list;     // 只更新已在本地库里的
      const next = list.map(x => x.id === updated.id ? updated : x);
      if (typeof savedNoteUpsert === 'function') savedNoteUpsert(updated);
      return next;
    });
    if (/^note_/.test(updated.id)) {
      try {
        fetch((window.POPOR_API_BASE || '') + '/api/notes/' + encodeURIComponent(updated.id) + '/update', {
          method: 'POST', headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ title: updated.title, text: updated.body }),
        }).catch(() => {});
      } catch (e) {}
    }
  }

  // 全部标签（主分类 + 内容标签，去重）
  const workNotes = useMemoApp(() => extraNotes.concat(NOTES), [extraNotes]);
  const allTags = useMemoApp(() => {
    const s = [];
    workNotes.forEach(n => { [n.cat, ...n.notes].forEach(x => { if (x && !s.includes(x)) s.push(x); }); });
    return s;
  }, [workNotes]);

  // 时空轴的数据 = 已写入笔记 + 采集箱（按原件/整理两个时间落点，时间轴随之拉长）
  const axisNotes = useMemoApp(
    () => workNotes.concat(typeof inboxToAxisNotes === 'function' ? inboxToAxisNotes(inboxItems) : []),
    [workNotes, inboxItems]);

  // 过滤（交叉）
  const filtered = useMemoApp(() => workNotes.filter(n => {
    if (timeFilter.year && n.year !== timeFilter.year) return false;
    if (timeFilter.month && n.month !== timeFilter.month) return false;
    if (placeFilter.city && n.city !== placeFilter.city) return false;
    if (placeFilter.scene && n.scene !== placeFilter.scene) return false;
    if (tagFilter !== 'all' && n.cat !== tagFilter && !n.notes.includes(tagFilter)) return false;
    if (notebookFilter && n.notebook !== notebookFilter) return false;
    return true;
  }), [workNotes, timeFilter, placeFilter, tagFilter, notebookFilter]);

  const counts = useMemoApp(() => {
    const c = {};
    workNotes.forEach(n => { c[n.notebook] = (c[n.notebook] || 0) + 1; });
    return c;
  }, [workNotes]);

  const noteById = id => workNotes.find(n => n.id === id);
  const current = openNote ? noteById(openNote) : null;

  // 导入文件 → 直接进书写台（文本 → 加工 → 保存 的入口）
  function pcPlace() {
    // 电脑地点：第一次导入询问一次，存本机，以后自动带上（设置里可清 localStorage 重设）
    let place = localStorage.getItem('popor.pc.place');
    if (place === null) {
      place = prompt('这台电脑所在地点（如：深圳福田）？\n作为客观「录入地点」自动记录（文本里的时间地点另算），可留空：') || '';
      localStorage.setItem('popor.pc.place', place);
    }
    return place;
  }

  async function importFile(file) {
    try {
      const { title, body, image, kind, lossy } = await readImportedFile(file);
      const nb = NOTEBOOKS[0];
      setOpenNote(null);

      // ── 生产：导入即落库（双时间点：原件=文件修改时间，导入=现在）──
      const API = window.POPOR_API_BASE || '';
      const contentDate = file.lastModified
        ? new Date(file.lastModified).toISOString().slice(0, 10) : '';
      const place = pcPlace();
      let backendNote = null;
      try {
        if (body && body.trim()) {
          const r = await fetch(API + '/api/notes/text', {
            method: 'POST', headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ text: body, content_date: contentDate,
              import_location: place, manual_category: nb.name }) });
          if (r.ok) backendNote = (await r.json());
        } else if (image) {
          const blob = await (await fetch(image)).blob();
          const fd = new FormData();
          fd.append('file', new File([blob], file.name || 'import.jpg', { type: blob.type }));
          fd.append('content_date', contentDate);
          fd.append('import_location', place);
          fd.append('manual_category', nb.name);
          const r = await fetch(API + '/api/notes/upload', { method: 'POST', body: fd });
          if (r.ok) backendNote = (await r.json());
        }
      } catch (e) { backendNote = null; }

      if (backendNote && backendNote.note_id) {
        // 重新拉一次列表，让笔记进入主库与时空轴，然后打开书写台继续编辑
        const full = await fetch(API + '/api/notes/' + backendNote.note_id).then(r => r.json()).catch(() => null);
        const proto = (full && full.note && typeof transformNote === 'function') ? transformNote(full.note) : null;
        if (proto) {
          setExtraNotes(e => e.some(x => x.id === proto.id) ? e : [proto].concat(e));
          setPaperNote(proto);
          return;
        }
      }

      // ── 回落：后端不可达时保持原行为（仅本地预览）──
      setPaperNote({
        id: 'import-' + Date.now(),
        title: title || '导入的内容', en: '',
        date: NOW.date.replace(/-/g, '.'), time: NOW.time, year: '2026', month: '6月',
        city: NOW.city || '上海', scene: NOW.scene || '家', gps: '',
        notebook: nb.id, cat: nb.name, notes: [], locs: [],
        body: body || '', _blank: !body && !image, _imported: true, _lossy: lossy, _kind: kind, _image: image,
        nbName: nb.name, nbIcon: nb.lineIcon,
      });
    } catch (e) {
      alert('导入失败：' + (e.message || e));
    }
  }

  // 在某个本子下新建一页 → 直接进书写视图（干净的空白页）
  function newNoteIn(nbId) {
    const nb = NOTEBOOKS.find(n => n.id === nbId) || NOTEBOOKS[0];
    setOpenNote(null);
    setPaperNote({
      id: 'new-' + Date.now(),
      title: '新的一页', en: '',
      date: '2026.06.01', time: '11:15', year: '2026', month: '6月',
      city: '上海', scene: '家', gps: '31.23°N 121.47°E',
      notebook: nb.id, cat: nb.name, notes: [], locs: [],
      body: '', _blank: true, nbName: nb.name, nbIcon: nb.lineIcon,
    });
  }

  return (
    <div className="shell app-bg" data-btn={t.buttonStyle}>
      <TopBar notebooks={NOTEBOOKS} onImport={importFile}
        onOpenContacts={() => setContactsOpen(true)}
        onOpenSkills={() => setSkillsOpen(true)}
        onOpenShare={() => setShareNote(current || filtered[0] || NOTES[0])}
        onOpenInbox={() => setInboxOpen(true)} inboxCount={inboxItems.length}
        onOpenPlans={() => setPlansOpen(true)} />

      <NotebookRow notebooks={NOTEBOOKS} counts={counts}
        active={notebookFilter} onPick={setNotebookFilter}
        onNewNote={newNoteIn} onAdd={() => {}} />

      <div className="body3 no-right" data-cards={t.cardLayout}>
        <LeftAxis
          axis={axis} setAxis={setAxis} allNotes={axisNotes}
          timeFilter={timeFilter} setTimeFilter={setTimeFilter}
          placeFilter={placeFilter} setPlaceFilter={setPlaceFilter}
          onOpenNote={id => setOpenNote(id)}
          onExpandMetro={() => setMetroOpen(true)}
          onOpenInbox={() => setInboxOpen(true)}
          selectedNote={openNote} stCity={stCity} setStCity={setStCity} />

        <div className="center-wrap">
          <NoteList
            notes={filtered} allTags={allTags}
            tagFilter={tagFilter} setTagFilter={setTagFilter}
            selected={openNote} cardLayout={t.cardLayout}
            onOpen={id => setOpenNote(id)} />

          {current && (
            <DetailView
              note={current} notebook={NOTEBOOKS.find(nb => nb.id === current.notebook)}
              onBack={() => setOpenNote(null)}
              onWrite={n => setPaperNote(n)}
              onShare={n => setShareNote(n)} />
          )}
        </div>
      </div>

      {metroOpen && (
        <MetroMap onClose={() => setMetroOpen(false)}
          onOpenNote={id => { setMetroOpen(false); setOpenNote(id); }} />
      )}
      {paperNote && (
        <PaperView note={paperNote} onClose={() => setPaperNote(null)} onPersist={persistNote} defaultTexture={t.paperTexture}
          onOpenStore={() => { setPaperNote(null); setSkillsOpen(true); }} />
      )}

      {contactsOpen && (
        <ContactsView onClose={() => setContactsOpen(false)}
          onOpenNote={c => {
            const hit = NOTES.find(n => (n.notes || []).concat([n.title]).some(x => c.note && c.note.indexOf(x) >= 0))
              || NOTES.find(n => n.city === c.now);
            setContactsOpen(false);
            if (hit) setOpenNote(hit.id);
          }} />
      )}
      {skillsOpen && <SkillStore onClose={() => setSkillsOpen(false)} />}
      {inboxOpen && (
        <InboxPanel items={inboxItems} onClose={() => setInboxOpen(false)}
          onOrganize={organizeInbox} onDismiss={dismissInbox} />
      )}
      {shareNote && <ShareSheet note={shareNote} onClose={() => setShareNote(null)} />}
      {plansOpen && (
        <PlansPanel current={USER_WALLET.plan}
          onPick={() => setPlansOpen(false)}
          onClose={() => setPlansOpen(false)} />
      )}

      {/* —— Tweaks —— */}
      <TweaksPanel title="Tweaks">
        <TweakSection label="控件" />
        <TweakRadio label="按钮风格" value={t.buttonStyle}
          options={[{ value: 'seal', label: '朱砂印章' }, { value: 'wireframe', label: '极简线框' }, { value: 'stationery', label: '文具按键' }]}
          onChange={v => setTweak('buttonStyle', v)} />
        <TweakSection label="列表与纸张" />
        <TweakRadio label="卡片布局" value={t.cardLayout}
          options={[{ value: 'list', label: '紧凑列表' }, { value: 'grid', label: '卡片网格' }, { value: 'stream', label: '时间流' }]}
          onChange={v => setTweak('cardLayout', v)} />
        <TweakRadio label="纸张底纹" value={t.paperTexture}
          options={[{ value: 'grid', label: '方格' }, { value: 'lines', label: '横线' }, { value: 'dots', label: '点状' }, { value: 'blank', label: '留白' }]}
          onChange={v => setTweak('paperTexture', v)} />
      </TweaksPanel>
    </div>
  );
}

// 启动：先从后端拉取真实数据，注入全局后再渲染（失败自动回落示例数据）
function bootApp() {
  const root = ReactDOM.createRoot(document.getElementById('root'));
  const ready = (typeof loadNotes === 'function')
    ? loadNotes()
    : Promise.resolve({ notes: window.NOTES || [], notebooks: window.NOTEBOOKS });
  ready.then(({ notes, notebooks }) => {
    window.NOTES = notes;
    if (notebooks) window.NOTEBOOKS = notebooks;
    root.render(<App />);
  });
}
bootApp();
