/* 彩云间 — 主应用：路由 / 导航 / 状态 / Tweaks */

const CY_CUTE_TITLES = ['云朵萌新','小云童','观云员','追云少年','集云达人','云朵铁粉','云图馆长','云朵之神'];
function levelFor(n, voice) {
  const base = window.cyLevelFor(n);
  if (voice === 'cute') {
    return { ...base, title: CY_CUTE_TITLES[base.index],
      next: base.next ? { ...base.next, title: CY_CUTE_TITLES[base.index+1] } : null };
  }
  return base;
}

// 主题
const CY_THEMES = {
  '晴空': { sky1:'#bfe0f7', sky2:'#d8edfb', sky3:'#f4fafe', bg:'#f3f9fe', card:'#fffdf8', cardDim:'#e8f1f9',
            ink:'#32485c', inkSoft:'#8298ab', line:'#dde8f1', accent:'#ef9f74', accent2:'#5a9fd4' },
  '黄昏': { sky1:'#f3b98a', sky2:'#f6cf9e', sky3:'#fbeed8', bg:'#fcf4ea', card:'#fffdf9', cardDim:'#f6e7d6',
            ink:'#5a4439', inkSoft:'#ac9181', line:'#f0e2d3', accent:'#e87b6a', accent2:'#f0a85c' },
  '薄荷': { sky1:'#a8ddd0', sky2:'#cdebe2', sky3:'#eef8f4', bg:'#f1faf6', card:'#fffdf9', cardDim:'#dff0e9',
            ink:'#2f4f48', inkSoft:'#7ba096', line:'#d8ece4', accent:'#52b496', accent2:'#6fb8c9' },
};
const CY_NAMEFONTS = { '宋体':"'Noto Serif SC', serif", '黑体':"'Noto Sans SC', sans-serif" };

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "晴空",
  "radius": 20,
  "nameFont": "宋体",
  "voice": "poetic",
  "petals": true,
  "daypart": "auto",
  "recogMode": "auto"
}/*EDITMODE-END*/;

// 把拍摄照片缩小后再存进本地，避免 localStorage 撑爆
function shrinkPhoto(dataUrl, max = 420) {
  return new Promise(resolve => {
    if (!dataUrl) return resolve(null);
    const img = new Image();
    img.onload = () => {
      const scale = Math.min(1, max / Math.max(img.width, img.height));
      const cv = document.createElement('canvas');
      cv.width = Math.round(img.width * scale);
      cv.height = Math.round(img.height * scale);
      cv.getContext('2d').drawImage(img, 0, 0, cv.width, cv.height);
      try { resolve(cv.toDataURL('image/jpeg', 0.7)); } catch (e) { resolve(null); }
    };
    img.onerror = () => resolve(null);
    img.src = dataUrl;
  });
}

const CY_STORE = 'cy-state-v2';
const CY_LEGACY_STORES = ['cy-state-v1'];
function loadState() {
  CY_LEGACY_STORES.forEach(key => {
    try { localStorage.removeItem(key); } catch (e) {}
  });
  try {
    const s = JSON.parse(localStorage.getItem(CY_STORE));
    if (s && s.collected) {
      if (!s.records) s.records = [];
      if (s.avatar == null) s.avatar = 0;
      if (s.captures == null) s.captures = 0;
      if (s.streak == null) s.streak = 0;
      return s;
    }
  } catch (e) {}
  return emptyState();
}

