// Main app shell — real camera → /analyze → structured result render
function App({ variant }) {
  const [screen, setScreen] = React.useState('camera'); // camera | loading | result | zukan
  const [photo, setPhoto] = React.useState(null);       // data URL of captured photo
  const [analysis, setAnalysis] = React.useState(null); // { base fields + levels: {hs: {...}} }
  const [level, setLevel] = React.useState(() => localStorage.getItem('naz_level') || 'hs');
  const [tone, setTone] = React.useState(() => localStorage.getItem('naz_tone') || 'formal');
  const [error, setError] = React.useState(null);
  const [entries, setEntries] = React.useState(() => {
    try { return JSON.parse(localStorage.getItem('naz_zukan_v2') || '[]'); } catch { return []; }
  });

  const persistEntries = (next) => {
    setEntries(next);
    try { localStorage.setItem('naz_zukan_v2', JSON.stringify(next.slice(0, 100))); } catch {}
  };

  const changeLevel = async (lv) => {
    setLevel(lv);
    localStorage.setItem('naz_level', lv);
    if (!analysis) return;
    if (analysis.levels?.[lv]) return; // cached
    try {
      const r = await fetch('/analyze', {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({ image: analysis.__image, level: lv, tone }),
      });
      const j = await r.json();
      if (j.error) throw new Error(j.error);
      setAnalysis(a => ({ ...a, levels: { ...(a.levels||{}), [lv]: j } }));
    } catch (e) {
      console.error('level switch failed', e);
    }
  };

  const changeTone = (t) => { setTone(t); localStorage.setItem('naz_tone', t); };

  const analyzePhoto = async (dataUrl) => {
    setPhoto(dataUrl);
    setScreen('loading');
    setError(null);
    try {
      const r = await fetch('/analyze', {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({ image: dataUrl, level, tone }),
      });
      const j = await r.json();
      if (j.error) throw new Error(j.error);
      const a = {
        ...j,
        __image: dataUrl,
        thumb: dataUrl,
        levels: { [level]: j },
      };
      setAnalysis(a);
      setScreen('result');
      const d = new Date();
      const date = `${String(d.getMonth() + 1).padStart(2, '0')}/${String(d.getDate()).padStart(2, '0')}`;
      const entry = { id: Date.now(), subject: a, date };
      persistEntries([entry, ...entries].slice(0, 100));
    } catch (e) {
      console.error('analyze failed', e);
      setError(e.message || '解析に失敗しました');
      setScreen('camera');
    }
  };

  const closeResult = () => setScreen('camera');
  const openZukan = () => setScreen('zukan');
  const closeZukan = () => setScreen('camera');
  const openEntry = (entry) => {
    setAnalysis(entry.subject);
    setPhoto(entry.subject.__image || entry.subject.thumb);
    setScreen('result');
  };
  const clearZukan = () => {
    if (!confirm('図鑑を全て消去しますか？')) return;
    persistEntries([]);
  };
  const cycleVariant = () => {
    const order = ['encyclopedia', 'museum', 'notebook'];
    const next = order[(order.indexOf(variant) + 1) % order.length];
    window.__setVariant?.(next);
  };

  const ResultComponent = {
    museum: MuseumResult,
    notebook: NotebookResult,
    encyclopedia: EncyclopediaResult,
  }[variant] || EncyclopediaResult;

  const currentSubject = analysis ? flattenForDisplay(analysis, level, tone) : null;

  return (
    <>
      <CameraView
        variant={variant}
        onCapture={analyzePhoto}
        onOpenBook={openZukan}
        onOpenSettings={cycleVariant}
      />

      {error && (
        <div style={{
          position: 'absolute', top: 60, left: 16, right: 16, zIndex: 50,
          background: '#c04040', color: '#fff', padding: '10px 14px',
          borderRadius: 8, fontSize: 13, textAlign: 'center', cursor: 'pointer',
        }} onClick={() => setError(null)}>{error}（タップで閉じる）</div>
      )}

      {screen === 'loading' && (
        <div style={overlayStyle()}>
          <LoadingScreen variant={variant}/>
        </div>
      )}

      {screen === 'result' && currentSubject && (
        <div style={overlayStyle()}>
          <ResultComponent
            subject={currentSubject}
            level={level}
            onChangeLevel={changeLevel}
            tone={tone}
            onChangeTone={changeTone}
            onClose={closeResult}
          />
        </div>
      )}

      {screen === 'zukan' && (
        <div style={overlayStyle()}>
          <ZukanScreen
            variant={variant}
            entries={entries}
            onOpen={openEntry}
            onClose={closeZukan}
            onClear={clearZukan}
          />
        </div>
      )}
    </>
  );
}

function overlayStyle() {
  return {
    position: 'absolute', inset: 0, zIndex: 30,
    animation: 'sheetIn 0.35s cubic-bezier(0.2, 0.9, 0.3, 1) both',
  };
}

function flattenForDisplay(analysis, level, tone) {
  const lv = analysis.levels?.[level] || analysis.levels?.hs || analysis;
  return {
    ...analysis,
    ...lv,
    thumb: analysis.thumb || analysis.__image,
  };
}

window.App = App;
window.flattenForDisplay = flattenForDisplay;
