// ============================================================
// SocialPulse — Brands Page (API-connected)
// ============================================================

function BrandsPage({ onNavigate }) {
  const brands = useApi(() => spBrands.list(), []);
  const cats = useApi(() => spStats.categories(), []);
  const [selectedCat, setSelectedCat] = useState(null);
  // Deep-linkable selection: #/brands/15 opens brand 15 directly, and the
  // browser back button returns to the list.
  const [selectedBrand, setSelectedBrandState] = useState(() => {
    const sub = (typeof _hashSub === 'function') ? _hashSub() : null;
    return sub ? (parseInt(sub) || null) : null;
  });
  const setSelectedBrand = (id) => {
    setSelectedBrandState(id);
    spNavigate(id ? `brands/${id}` : 'brands');
  };
  useEffect(() => {
    const onHash = () => {
      const sub = (typeof _hashSub === 'function') ? _hashSub() : null;
      setSelectedBrandState(sub ? (parseInt(sub) || null) : null);
    };
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);
  const [showModal, setShowModal] = useState(false);
  const [editing, setEditing] = useState(null); // brand object or null
  const [showCatModal, setShowCatModal] = useState(false);
  const [showBatchModal, setShowBatchModal] = useState(false);
  const tasks = useScrapeTasks();
  const user = spGetUser() || {};
  const isAdmin = user.role === 'admin';

  // When a scrape finishes, refresh the list.
  const lastTaskCount = useRef(tasks.length);
  useEffect(() => {
    if (lastTaskCount.current > 0 && tasks.length === 0) brands.reload();
    lastTaskCount.current = tasks.length;
  }, [tasks.length]);

  if (selectedBrand) return <BrandDetail brandId={selectedBrand} onNavigate={onNavigate} onBack={() => { setSelectedBrand(null); brands.reload(); }}/>;

  const filtered = (brands.data || []).filter(b => !selectedCat || b.category_id === selectedCat);

  return (
    <div>
      <div style={{display:'flex',alignItems:'center',gap:12,marginBottom:20}}>
        <h2 style={{fontSize:22,fontWeight:800,letterSpacing:'-.02em'}}>品牌</h2>
        <span style={{fontFamily:'var(--font-mono)',fontSize:11,color:'var(--text3)',padding:'3px 8px',border:'1px solid var(--line)',borderRadius:'var(--r-xs)'}}>已追蹤 {(brands.data||[]).length}</span>
        <div style={{marginLeft:'auto',display:'flex',gap:8}}>
          {isAdmin && <button className="btn btn-ghost btn-sm" onClick={()=>setShowCatModal(true)}>分類管理</button>}
          <button className="btn btn-ghost btn-sm" onClick={()=>brands.reload()} title="重新讀取品牌列表" disabled={brands.loading}>
            {brands.loading ? '載入中…' : '↻ 重新整理'}
          </button>
          {(brands.data||[]).length > 0 && (
            <button className="btn btn-ghost btn-sm" onClick={()=>setShowBatchModal(true)} disabled={tasks.length > 0}>
              🔄 更新全部
            </button>
          )}
          <button className="btn btn-primary" onClick={()=>setShowModal(true)}>+ 新增品牌</button>
        </div>
      </div>

      {tasks.length > 0 && <RunningBanner tasks={tasks}/>}

      {/* Category filters */}
      <div style={{display:'flex',gap:6,marginBottom:20,flexWrap:'wrap'}}>
        <span style={{fontFamily:'var(--font-mono)',fontSize:10,color:'var(--text3)',textTransform:'uppercase',letterSpacing:'.1em',padding:'5px 0',marginRight:4}}>分類</span>
        <Chip active={!selectedCat} onClick={()=>setSelectedCat(null)}>全部</Chip>
        {(cats.data || []).map(c => (
          <Chip key={c.id} active={selectedCat===c.id} onClick={()=>setSelectedCat(c.id)}>
            {c.icon} {c.name}
          </Chip>
        ))}
      </div>

      {brands.loading ? <LoadingState/> :
       brands.error ? <ErrorState error={brands.error} onRetry={brands.reload}/> :
       filtered.length === 0 ? <EmptyState title="尚未追蹤品牌" desc="點「+ 新增品牌」開始"/> :
      <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(320px,1fr))',gap:14}}>
        {filtered.map(brand => {
          const totalEng = (brand.total_likes || 0) + (brand.total_comments || 0) + (brand.total_shares || 0);
          const postCount = brand.post_count || 0;
          const color = brand.color || 'var(--indigo)';
          const brandTasks = tasks.filter(t => t.brandId === brand.id);
          return (
            <div key={brand.id}
              style={{background:'var(--panel)',border:'1px solid var(--line)',borderRadius:'var(--r-xl)',overflow:'hidden',transition:'all .15s',position:'relative'}}>
              {brandTasks.length > 0 && (
                <div style={{position:'absolute',top:10,right:10,display:'flex',alignItems:'center',gap:5,fontFamily:'var(--font-mono)',fontSize:10,color:'var(--indigo2)',padding:'2px 7px',borderRadius:'var(--r-xs)',background:'var(--indigo-soft)',border:'1px solid rgba(99,102,241,.3)',zIndex:2}}>
                  <span style={{width:6,height:6,borderRadius:'50%',background:'var(--indigo2)',animation:'spin .8s linear infinite',boxShadow:'0 0 6px var(--indigo2)'}}/>
                  更新中
                </div>
              )}
              <div onClick={()=>setSelectedBrand(brand.id)}
                style={{padding:'18px 20px',display:'flex',alignItems:'center',gap:12,borderBottom:'1px solid var(--line)',cursor:'pointer'}}
                onMouseOver={e=>e.currentTarget.style.background='var(--panel2)'}
                onMouseOut={e=>e.currentTarget.style.background='transparent'}>
                {brand.logo_url ?
                  <img src={brand.logo_url} alt="" style={{width:40,height:40,borderRadius:'var(--r-md)',objectFit:'cover'}} onError={e=>{e.target.style.display='none'}}/>
                  : <BrandAvatar name={brand.name} color={color} size={40}/>
                }
                <div style={{flex:1,minWidth:0}}>
                  <div style={{fontWeight:700,fontSize:15,marginBottom:2,whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{brand.name}</div>
                  <div style={{display:'flex',gap:6,alignItems:'center'}}>
                    {brand.fb_page_id && <PlatformBadge platform="fb"/>}
                    {brand.ig_username && <PlatformBadge platform="ig"/>}
                    {brand.category_name && <span style={{fontFamily:'var(--font-mono)',fontSize:10,color:'var(--text3)',padding:'1px 6px',borderRadius:'var(--r-xs)',background:'var(--panel2)',border:'1px solid var(--line)'}}>{brand.category_name}</span>}
                  </div>
                </div>
              </div>
              <div style={{display:'grid',gridTemplateColumns:'repeat(2,1fr)',gap:0}} onClick={()=>setSelectedBrand(brand.id)}>
                <StatCell k="總互動" v={fmtK(totalEng)}/>
                <StatCell k="貼文" v={postCount} border={false}/>
              </div>
              {brand.last_fetched && (
                <div style={{padding:'8px 14px',fontSize:10,color:'var(--text3)',fontFamily:'var(--font-mono)',display:'flex',gap:10,flexWrap:'wrap',borderTop:'1px solid var(--line)'}} onClick={()=>setSelectedBrand(brand.id)}>
                  <span>最後更新 {fmtDate(brand.last_fetched)}</span>
                </div>
              )}
              <div style={{display:'flex',padding:'8px 12px',gap:6,borderTop:'1px solid var(--line)',background:'var(--bg2)'}}>
                <button className="btn btn-ghost btn-sm" style={{flex:1,fontSize:11}} onClick={(e)=>{e.stopPropagation();setEditing(brand);}}>✏️ 編輯</button>
                <button className="btn btn-ghost btn-sm" style={{flex:1,fontSize:11,color:'var(--red)'}} onClick={async (e)=>{
                  e.stopPropagation();
                  if (!confirm(`確定刪除「${brand.name}」？貼文資料保留，可再次新增同名品牌`)) return;
                  try { await spBrands.delete(brand.id); spToast(`已刪除 ${brand.name}`); brands.reload(); }
                  catch (err) { spToast(err.message || '刪除失敗', 'err'); }
                }}>🗑 刪除</button>
              </div>
            </div>
          );
        })}
      </div>}

      {showModal && <BrandFormModal categories={cats.data||[]} onClose={()=>setShowModal(false)} onSaved={()=>{setShowModal(false);brands.reload();}}/>}
      {editing && <BrandFormModal brand={editing} categories={cats.data||[]} onClose={()=>setEditing(null)} onSaved={()=>{setEditing(null);brands.reload();}}/>}
      {showCatModal && <CategoriesModal categories={cats.data||[]} onClose={()=>setShowCatModal(false)} onSaved={()=>{cats.reload();brands.reload();}}/>}
      {showBatchModal && <BatchScrapeModal brandCount={(brands.data||[]).length} onClose={()=>setShowBatchModal(false)} onStarted={()=>{setShowBatchModal(false);}}/>}
    </div>
  );
}

function BatchScrapeModal({ brandCount, onClose, onStarted }) {
  const [days, setDays] = useState(7);
  const [platform, setPlatform] = useState('all');
  const [estimate, setEstimate] = useState(null);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState('');
  const user = spGetUser() || {};
  const histLimit = spHistLimit(user);

  const doEstimate = async () => {
    setErr(''); setBusy(true);
    try {
      const plan = await spScrape.batchPlan({ newerThan: `${days} days`, platform });
      setEstimate(plan);
    } catch (e) { setErr(e.message); }
    finally { setBusy(false); }
  };

  const doStart = async () => {
    setBusy(true); setErr('');
    try {
      const r = await spStartBatchScrape({ days, platform });
      spToast(`已啟動 ${r.ok} 個爬取任務${r.errors.length ? `（${r.errors.length} 個失敗）` : ''}`, r.errors.length ? 'warn' : 'ok');
      if (r.errors.length) console.warn('batch scrape errors', r.errors);
      onStarted();
    } catch (e) { setErr(e.message); setBusy(false); }
  };

  useEffect(() => { setEstimate(null); }, [days, platform]);

  return (
    <div style={{position:'fixed',inset:0,background:'rgba(0,0,0,.6)',zIndex:200,display:'flex',alignItems:'center',justifyContent:'center',padding:16}} onClick={onClose}>
      <div style={{background:'var(--panel)',border:'1px solid var(--line)',borderRadius:'var(--r-2xl)',padding:28,width:'100%',maxWidth:480}} onClick={e=>e.stopPropagation()}>
        <h3 style={{fontSize:18,fontWeight:700,marginBottom:8}}>更新全部品牌</h3>
        <div style={{fontSize:13,color:'var(--text2)',marginBottom:20}}>對所有 {brandCount} 個品牌啟動爬取</div>

        <div style={{marginBottom:14}}>
          <label style={{display:'block',fontSize:12,color:'var(--text2)',marginBottom:6,fontWeight:500}}>時間範圍</label>
          <select value={days} onChange={e=>setDays(Number(e.target.value))}
            style={{width:'100%',padding:'10px 12px',background:'var(--bg)',border:'1px solid var(--line)',borderRadius:'var(--r-md)',color:'var(--text)',fontSize:13,outline:'none'}}>
            {SCRAPE_DAY_OPTIONS.map(o => {
              const locked = o.value > histLimit;
              return <option key={o.value} value={o.value} disabled={locked}>
                {locked ? '🔒 ' : ''}{o.label}{locked ? '（升級解鎖）' : ''}
              </option>;
            })}
          </select>
        </div>

        <div style={{marginBottom:14}}>
          <label style={{display:'block',fontSize:12,color:'var(--text2)',marginBottom:6,fontWeight:500}}>平台</label>
          <div style={{display:'flex',gap:6}}>
            {[['all','FB + IG'],['fb','僅 FB'],['ig','僅 IG']].map(([v,l]) =>
              <Chip key={v} active={platform===v} onClick={()=>setPlatform(v)}>{l}</Chip>)}
          </div>
        </div>

        {estimate && (
          <div style={{padding:'12px 14px',background:'var(--indigo-soft)',border:'1px solid rgba(99,102,241,.3)',borderRadius:'var(--r-md)',marginBottom:14,fontSize:13,lineHeight:1.6}}>
            <div>📊 {estimate.tasks?.length || 0} 個爬取任務 · 預估消耗 <strong style={{color:'var(--indigo2)'}}>{estimate.estimateMin}~{estimate.estimateMax} 點</strong></div>
          </div>
        )}

        {err && <div style={{fontSize:12,color:'var(--red)',marginBottom:12}}>{err}</div>}

        <div style={{display:'flex',justifyContent:'flex-end',gap:8,marginTop:20}}>
          <button className="btn btn-ghost" onClick={onClose} disabled={busy}>取消</button>
          {!estimate ? (
            <button className="btn btn-ghost" onClick={doEstimate} disabled={busy}>{busy ? '試算中…' : '試算點數'}</button>
          ) : (
            <button className="btn btn-primary" onClick={doStart} disabled={busy}>{busy ? '啟動中…' : '啟動爬取 →'}</button>
          )}
        </div>
      </div>
    </div>
  );
}

function RunningBanner({ tasks }) {
  const avgPct = Math.round(tasks.reduce((s,t)=>s+(t.pct||0),0) / tasks.length);
  const hasFailed = tasks.some(t => t.status === 'failed');
  return (
    <div style={{
      background:'var(--panel)',border:'1px solid var(--line)',borderRadius:'var(--r-lg)',
      padding:'12px 18px',marginBottom:16,display:'flex',alignItems:'center',gap:14,
    }}>
      <div style={{flex:1,minWidth:0}}>
        <div style={{fontSize:13,fontWeight:600,marginBottom:6}}>
          {hasFailed ? '⚠ 部分更新失敗' : `正在更新 ${tasks.length} 個任務`}
        </div>
        <div style={{height:4,background:'var(--line)',borderRadius:2,overflow:'hidden'}}>
          <div style={{height:'100%',width:`${avgPct}%`,background:'var(--indigo)',borderRadius:2,transition:'width .3s'}}/>
        </div>
        <div style={{fontSize:11,color:'var(--text3)',fontFamily:'var(--font-mono)',marginTop:6}}>
          {tasks.map(t => t.brandName).join(' · ')}
        </div>
      </div>
      <div style={{fontSize:11,color:'var(--text3)',fontFamily:'var(--font-mono)'}}>
        {tasks.length ? '可安心切換分頁' : ''}
      </div>
    </div>
  );
}

function Chip({ active, onClick, children }) {
  return <span onClick={onClick} style={{
    padding:'4px 10px',borderRadius:'var(--r-sm)',
    border: active ? '1px solid var(--lime)' : '1px solid var(--line)',
    background: active ? 'var(--lime)' : 'transparent',
    color: active ? 'var(--bg)' : 'var(--text2)',
    fontFamily:'var(--font-mono)',fontSize:11,fontWeight: active?700:400,
    cursor:'pointer',
  }}>{children}</span>;
}

function StatCell({ k, v, border=true }) {
  return (
    <div style={{padding:'14px 16px',textAlign:'center',borderRight:border?'1px solid var(--line)':'none'}}>
      <div style={{fontFamily:'var(--font-mono)',fontSize:9,color:'var(--text3)',textTransform:'uppercase',letterSpacing:'.1em',marginBottom:4}}>{k}</div>
      <div style={{fontSize:17,fontWeight:700}}>{v}</div>
    </div>
  );
}

function DetailStat({ k, v, color='var(--text)', border=true }) {
  return (
    <div style={{padding:'16px 12px',textAlign:'center',borderRight:border?'1px solid var(--line)':'none',background:'var(--bg2)'}}>
      <div style={{fontFamily:'var(--font-mono)',fontSize:9,color:'var(--text3)',textTransform:'uppercase',letterSpacing:'.1em',marginBottom:6}}>{k}</div>
      <div style={{fontSize:20,fontWeight:800,color}}>{v}</div>
    </div>
  );
}

function BrandFormModal({ brand, categories, onClose, onSaved }) {
  const isEdit = !!brand;
  const [form, setForm] = useState({
    name: brand?.name || '',
    fb_page_url: brand?.fb_page_url || '',
    ig_username: brand?.ig_username || '',
    category_id: brand?.category_id || '',
    logo_url: brand?.logo_url || '',
    notes: brand?.notes || '',
  });
  const [saving, setSaving] = useState(false);
  const [err, setErr] = useState('');

  const fetchLogo = async () => {
    if (!form.fb_page_url) { spToast('先填 FB 粉專網址', 'warn'); return; }
    try {
      const r = await spBrands.fetchFbLogo(form.fb_page_url);
      if (r.logo_url) { setForm(f => ({ ...f, logo_url: r.logo_url })); spToast('已抓取頭像'); }
      else spToast('找不到頭像，請手動填入', 'warn');
    } catch (e) { spToast(e.message || '抓取失敗', 'err'); }
  };

  const save = async () => {
    if (!form.name || !form.category_id) { setErr('品牌名稱與分類必填'); return; }
    setSaving(true); setErr('');
    try {
      const payload = { ...form, category_id: Number(form.category_id) };
      if (isEdit) {
        await spBrands.update(brand.id, payload);
        spToast(`已更新 ${form.name}`);
      } else {
        await spBrands.create(payload);
        spToast(`已新增 ${form.name}`);
      }
      onSaved();
    } catch (e) { setErr(e.message); }
    finally { setSaving(false); }
  };

  return (
    <div style={{position:'fixed',inset:0,background:'rgba(0,0,0,.6)',zIndex:200,display:'flex',alignItems:'center',justifyContent:'center',padding:16}} onClick={onClose}>
      <div style={{background:'var(--panel)',border:'1px solid var(--line)',borderRadius:'var(--r-2xl)',padding:28,width:'100%',maxWidth:480,maxHeight:'90vh',overflowY:'auto'}} onClick={e=>e.stopPropagation()}>
        <h3 style={{fontSize:18,fontWeight:700,marginBottom:20}}>{isEdit ? '編輯品牌' : '新增品牌'}</h3>
        <Field label="品牌名稱" value={form.name} onChange={v=>setForm({...form,name:v})} required/>
        <Field label="FB 粉專網址" value={form.fb_page_url} onChange={v=>setForm({...form,fb_page_url:v})} placeholder="https://www.facebook.com/..."/>
        <Field label="IG 帳號（不含 @）" value={form.ig_username} onChange={v=>setForm({...form,ig_username:v})} placeholder="brand_handle"/>
        <div style={{marginBottom:14}}>
          <label style={{display:'block',fontSize:12,color:'var(--text2)',marginBottom:4,fontWeight:500}}>分類 *</label>
          <select value={form.category_id} onChange={e=>setForm({...form,category_id:e.target.value})}
            style={{width:'100%',padding:'10px 12px',background:'var(--bg)',border:'1px solid var(--line)',borderRadius:'var(--r-md)',color:'var(--text)',fontSize:14,outline:'none'}}>
            <option value="">選擇分類</option>
            {categories.map(c=><option key={c.id} value={c.id}>{c.icon} {c.name}</option>)}
          </select>
        </div>
        <div style={{marginBottom:14}}>
          <label style={{display:'block',fontSize:12,color:'var(--text2)',marginBottom:4,fontWeight:500}}>Logo 網址</label>
          <div style={{display:'flex',gap:6}}>
            <input value={form.logo_url} onChange={e=>setForm({...form,logo_url:e.target.value})}
              placeholder="https://..."
              style={{flex:1,padding:'10px 12px',background:'var(--bg)',border:'1px solid var(--line)',borderRadius:'var(--r-md)',color:'var(--text)',fontSize:13,outline:'none'}}/>
            <button className="btn btn-ghost btn-sm" onClick={fetchLogo} type="button">自動抓取</button>
          </div>
        </div>
        <div style={{marginBottom:14}}>
          <label style={{display:'block',fontSize:12,color:'var(--text2)',marginBottom:4,fontWeight:500}}>備註</label>
          <textarea value={form.notes} onChange={e=>setForm({...form,notes:e.target.value})}
            rows={2}
            style={{width:'100%',padding:'10px 12px',background:'var(--bg)',border:'1px solid var(--line)',borderRadius:'var(--r-md)',color:'var(--text)',fontSize:13,outline:'none',fontFamily:'var(--font-ui)',resize:'vertical'}}/>
        </div>
        {err && <div style={{fontSize:12,color:'var(--red)',marginBottom:12}}>{err}</div>}
        <div style={{display:'flex',justifyContent:'flex-end',gap:8,marginTop:20}}>
          <button className="btn btn-ghost" onClick={onClose}>取消</button>
          <button className="btn btn-primary" onClick={save} disabled={saving}>{saving?'儲存中…':'儲存'}</button>
        </div>
      </div>
    </div>
  );
}

function CategoriesModal({ categories, onClose, onSaved }) {
  const [list, setList] = useState(categories);
  const [adding, setAdding] = useState({ name: '', icon: '🏷️' });
  const [busy, setBusy] = useState(false);

  const add = async () => {
    if (!adding.name.trim()) { spToast('分類名稱必填', 'warn'); return; }
    setBusy(true);
    try {
      await spApi('/api/categories', { method: 'POST', body: { name: adding.name.trim(), icon: adding.icon || '🏷️' } });
      const r = await spStats.categories();
      setList(r); setAdding({ name:'', icon:'🏷️' });
      spToast('已新增分類');
      onSaved && onSaved();
    } catch (e) { spToast(e.message, 'err'); }
    finally { setBusy(false); }
  };

  const del = async (id, name) => {
    if (!confirm(`刪除分類「${name}」？該分類下不能有品牌`)) return;
    try {
      await spApi(`/api/categories/${id}`, { method: 'DELETE' });
      const r = await spStats.categories();
      setList(r);
      spToast(`已刪除 ${name}`);
      onSaved && onSaved();
    } catch (e) { spToast(e.message, 'err'); }
  };

  return (
    <div style={{position:'fixed',inset:0,background:'rgba(0,0,0,.6)',zIndex:200,display:'flex',alignItems:'center',justifyContent:'center',padding:16}} onClick={onClose}>
      <div style={{background:'var(--panel)',border:'1px solid var(--line)',borderRadius:'var(--r-2xl)',padding:28,width:'100%',maxWidth:480,maxHeight:'90vh',overflowY:'auto'}} onClick={e=>e.stopPropagation()}>
        <h3 style={{fontSize:18,fontWeight:700,marginBottom:16}}>分類管理</h3>
        <div style={{display:'flex',flexDirection:'column',gap:6,marginBottom:16}}>
          {list.map(c => (
            <div key={c.id} style={{display:'flex',alignItems:'center',gap:10,padding:'8px 12px',background:'var(--bg2)',borderRadius:'var(--r-md)',border:'1px solid var(--line)'}}>
              <span style={{fontSize:18}}>{c.icon}</span>
              <span style={{flex:1,fontSize:13,fontWeight:500}}>{c.name}</span>
              <span style={{fontFamily:'var(--font-mono)',fontSize:10,color:'var(--text3)'}}>{c.brand_count || 0} 個品牌</span>
              <button className="btn btn-ghost btn-sm" style={{color:'var(--red)',fontSize:11}} onClick={() => del(c.id, c.name)}>刪除</button>
            </div>
          ))}
        </div>
        <div style={{borderTop:'1px solid var(--line)',paddingTop:16}}>
          <div style={{fontSize:12,color:'var(--text2)',marginBottom:8,fontWeight:500}}>新增分類</div>
          <div style={{display:'flex',gap:6}}>
            <input value={adding.icon} onChange={e=>setAdding({...adding, icon:e.target.value})}
              maxLength={4} placeholder="📱"
              style={{width:60,padding:'10px',background:'var(--bg)',border:'1px solid var(--line)',borderRadius:'var(--r-md)',color:'var(--text)',fontSize:18,outline:'none',textAlign:'center'}}/>
            <input value={adding.name} onChange={e=>setAdding({...adding, name:e.target.value})}
              placeholder="分類名稱"
              style={{flex:1,padding:'10px 12px',background:'var(--bg)',border:'1px solid var(--line)',borderRadius:'var(--r-md)',color:'var(--text)',fontSize:13,outline:'none'}}/>
            <button className="btn btn-primary btn-sm" onClick={add} disabled={busy}>新增</button>
          </div>
        </div>
        <div style={{display:'flex',justifyContent:'flex-end',marginTop:20}}>
          <button className="btn btn-ghost" onClick={onClose}>關閉</button>
        </div>
      </div>
    </div>
  );
}

// Ranges beyond the plan's history_days (from /me quota) display 🔒.
const SCRAPE_DAY_OPTIONS = [
  { value: 1,   label: '近 1 天' },
  { value: 3,   label: '近 3 天' },
  { value: 7,   label: '近 7 天' },
  { value: 14,  label: '近 14 天' },
  { value: 30,  label: '近 30 天' },
  { value: 90,  label: '近 90 天' },
  { value: 180, label: '近 180 天' },
  { value: 365, label: '近 365 天' },
];
// Plan-driven scrape-history cap; admin unrestricted.
function spHistLimit(user) {
  if (user?.role === 'admin') return 365;
  return Number(user?.history_days) || 14;
}

const POST_PAGE_SIZE = 20;

function BrandDetail({ brandId, onBack, onNavigate }) {
  const brand = useApi(() => spBrands.get(brandId), [brandId]);
  const [days, setDays] = useState(14);
  const [starting, setStarting] = useState(null); // 'fb' | 'ig' | 'both' | null
  const [msg, setMsg] = useState(null);
  const [estimate, setEstimate] = useState(null);
  const [postFilter, setPostFilter] = useState({
    platform: '', from: '', to: '',
    sort: 'engagement_desc', page: 1,
  });
  const tasks = useScrapeTasks(brandId);
  const user = spGetUser() || {};
  const histLimit = spHistLimit(user);

  const posts = useApi(() => spPosts.list({
    brand_id: brandId,
    limit: POST_PAGE_SIZE,
    offset: (postFilter.page - 1) * POST_PAGE_SIZE,
    sort: postFilter.sort,
    platform: postFilter.platform || undefined,
    // Backend /api/posts reads `from`/`to` — the old date_from/date_to names
    // were silently ignored, making this page's date filter a no-op.
    from: postFilter.from || undefined,
    to: postFilter.to || undefined,
  }), [brandId, postFilter.page, postFilter.sort, postFilter.platform, postFilter.from, postFilter.to]);

  // When scrape finishes, refresh data.
  const prev = useRef(tasks.length);
  useEffect(() => {
    if (prev.current > 0 && tasks.length === 0) {
      brand.reload(); posts.reload();
      setMsg({ type: 'ok', text: '數據已更新' });
      setTimeout(() => setMsg(null), 3000);
    }
    prev.current = tasks.length;
  }, [tasks.length]);

  const runEstimate = async () => {
    try {
      const b = brand.data;
      const parts = [];
      if (b.fb_page_id || b.fb_page_url) {
        parts.push({ p:'fb', ...(await spScrape.estimate({ type: 'fb', days })) });
      }
      if (b.ig_username) {
        // Must match the resultsLimit the actual scrape sends (spScrape.ig
        // defaults to 20 server-side) — quoting 50 here over-stated the cost.
        parts.push({ p:'ig', ...(await spScrape.estimate({ type: 'ig', count: 20 })) });
      }
      setEstimate(parts);
    } catch (e) { spToast(e.message || '試算失敗', 'err'); }
  };

  const startUpdate = async (platforms) => {
    if (days > histLimit) { setMsg({ type: 'err', text: `目前方案最多可爬取近 ${histLimit} 天` }); return; }
    const label = platforms.length === 1 ? platforms[0].toUpperCase() : 'FB+IG';
    setStarting(label === 'FB+IG' ? 'both' : platforms[0]); setMsg(null);
    try {
      await spStartBrandScrape(brand.data, days, platforms);
      spToast(`已開始更新 ${label}`);
      setEstimate(null);
    } catch (e) {
      setMsg({ type: 'err', text: e.message || '啟動失敗' });
      spToast(e.message || '啟動失敗', 'err');
    } finally {
      setStarting(null);
    }
  };

  useEffect(() => { setEstimate(null); }, [days]);

  if (brand.loading) return <LoadingState/>;
  if (brand.error) return <ErrorState error={brand.error} onRetry={brand.reload}/>;
  const b = brand.data || {};
  const running = tasks.length > 0;
  const totalLikes = b.total_likes || 0;
  const totalComments = b.total_comments || 0;
  const totalShares = b.total_shares || 0;
  const totalEng = totalLikes + totalComments + totalShares;
  const fmtTime = (t) => {
    if (!t) return null;
    const d = new Date(t);
    if (isNaN(d.getTime())) return null;
    return d.toLocaleString('zh-TW', { month:'2-digit', day:'2-digit', hour:'2-digit', minute:'2-digit' });
  };
  const lastFetched = fmtTime(b.last_fetched);

  return (
    <div>
      <button onClick={onBack} className="btn btn-ghost btn-sm" style={{marginBottom:16}}>← 回品牌列表</button>
      <div style={{background:'var(--panel)',border:'1px solid var(--line)',borderRadius:'var(--r-xl)',padding:'24px 28px',marginBottom:16}}>
        <div style={{display:'flex',alignItems:'center',gap:16,flexWrap:'wrap'}}>
          {b.logo_url ? <img src={b.logo_url} style={{width:56,height:56,borderRadius:'var(--r-md)',objectFit:'cover'}} onError={e=>{e.target.style.display='none'}}/> : <BrandAvatar name={b.name} color="var(--indigo)" size={56}/>}
          <div style={{flex:1,minWidth:200}}>
            <h2 style={{fontSize:24,fontWeight:800,letterSpacing:'-.02em',marginBottom:4}}>{b.name}</h2>
            <div style={{display:'flex',gap:8,alignItems:'center',flexWrap:'wrap'}}>
              {b.fb_page_id && <PlatformBadge platform="fb"/>}
              {b.ig_username && <PlatformBadge platform="ig"/>}
              {b.category_name && <span style={{fontFamily:'var(--font-mono)',fontSize:11,color:'var(--text3)'}}>{b.category_name}</span>}
              {b.followers > 0 && <span style={{fontSize:12,color:'var(--text2)'}}>👥 {fmtK(b.followers)} 追蹤者</span>}
            </div>
          </div>
          <div style={{display:'flex',alignItems:'center',gap:8,flexWrap:'wrap'}}>
            <select value={days} onChange={e=>setDays(Number(e.target.value))} disabled={running||!!starting}
              style={{padding:'8px 10px',background:'var(--bg)',border:'1px solid var(--line)',borderRadius:'var(--r-md)',color:'var(--text)',fontSize:13,outline:'none'}}>
              {SCRAPE_DAY_OPTIONS.map(o => {
                const locked = o.value > histLimit;
                return <option key={o.value} value={o.value} disabled={locked}>
                  {locked ? '🔒 ' : ''}{o.label}{locked ? '（升級解鎖）' : ''}
                </option>;
              })}
            </select>
            <button className="btn btn-ghost btn-sm" onClick={runEstimate} disabled={running||!!starting}>
              試算點數
            </button>
            {(b.fb_page_id || b.fb_page_url) && (
              <button className="btn btn-primary btn-sm" onClick={()=>startUpdate(['fb'])} disabled={running||!!starting}
                style={{background:'var(--fb, #1877f2)', color:'#fff', borderColor:'transparent'}}>
                {starting==='fb' ? '啟動中…' : '更新 FB'}
              </button>
            )}
            {b.ig_username && (
              <button className="btn btn-primary btn-sm" onClick={()=>startUpdate(['ig'])} disabled={running||!!starting}
                style={{background:'linear-gradient(135deg,#f09433,#dc2743,#bc1888)', color:'#fff', borderColor:'transparent'}}>
                {starting==='ig' ? '啟動中…' : '更新 IG'}
              </button>
            )}
            {(b.fb_page_id || b.fb_page_url) && b.ig_username && (
              <button className="btn btn-primary btn-sm" onClick={()=>startUpdate(['fb','ig'])} disabled={running||!!starting}>
                {starting==='both' ? '啟動中…' : '兩者一起'}
              </button>
            )}
          </div>
        </div>

        {estimate && (
          <div style={{marginTop:14,padding:'12px 14px',background:'var(--indigo-soft)',border:'1px solid rgba(99,102,241,.3)',borderRadius:'var(--r-md)',fontSize:13,lineHeight:1.6}}>
            <div style={{fontWeight:600,marginBottom:4}}>📊 試算</div>
            {estimate.map((e, i) => (
              <div key={i} style={{fontSize:12,color:'var(--text2)'}}>
                {e.p === 'fb' ? 'FB' : 'IG'}：約 {e.postCount || 0} 篇 · 預估 {e.min}~{e.max} 點
              </div>
            ))}
            <div style={{fontSize:12,marginTop:4,fontWeight:600,color:'var(--indigo2)'}}>
              合計 {estimate.reduce((s,e)=>s+e.min,0)}~{estimate.reduce((s,e)=>s+e.max,0)} 點
            </div>
          </div>
        )}

        {/* Stats row */}
        <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fit,minmax(110px,1fr))',gap:0,marginTop:18,border:'1px solid var(--line)',borderRadius:'var(--r-md)',overflow:'hidden'}}>
          <DetailStat k="貼文" v={b.post_count || 0} color="var(--text)"/>
          <DetailStat k="總讚" v={fmtK(totalLikes)} color="var(--red)"/>
          <DetailStat k="留言" v={fmtK(totalComments)} color="var(--blue)"/>
          <DetailStat k="分享" v={fmtK(totalShares)} color="var(--green)"/>
          <DetailStat k="🔥 總互動" v={fmtK(totalEng)} color="var(--orange)" border={false}/>
        </div>

        {lastFetched && (
          <div style={{marginTop:12,fontSize:11,color:'var(--text3)',fontFamily:'var(--font-mono)',display:'flex',gap:14,flexWrap:'wrap'}}>
            <span>最後更新 {lastFetched}</span>
          </div>
        )}

        {running && (
          <div style={{marginTop:14}}>
            <div style={{height:4,background:'var(--line)',borderRadius:2,overflow:'hidden'}}>
              <div style={{height:'100%',width:`${Math.round(tasks.reduce((s,t)=>s+(t.pct||0),0)/tasks.length)}%`,background:'var(--indigo)',borderRadius:2,transition:'width .3s'}}/>
            </div>
            <div style={{fontSize:11,color:'var(--text3)',marginTop:6,fontFamily:'var(--font-mono)'}}>等待公開資料回傳（平均 1–3 分鐘）· 可切換分頁</div>
          </div>
        )}
        {msg && (
          <div style={{
            marginTop:12,fontSize:12,padding:'8px 12px',borderRadius:'var(--r-md)',
            color: msg.type==='ok' ? 'var(--green)' : 'var(--red)',
            background: msg.type==='ok' ? 'var(--green-soft)' : 'var(--red-soft)',
            border: `1px solid ${msg.type==='ok' ? 'rgba(45,212,138,.28)' : 'rgba(255,85,119,.3)'}`,
          }}>
            {msg.text}
          </div>
        )}
      </div>

      <div style={{background:'var(--panel)',border:'1px solid var(--line)',borderRadius:'var(--r-xl)',overflow:'hidden'}}>
        <div style={{padding:'14px 22px',borderBottom:'1px solid var(--line)',display:'flex',alignItems:'center',gap:12,flexWrap:'wrap'}}>
          <span style={{fontSize:15,fontWeight:700}}>貼文</span>
          <div style={{display:'flex',gap:6,flexWrap:'wrap',alignItems:'center'}}>
            {[['','全部'],['fb','FB'],['ig','IG']].map(([v,l]) => (
              <Chip key={v} active={postFilter.platform===v} onClick={()=>setPostFilter(f=>({...f,platform:v,page:1}))}>{l}</Chip>
            ))}
          </div>
          <div style={{display:'flex',gap:4,alignItems:'center'}}>
            <input type="date" value={postFilter.from} onChange={e=>setPostFilter(f=>({...f,from:e.target.value,page:1}))}
              style={{padding:'5px 8px',background:'var(--bg)',border:'1px solid var(--line)',borderRadius:'var(--r-sm)',color:'var(--text)',fontSize:12,outline:'none'}}/>
            <span style={{fontSize:11,color:'var(--text3)'}}>–</span>
            <input type="date" value={postFilter.to} onChange={e=>setPostFilter(f=>({...f,to:e.target.value,page:1}))}
              style={{padding:'5px 8px',background:'var(--bg)',border:'1px solid var(--line)',borderRadius:'var(--r-sm)',color:'var(--text)',fontSize:12,outline:'none'}}/>
          </div>
          <select value={postFilter.sort} onChange={e=>setPostFilter(f=>({...f,sort:e.target.value,page:1}))}
            style={{padding:'5px 8px',background:'var(--bg)',border:'1px solid var(--line)',borderRadius:'var(--r-sm)',color:'var(--text)',fontSize:12,outline:'none'}}>
            <option value="engagement_desc">互動高→低</option>
            <option value="date_desc">最新→最舊</option>
            <option value="likes_desc">讚數高→低</option>
          </select>
          {(postFilter.platform || postFilter.from || postFilter.to || postFilter.sort !== 'engagement_desc') && (
            <button className="btn btn-ghost btn-sm" style={{fontSize:11}} onClick={()=>setPostFilter({platform:'',from:'',to:'',sort:'engagement_desc',page:1})}>清除</button>
          )}
        </div>
        {posts.loading ? <LoadingState/> :
         posts.error ? <ErrorState error={posts.error}/> :
         (posts.data||[]).length === 0 ? <EmptyState title="尚無貼文" desc={postFilter.platform||postFilter.from||postFilter.to?'沒有符合條件的貼文':'點「更新數據」抓取最新貼文'}/> :
         (posts.data||[]).map((p,i,arr) => {
          const likes = p.likes_count||0, comments = p.comments_count||0, shares = p.shares_count||0;
          const eng = likes+comments+shares;
          const link = p.permalink_url && /^https?:\/\//.test(p.permalink_url) ? p.permalink_url : null;
          const Body = (
            <div style={{minWidth:0}}>
              <div style={{display:'flex',gap:6,alignItems:'center',marginBottom:2}}>
                <PlatformBadge platform={p.platform||'fb'}/>
                <span style={{fontFamily:'var(--font-mono)',fontSize:10,color:'var(--text3)'}}>{p.created_time?.slice(0,16).replace('T',' ')}</span>
              </div>
              <div style={{fontSize:12,color:'var(--text2)',overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{p.message}</div>
            </div>
          );
          return (
            <div key={p.id} style={{padding:'12px 22px',borderBottom:i===arr.length-1?'none':'1px solid var(--line)',display:'grid',gridTemplateColumns:'1fr auto',gap:16,alignItems:'center'}}>
              {link ? <a href={link} target="_blank" rel="noopener noreferrer" style={{textDecoration:'none',color:'inherit',minWidth:0}}>{Body}</a> : Body}
              <div style={{display:'flex',gap:14,fontFamily:'var(--font-mono)',fontSize:12,whiteSpace:'nowrap'}}>
                <span style={{color:'var(--red)'}}>❤ {fmtK(likes)}</span>
                <span style={{color:'var(--blue)'}}>💬 {fmtK(comments)}</span>
                <span style={{color:'var(--green)'}}>🔄 {fmtK(shares)}</span>
                {(p.video_url || (p.video_view_count||0) > 0) && (
                  <span style={{color:'var(--purple)'}}>👀 {fmtK(p.video_view_count||0)}</span>
                )}
                <span style={{color:'var(--orange)',fontWeight:700}}>🔥 {fmtK(eng)}</span>
              </div>
            </div>
          );
        })}
        {(posts.data||[]).length > 0 && (
          <div style={{padding:'12px 22px',borderTop:'1px solid var(--line)',display:'flex',alignItems:'center',gap:10,background:'var(--bg2)'}}>
            <button className="btn btn-ghost btn-sm" disabled={postFilter.page === 1}
              onClick={()=>setPostFilter(f=>({...f,page:Math.max(1,f.page-1)}))}>← 上一頁</button>
            <span style={{fontSize:12,color:'var(--text3)',fontFamily:'var(--font-mono)'}}>
              第 {postFilter.page} 頁 · 本頁 {(posts.data||[]).length} 篇
            </span>
            <button className="btn btn-ghost btn-sm" style={{marginLeft:'auto'}}
              disabled={(posts.data||[]).length < POST_PAGE_SIZE}
              onClick={()=>setPostFilter(f=>({...f,page:f.page+1}))}>下一頁 →</button>
          </div>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { BrandsPage, Chip });