function emptyState() {
  return { collected: [], captures: 0, streak: 0, records: [], avatar: 0 };
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [state, setState] = React.useState(loadState);
  const [tab, setTab] = React.useState('sky');
  const [modal, setModal] = React.useState(null);

  React.useEffect(() => { localStorage.setItem(CY_STORE, JSON.stringify(state)); }, [state]);

  // 识别来源 → 适配器配置
  React.useEffect(() => { window.CloudRecognizer.setConfig({ mode: t.recogMode }); }, [t.recogMode]);

  // 主题 → CSS 变量
  const theme = CY_THEMES[t.theme] || CY_THEMES['晴空'];
  const rootVars = {
    '--cy-sky1':theme.sky1, '--cy-sky2':theme.sky2, '--cy-sky3':theme.sky3,
    '--cy-bg':theme.bg, '--cy-card':theme.card, '--cy-card-dim':theme.cardDim,
    '--cy-ink':theme.ink, '--cy-ink-soft':theme.inkSoft, '--cy-line':theme.line,
    '--cy-accent':theme.accent, '--cy-accent2':theme.accent2,
    '--cy-r': t.radius + 'px',
    '--cy-serif': CY_NAMEFONTS[t.nameFont] || CY_NAMEFONTS['宋体'],
    '--cy-sans': "'Noto Sans SC', sans-serif",
    '--cy-brand': "'Ma Shan Zheng', cursive",
    '--cy-shadow': '0 6px 22px rgba(60,90,120,.10)',
  };

  const level = levelFor(state.collected.length, t.voice);

  // 选取目标云（模拟回退用，优先未收集）
  const pickTarget = () => {
    const un = window.CY_CLOUDS.filter(c => !state.collected.includes(c.id));
    const pool = un.length ? un : window.CY_CLOUDS;
    return pool[Math.floor(Math.random() * pool.length)];
  };

  const openCamera  = () => setModal({ type:'camera', fallback: pickTarget() });
  const openCloud   = (id) => setModal({ type:'detail', id });
  const openJournal = () => setModal({ type:'journal' });
  const clearLocalData = () => {
    if (!window.confirm('清空本机的收集记录和观云记录？此操作不会影响线上部署。')) return;
    [CY_STORE, ...CY_LEGACY_STORES].forEach(key => localStorage.removeItem(key));
    setState(emptyState());
    setModal(null);
    setTab('sky');
  };

  // 拍下 → 进入识别（带上照片，可能为 null）
  const onShutter = (photo) => {
    setModal(m => ({ type:'recognizing', fallback: m.fallback, photo }));
  };

  // 识别完成 → 记一条观云记录 + 出结果
  const onRecognized = async (res) => {
    if (res.failed) {
      setModal({ type:'error', fallback: modal.fallback, photo: modal.photo, reason: res.reason, source: res.source });
      return;
    }
    if (res.noCloud) {
      setModal({ type:'noCloud', fallback: modal.fallback, photo: modal.photo, reason: res.reason, conf: res.confidence, source: res.source });
      return;
    }
    const c = res.cloud;
    const isNew = !state.collected.includes(c.id);
    const conf = res.confidence;
    const photo = modal.photo;
    const small = await shrinkPhoto(photo);
    const record = { id:c.id, ts: Date.now(), isNew, conf, photo: small, source: res.source };
    setState(s => ({ ...s, captures: s.captures + 1, records: [...(s.records||[]), record] }));
    setModal({ type:'result', id:c.id, isNew, conf, photo, reason: res.reason, source: res.source });
  };

  const retryRecognition = () => {
    setModal(m => ({ type:'recognizing', fallback: m.fallback || pickTarget(), photo: m.photo }));
  };

  const collect = () => {
    const id = modal.id;
    setState(s => s.collected.includes(id) ? s : { ...s, collected:[...s.collected, id] });
    setModal(null);
    setTab('gallery');
  };

  const cloudById = (id) => window.CY_CLOUDS.find(c => c.id === id);

  return (
    <div className="cy-root" style={rootVars}>
      <CloudDefs/>
      <div className="cy-stage">
      <div className="cy-device">
        <div className="cy-app-viewport" style={{ height:'100%', position:'relative', background:'var(--cy-bg)', overflow:'hidden' }}>
          {/* 标签内容 */}
          <div style={{ height:'100%', paddingTop:'env(safe-area-inset-top)', boxSizing:'border-box' }}>
            {tab === 'sky'     && <HomeScreen state={state} level={level} daypart={t.daypart} onCapture={openCamera} onOpenCloud={openCloud} goTab={setTab}/>}
            {tab === 'gallery' && <GalleryScreen state={state} onOpenCloud={openCloud}/>}
            {tab === 'me'      && <ProfileScreen state={state} level={level} onOpenCloud={openCloud} onOpenJournal={openJournal}/>}
          </div>

          {/* 底部导航 */}
          {!modal && <BottomNav tab={tab} setTab={setTab} onCapture={openCamera}/>}

          {/* 覆盖层 */}
          {modal?.type === 'camera' &&
            <CameraScreen fallbackCloud={modal.fallback} onShutter={onShutter} onClose={() => setModal(null)}/>}
          {modal?.type === 'recognizing' &&
            <RecognizingScreen photo={modal.photo} fallbackCloud={modal.fallback} collected={state.collected} onDone={onRecognized}/>}
          {modal?.type === 'result' &&
            <ResultScreen cloud={cloudById(modal.id)} isNew={modal.isNew} conf={modal.conf} photo={modal.photo} petals={t.petals}
              reason={modal.reason} source={modal.source}
              onCollect={collect} onRetake={openCamera} onClose={() => setModal(null)}/>}
          {modal?.type === 'noCloud' &&
            <NoCloudScreen photo={modal.photo} reason={modal.reason} conf={modal.conf}
              onRetake={openCamera} onClose={() => setModal(null)}/>}
          {modal?.type === 'error' &&
            <RecognitionErrorScreen photo={modal.photo} reason={modal.reason}
              onRetry={retryRecognition} onRetake={openCamera} onClose={() => setModal(null)}/>}
          {modal?.type === 'detail' &&
            <DetailScreen cloud={cloudById(modal.id)} records={state.records} onClose={() => setModal(null)}/>}
          {modal?.type === 'journal' &&
            <JournalScreen records={state.records} onOpenCloud={openCloud} onCapture={openCamera} onClose={() => setModal(null)}/>}
        </div>
      </div>
      </div>

      <TweaksPanel>
        <TweakSection label="外观"/>
        <TweakRadio label="配色" value={t.theme} options={['晴空','黄昏','薄荷']} onChange={v => setTweak('theme', v)}/>
        <TweakRadio label="云名字体" value={t.nameFont} options={['宋体','黑体']} onChange={v => setTweak('nameFont', v)}/>
        <TweakSlider label="圆角" value={t.radius} min={10} max={28} unit="px" onChange={v => setTweak('radius', v)}/>
        <TweakSection label="首页天色"/>
        <TweakSelect label="今日天空" value={t.daypart}
          options={[{label:'随时间自动',value:'auto'},{label:'白天',value:'day'},{label:'夜晚',value:'night'}]}
          onChange={v => setTweak('daypart', v)}/>
        <TweakSection label="识别与称号"/>
        <TweakRadio label="识别来源" value={t.recogMode}
          options={[{label:'模拟',value:'mock'},{label:'自动',value:'auto'},{label:'接口',value:'api'}]}
          onChange={v => setTweak('recogMode', v)}/>
        <TweakRadio label="称号口吻" value={t.voice} options={[{label:'诗意',value:'poetic'},{label:'可爱',value:'cute'}]} onChange={v => setTweak('voice', v)}/>
        <TweakToggle label="收集时撒花" value={t.petals} onChange={v => setTweak('petals', v)}/>
        <TweakButton label="清空本地记录" secondary onClick={clearLocalData}/>
      </TweaksPanel>
    </div>
  );
}

// 底部导航：天空 / 拍云FAB / 图鉴
function BottomNav({ tab, setTab, onCapture }) {
  const TabBtn = ({ id, icon, label }) => {
    const on = tab === id;
    return (
      <button onClick={() => setTab(id)} className="cy-tap" style={{ border:'none', background:'none', cursor:'pointer',
        display:'flex', flexDirection:'column', alignItems:'center', gap:3, padding:'4px 18px',
        color: on ? 'var(--cy-accent)' : 'var(--cy-ink-soft)' }}>
        <Icon name={icon} size={25}/>
        <span style={{ fontSize:11, fontWeight: on ? 700 : 500 }}>{label}</span>
      </button>
    );
  };
  return (
    <div style={{ position:'fixed', bottom:'calc(env(safe-area-inset-bottom) + 10px)', left:0, right:0, zIndex:35, display:'flex', justifyContent:'center', pointerEvents:'none' }}>
      <div style={{ position:'relative', display:'flex', alignItems:'center', gap:36, pointerEvents:'auto',
        background:'rgba(255,255,255,.78)', backdropFilter:'blur(16px) saturate(160%)', WebkitBackdropFilter:'blur(16px)',
        border:'1px solid rgba(255,255,255,.7)', borderRadius:99, padding:'8px 26px',
        boxShadow:'0 10px 30px rgba(60,90,120,.16)' }}>
        <TabBtn id="sky" icon="sky" label="天空"/>
        {/* FAB 占位 */}
        <div style={{ width:58 }}/>
        <TabBtn id="gallery" icon="book" label="图鉴"/>
        {/* 拍云 FAB */}
        <button onClick={onCapture} className="cy-tap" aria-label="拍云" style={{ position:'absolute', left:'50%', top:-18, transform:'translateX(-50%)',
          width:62, height:62, borderRadius:99, border:'4px solid var(--cy-bg)', cursor:'pointer',
          background:'linear-gradient(140deg, var(--cy-accent2), var(--cy-accent))', color:'#fff',
          display:'grid', placeItems:'center', boxShadow:'0 8px 22px rgba(90,159,212,.4)' }}>
          <Icon name="camera" size={28}/>
        </button>
      </div>
    </div>
  );
}

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