// teacher.jsx — Teacher app (desktop, in browser window)

const { useState: useStateT, useEffect: useEffectT, useMemo: useMemoT } = React;

// ─── Sidebar ──────────────────────────────────────────────
function TeacherSidebar({ page, setPage, t, lang, pendingCount, open, onClose, teacher }) {
  const items = [
    { id: 'dashboard', label: t.dashboard, icon: 'layout' },
    { id: 'issues',    label: t.issues,    icon: 'list', badge: pendingCount },
    { id: 'timeline',  label: t.timeline,  icon: 'clock' },
    { id: 'settings',  label: lang === 'th' ? 'โปรไฟล์' : 'Profile', icon: 'user' },
  ];
  return (
    <aside className={`bp-teacher-sidebar ${open ? 'open' : ''}`} style={{
      width: 220, padding: '20px 14px', background:'var(--bp-surface)',
      borderRight:'1px solid var(--bp-line)',
      display:'flex', flexDirection:'column', gap: 4,
      flexShrink: 0,
    }}>
      <div style={{ display:'flex', alignItems:'center', gap: 10, padding:'4px 8px 22px' }}>
        <Logomark size={34}/>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontFamily:'Space Grotesk', fontWeight: 600, fontSize: 16, letterSpacing:'-0.01em' }}>Bodin plus</div>
          <div style={{ fontSize: 10, color:'var(--bp-ink-3)' }}>{lang === 'th' ? 'แดชบอร์ดครู' : 'Teacher console'}</div>
        </div>
        {/* Close button (mobile drawer) */}
        <button className="bp-mobile-menu-btn" onClick={onClose} style={{
          appearance:'none', border:0, background:'transparent', cursor:'pointer',
          width: 30, height: 30, borderRadius: 8, color:'var(--bp-ink-3)',
          alignItems:'center', justifyContent:'center',
        }}>
          <Icon name="close" size={16}/>
        </button>
      </div>

      {items.map(it => {
        const active = page === it.id;
        return (
          <button key={it.id} onClick={() => { setPage(it.id); onClose?.(); }} style={{
            appearance:'none', border:0, cursor:'pointer',
            display:'flex', alignItems:'center', gap: 10,
            padding:'10px 12px', borderRadius: 12,
            background: active ? 'var(--bp-grad)' : 'transparent',
            color: active ? '#fff' : 'var(--bp-ink-2)',
            fontSize: 13, fontWeight: active ? 600 : 500, textAlign:'left',
            boxShadow: active ? '0 6px 14px rgba(80,50,180,0.22)' : 'none',
            transition: 'background .15s ease, color .15s ease',
          }}>
            <Icon name={it.icon} size={17} strokeWidth={active ? 2 : 1.6}/>
            <span style={{ flex: 1 }}>{it.label}</span>
            {it.badge > 0 && (
              <span style={{
                background: active ? 'rgba(255,255,255,0.25)' : 'oklch(0.94 0.08 25)',
                color: active ? '#fff' : 'oklch(0.50 0.22 25)',
                borderRadius: 999, padding:'1px 7px', fontSize: 10, fontWeight: 600,
              }}>{it.badge}</span>
            )}
          </button>
        );
      })}

      <div style={{ flex: 1 }}/>

      <div style={{
        padding: 12, borderRadius: 14, background:'var(--bp-grad-soft)',
        border:'1px solid var(--bp-line)',
      }}>
        <div style={{ display:'flex', alignItems:'center', gap: 10 }}>
          <div style={{
            width: 36, height: 36, borderRadius:'50%',
            background: teacher?.photo ? `url(${teacher.photo}) center/cover` : 'var(--bp-grad)',
            color:'#fff',
            display:'flex', alignItems:'center', justifyContent:'center',
            fontFamily:'Space Grotesk', fontWeight: 600, overflow:'hidden',
          }}>{!teacher?.photo && ((teacher?.name || 'ครู').split('')[0])}</div>
          <div style={{ minWidth: 0, flex: 1 }}>
            <div style={{ fontSize: 12.5, fontWeight: 600, color:'var(--bp-ink)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{teacher?.name || 'ครูประภาส ส.'}</div>
            <div style={{ fontSize: 10.5, color:'var(--bp-ink-3)' }}>{lang === 'th' ? 'คุณครู' : 'Teacher'}</div>
          </div>
        </div>
      </div>
    </aside>
  );
}

// ─── Top bar ──────────────────────────────────────────────
function TeacherTopBar({ title, subtitle, lang, setLang, onSwitchRole, t, onMenuClick, reports, goToIssue }) {
  const [showNotifs, setShowNotifs] = useStateT(false);
  // Build notifications: reports sorted by latest timeline event, top 8
  const notifs = (reports || [])
    .map(r => {
      const events = r.timeline || [];
      const last = events[events.length - 1] || ['submitted', r.submittedAt, r.reporter];
      const [kind, when, who, note] = last;
      return { id: r.id, title: lang === 'th' ? r.title : (r.titleEn || r.title), kind, when, who, reporter: r.reporter, status: r.status };
    })
    .sort((a, b) => (b.when || '').localeCompare(a.when || ''))
    .slice(0, 8);
  const hasUnseen = (reports || []).some(r => r.status === 'pending');
  const kindLabel = (k) => ({
    submitted: lang === 'th' ? 'เรื่องใหม่' : 'New report',
    'in-progress': lang === 'th' ? 'เริ่มแก้ไข' : 'Started',
    progress: lang === 'th' ? 'อัปเดตความคืบหน้า' : 'Progress update',
    resolved: lang === 'th' ? 'แก้ไขเสร็จ' : 'Resolved',
  }[k] || k);
  const timeAgo = (iso) => {
    if (!iso) return '';
    const ms = Date.now() - new Date(iso).getTime();
    const m = Math.floor(ms / 60000);
    if (m < 1) return lang === 'th' ? 'เพิ่งจะ' : 'just now';
    if (m < 60) return lang === 'th' ? `${m} นาทีที่แล้ว` : `${m}m ago`;
    const h = Math.floor(m / 60);
    if (h < 24) return lang === 'th' ? `${h} ชม. ที่แล้ว` : `${h}h ago`;
    const d = Math.floor(h / 24);
    return lang === 'th' ? `${d} วันที่แล้ว` : `${d}d ago`;
  };
  return (
    <div className="bp-topbar" style={{
      padding:'16px 28px', borderBottom:'1px solid var(--bp-line)',
      display:'flex', alignItems:'center', gap: 16, background:'var(--bp-surface)',
    }}>
      <button className="bp-mobile-menu-btn" onClick={onMenuClick} style={{
        appearance:'none', cursor:'pointer',
        width: 36, height: 36, borderRadius: 10,
        border:'1px solid var(--bp-line)', background:'var(--bp-surface)',
        alignItems:'center', justifyContent:'center', color:'var(--bp-ink-2)',
        flexShrink: 0,
      }}>
        <Icon name="list" size={16}/>
      </button>

      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 20, fontWeight: 600, letterSpacing:'-0.01em', color:'var(--bp-ink)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{title}</div>
        {subtitle && <div style={{ fontSize: 12.5, color:'var(--bp-ink-3)', marginTop: 2, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{subtitle}</div>}
      </div>

      {/* search */}
      <div className="bp-topbar-search" style={{
        height: 36, width: 280, padding:'0 12px', borderRadius: 10,
        border:'1px solid var(--bp-line)', background:'var(--bp-soft)',
        display:'flex', alignItems:'center', gap: 8, flexShrink: 0,
      }}>
        <Icon name="search" size={15} stroke="var(--bp-ink-3)"/>
        <input placeholder={t.search} style={{
          flex: 1, appearance:'none', border:0, background:'transparent',
          fontSize: 12.5, color:'var(--bp-ink)', outline:'none', minWidth: 0,
        }}/>
        <span style={{ fontSize: 10.5, color:'var(--bp-ink-3)', padding:'1px 5px', border:'1px solid var(--bp-line)', borderRadius: 4, background:'#fff' }}>⌘K</span>
      </div>

      <div style={{ position:'relative', flexShrink: 0 }}>
        <button onClick={() => setShowNotifs(v => !v)} style={{
          appearance:'none', cursor:'pointer',
          width: 36, height: 36, borderRadius: 10,
          border:'1px solid var(--bp-line)', background:'var(--bp-surface)',
          display:'flex', alignItems:'center', justifyContent:'center',
          position:'relative',
        }}>
          <Icon name="bell" size={16}/>
          {hasUnseen && (
            <span style={{
              position:'absolute', top: 7, right: 7,
              width: 7, height: 7, borderRadius:'50%',
              background:'oklch(0.65 0.22 25)', border:'1.5px solid #fff',
            }}/>
          )}
        </button>
        {showNotifs && (
          <>
            <div onClick={() => setShowNotifs(false)} style={{ position:'fixed', inset: 0, zIndex: 50 }}/>
            <div style={{
              position:'absolute', top: 44, right: 0, zIndex: 51,
              width: 360, maxWidth: '90vw', maxHeight: 460, overflow:'auto',
              background:'var(--bp-surface)', border:'1px solid var(--bp-line)',
              borderRadius: 14, boxShadow:'var(--bp-shadow-lg)',
              padding: 8,
            }}>
              <div style={{ padding:'8px 12px', fontSize: 13, fontWeight: 600, color:'var(--bp-ink)' }}>
                {lang === 'th' ? 'การแจ้งเตือน' : 'Notifications'}
              </div>
              {notifs.length === 0 ? (
                <div style={{ padding:'18px 12px', fontSize: 12, color:'var(--bp-ink-3)', textAlign:'center' }}>
                  {lang === 'th' ? 'ยังไม่มีรายงาน' : 'No reports yet'}
                </div>
              ) : notifs.map(n => (
                <button key={n.id} onClick={() => { setShowNotifs(false); goToIssue && goToIssue(n.id); }} style={{
                  display:'flex', width:'100%', gap: 10, alignItems:'flex-start',
                  padding:'10px 12px', borderRadius: 10, cursor:'pointer',
                  appearance:'none', border:0, background:'transparent', textAlign:'left',
                }}
                onMouseOver={e => e.currentTarget.style.background = 'var(--bp-soft)'}
                onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
                  <div style={{
                    width: 8, height: 8, borderRadius:'50%', marginTop: 6, flexShrink: 0,
                    background: n.status === 'pending' ? 'oklch(0.65 0.22 25)' :
                                n.status === 'in-progress' ? 'oklch(0.62 0.18 70)' :
                                'oklch(0.55 0.16 155)',
                  }}/>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 12.5, color:'var(--bp-ink)', fontWeight: 500, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{n.title}</div>
                    <div style={{ fontSize: 11, color:'var(--bp-ink-3)', marginTop: 2 }}>
                      {kindLabel(n.kind)} · {n.who || n.reporter} · {timeAgo(n.when)}
                    </div>
                  </div>
                </button>
              ))}
            </div>
          </>
        )}
      </div>
    </div>
  );
}

// ─── Dashboard ───────────────────────────────────────────────
function TeacherDashboard({ t, lang, reports, goToIssue }) {
  const stats = useMemoT(() => {
    const total = reports.length;
    const resolved = reports.filter(r => r.status === 'resolved').length;
    const inProgress = reports.filter(r => r.status === 'in-progress').length;
    const pending = reports.filter(r => r.status === 'pending').length;
    const pct = total ? Math.round((resolved / total) * 100) : 0;
    return { total, resolved, inProgress, pending, pct };
  }, [reports]);

  const byCategory = useMemoT(() => {
    const groups = {};
    CATEGORIES.forEach(c => groups[c.id] = { cat: c, total: 0, resolved: 0 });
    reports.forEach(r => {
      groups[r.category].total += 1;
      if (r.status === 'resolved') groups[r.category].resolved += 1;
    });
    return Object.values(groups).filter(g => g.total > 0).sort((a, b) => b.total - a.total);
  }, [reports]);

  const recent = reports.slice(0, 6);

  return (
    <div style={{ padding:'24px 28px 40px', display:'flex', flexDirection:'column', gap: 22 }}>

      {/* Last updated row */}
      <div style={{ display:'flex', alignItems:'center', justifyContent:'flex-end' }}>
        <div style={{ fontSize: 12, color:'var(--bp-ink-3)', display:'inline-flex', alignItems:'center', gap: 6 }}>
          <Icon name="calendar" size={13}/> {lang === 'th' ? 'อัปเดตล่าสุด: เมื่อสักครู่' : 'Last updated: just now'}
        </div>
      </div>

      {/* Top row: pie + stat cards */}
      <div className="bp-grid-2col">
        {/* Pie card */}
        <div className="bp-card" style={{ padding: 22, display:'flex', flexDirection:'column', gap: 16 }}>
          <div style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between' }}>
            <div>
              <div style={{ fontSize: 14, fontWeight: 600, color:'var(--bp-ink)' }}>{t.resolvedPct}</div>
              <div style={{ fontSize: 11.5, color:'var(--bp-ink-3)' }}>{lang === 'th' ? 'สัดส่วนสถานะของเรื่องทั้งหมด' : 'Status share of all reports'}</div>
            </div>
          </div>

          <div style={{ display:'flex', alignItems:'center', gap: 22 }}>
            <Donut
              size={186} stroke={22}
              segments={[
                { value: stats.resolved,   color: 'oklch(0.60 0.16 155)' },
                { value: stats.inProgress, color: 'oklch(0.66 0.20 260)' },
                { value: stats.pending,    color: 'oklch(0.72 0.18 70)' },
              ]}
              center={
                <>
                  <div className="font-num" style={{ fontSize: 38, fontWeight: 700, color:'var(--bp-ink)', letterSpacing:'-0.02em', lineHeight: 1 }}>{stats.pct}<span style={{ fontSize: 18, color:'var(--bp-ink-3)' }}>%</span></div>
                  <div style={{ fontSize: 10.5, color:'var(--bp-ink-3)', marginTop: 4, textTransform:'uppercase', letterSpacing:'0.06em' }}>{t.resolvedPct}</div>
                </>
              }
            />
            <div style={{ flex: 1, display:'flex', flexDirection:'column', gap: 10 }}>
              <LegendRow color="oklch(0.60 0.16 155)" label={t.resolved} value={stats.resolved}/>
              <LegendRow color="oklch(0.66 0.20 260)" label={t.inProgress} value={stats.inProgress}/>
              <LegendRow color="oklch(0.72 0.18 70)"  label={t.pending} value={stats.pending}/>
            </div>
          </div>
        </div>

        {/* Stat cards grid */}
        <div className="bp-grid-stats">
          <BigStat icon="list" tint="var(--bp-blue)"      label={t.totalReports}    value={stats.total}       trend="+8% เทียบเดือนก่อน"/>
          <BigStat icon="bolt" tint="oklch(0.62 0.22 25)" label={t.pendingCount}    value={stats.pending}     trend="ต้องรับเรื่องวันนี้"/>
          <BigStat icon="clock" tint="oklch(0.60 0.18 70)" label={t.inProgressCount} value={stats.inProgress}  trend="กำลังดำเนินการ"/>
        </div>
      </div>

      {/* By category bar + recent */}
      <div className="bp-grid-2col">
        {/* Category breakdown */}
        <div className="bp-card" style={{ padding: 22 }}>
          <div style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between', marginBottom: 14 }}>
            <div style={{ fontSize: 14, fontWeight: 600 }}>{t.byCategory}</div>
            <div style={{ fontSize: 11, color:'var(--bp-ink-3)' }}>{lang === 'th' ? 'รวม' : 'Total'} · {reports.length}</div>
          </div>
          <div style={{ display:'flex', flexDirection:'column', gap: 11 }}>
            {byCategory.map(g => (
              <div key={g.cat.id}>
                <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom: 5 }}>
                  <div style={{ display:'flex', alignItems:'center', gap: 8, fontSize: 12, color:'var(--bp-ink-2)' }}>
                    <span style={{
                      width: 18, height: 18, borderRadius: 5, background: g.cat.tint, color:'#fff',
                      display:'inline-flex', alignItems:'center', justifyContent:'center',
                    }}><Icon name={CAT_ICONS[g.cat.id]} size={10} strokeWidth={2.2}/></span>
                    <span>{g.cat[lang]}</span>
                  </div>
                  <div className="font-num" style={{ fontSize: 12, color:'var(--bp-ink)', fontWeight: 500 }}>
                    {g.resolved}<span style={{ color:'var(--bp-ink-3)' }}>/{g.total}</span>
                  </div>
                </div>
                <div style={{ height: 6, borderRadius: 3, background:'var(--bp-soft)', overflow:'hidden', position:'relative' }}>
                  <div style={{
                    position:'absolute', inset: 0,
                    width: `${(g.total / reports.length) * 100}%`,
                    background: g.cat.tint + '40',
                    borderRadius: 3,
                  }}/>
                  <div style={{
                    position:'absolute', left: 0, top: 0, bottom: 0,
                    width: `${(g.resolved / reports.length) * 100}%`,
                    background: g.cat.tint,
                    borderRadius: 3,
                  }}/>
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* Recent reports table */}
        <div className="bp-card" style={{ padding: 22 }}>
          <div style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between', marginBottom: 12 }}>
            <div style={{ fontSize: 14, fontWeight: 600 }}>{t.recent}</div>
            <div style={{ fontSize: 11.5, color: 'var(--bp-blue)', cursor:'pointer', fontWeight: 500 }}>{t.seeAll} ›</div>
          </div>
          <div style={{ display:'flex', flexDirection:'column' }}>
            {recent.map((r, i) => (
              <TeacherListRow key={r.id} r={r} t={t} lang={lang}
                onClick={() => goToIssue(r.id)}
                last={i === recent.length - 1}/>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function LegendRow({ color, label, value }) {
  return (
    <div style={{
      display:'flex', alignItems:'center', gap: 10,
      padding:'8px 10px', borderRadius: 10, background:'var(--bp-soft)',
    }}>
      <span style={{ width: 10, height: 10, borderRadius: 3, background: color }}/>
      <span style={{ flex: 1, fontSize: 12.5, color:'var(--bp-ink-2)' }}>{label}</span>
      <span className="font-num" style={{ fontSize: 14, fontWeight: 600, color:'var(--bp-ink)' }}>{value}</span>
    </div>
  );
}

function BigStat({ icon, tint, label, value, unit, trend }) {
  return (
    <div className="bp-card" style={{ padding: 18, display:'flex', flexDirection:'column', gap: 8 }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <div style={{
          width: 32, height: 32, borderRadius: 9,
          background: tint + '1A', color: tint,
          display:'flex', alignItems:'center', justifyContent:'center',
        }}><Icon name={icon} size={16}/></div>
      </div>
      <div className="font-num" style={{ fontSize: 30, fontWeight: 700, color:'var(--bp-ink)', letterSpacing:'-0.02em', lineHeight: 1 }}>
        {value} {unit && <span style={{ fontSize: 14, color:'var(--bp-ink-3)', fontWeight: 500 }}>{unit}</span>}
      </div>
      <div style={{ fontSize: 11.5, color:'var(--bp-ink-3)', display:'flex', flexDirection:'column' }}>
        <span style={{ color:'var(--bp-ink-2)', fontWeight: 500, fontSize: 12 }}>{label}</span>
        <span style={{ marginTop: 1 }}>{trend}</span>
      </div>
    </div>
  );
}

// ─── Mini progress bar (inline) ────────────────────────────
function MiniProgress({ value }) {
  const v = Math.max(0, Math.min(100, value));
  const color = v >= 75 ? 'oklch(0.55 0.16 155)'
              : v >= 40 ? 'oklch(0.56 0.20 265)'
              :           'oklch(0.66 0.20 290)';
  return (
    <div style={{ display:'flex', alignItems:'center', gap: 6, marginTop: 6, maxWidth: 220 }}>
      <div style={{
        flex: 1, height: 4, borderRadius: 999, background:'var(--bp-soft)', overflow:'hidden',
      }}>
        <div style={{
          width: v + '%', height:'100%', borderRadius: 999,
          background: color, transition:'width .25s ease',
        }}/>
      </div>
      <span className="font-num" style={{ fontSize: 10.5, fontWeight: 600, color, minWidth: 28, textAlign:'right' }}>{v}%</span>
    </div>
  );
}

function TeacherListRow({ r, t, lang, onClick, last }) {
  const cat = CAT_BY_ID[r.category];
  return (
    <button onClick={onClick} style={{
      appearance:'none', border:0, background:'transparent', cursor:'pointer',
      padding:'10px 0', textAlign:'left',
      display:'grid', gridTemplateColumns:'auto 1fr auto auto auto', gap: 14, alignItems:'center',
      borderBottom: last ? '0' : '1px solid var(--bp-line)',
    }}>
      <div style={{ width: 44, height: 44 }}>
        <Photo hue={r.before.hue} label={r.before.label} url={r.before.url} tag="" height={44} style={{ borderRadius: 9, padding: 0 }}/>
      </div>
      <div style={{ minWidth: 0 }}>
        <div style={{
          fontSize: 13, fontWeight: 500, color:'var(--bp-ink)',
          whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis',
        }}>{lang === 'th' ? r.title : r.titleEn}</div>
        <div style={{ fontSize: 11, color:'var(--bp-ink-3)', marginTop: 2, display:'flex', alignItems:'center', gap: 6 }}>
          <span className="font-mono">{r.id}</span>
          <span>·</span>
          <span>{r.reporter} {r.grade}</span>
        </div>
        {r.status === 'in-progress' && <MiniProgress value={r.progress || 0}/>}
      </div>
      <CategoryChip cat={cat} lang={lang}/>
      <div style={{ fontSize: 11, color:'var(--bp-ink-3)' }}>{relTime(r.submittedAt, lang)}</div>
      <StatusPill status={r.status} lang={lang} t={t}/>
    </button>
  );
}

// ─── Issues page (list + filters) ──────────────────────────
function TeacherIssues({ t, lang, reports, goToIssue }) {
  const [cat, setCat] = useStateT('all');
  const [status, setStatus] = useStateT('all');

  const filtered = reports.filter(r =>
    (cat === 'all' || r.category === cat) &&
    (status === 'all' || r.status === status)
  );

  return (
    <div style={{ padding:'24px 28px 40px' }}>
      {/* Filters */}
      <div className="bp-card" style={{ padding: 14, display:'flex', alignItems:'center', gap: 12, flexWrap:'wrap' }}>
        <div style={{ display:'inline-flex', alignItems:'center', gap: 6, color:'var(--bp-ink-3)', fontSize: 12, paddingLeft: 4 }}>
          <Icon name="filter" size={14}/> {t.filter}
        </div>

        <FilterSelect value={cat} onChange={setCat} options={[
          ['all', t.allCategories],
          ...CATEGORIES.map(c => [c.id, c[lang]])
        ]}/>
        <FilterSelect value={status} onChange={setStatus} options={[
          ['all', t.allStatuses],
          ['pending', t.pending],
          ['in-progress', t.inProgress],
          ['resolved', t.resolved],
        ]}/>

        <div style={{ flex: 1 }}/>
        <span style={{ fontSize: 12, color:'var(--bp-ink-3)' }}>
          {filtered.length} / {reports.length} {lang === 'th' ? 'รายการ' : 'reports'}
        </span>
      </div>

      {/* Table */}
      <div className="bp-card" style={{ marginTop: 14, padding: 0, overflow:'hidden' }}>
        <div className="bp-issue-table-head" style={{
          gridTemplateColumns:'56px minmax(0, 2.6fr) minmax(0, 1.1fr) minmax(0, 1.2fr) auto auto',
          gap: 14, padding:'12px 18px',
          background:'var(--bp-soft)',
          fontSize: 11, fontWeight: 600, color:'var(--bp-ink-3)',
          textTransform:'uppercase', letterSpacing:'0.04em',
        }}>
          <div></div>
          <div>{lang === 'th' ? 'รายงาน' : 'Report'}</div>
          <div>{t.category}</div>
          <div>{t.reporter}</div>
          <div>{lang === 'th' ? 'เวลา' : 'Time'}</div>
          <div>{lang === 'th' ? 'สถานะ' : 'Status'}</div>
        </div>

        {filtered.map((r, i) => {
          const c = CAT_BY_ID[r.category];
          return (
            <button key={r.id} onClick={() => goToIssue(r.id)} className="bp-issue-row" style={{
              appearance:'none', border:0, background:'var(--bp-surface)', cursor:'pointer',
              width:'100%', textAlign:'left',
              gridTemplateColumns:'56px minmax(0, 2.6fr) minmax(0, 1.1fr) minmax(0, 1.2fr) auto auto',
              gap: 14, padding:'14px 18px', alignItems:'center',
              borderBottom: i < filtered.length - 1 ? '1px solid var(--bp-line)' : '0',
              fontFamily:'inherit',
            }}>
              <div style={{ width: 44, height: 44 }}>
                <Photo hue={r.before.hue} label={r.before.label} url={r.before.url} tag="" height={44} style={{ borderRadius: 9, padding: 0 }}/>
              </div>
              <div style={{ minWidth: 0 }}>
                <div style={{ fontSize: 13.5, fontWeight: 500, color:'var(--bp-ink)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
                  {lang === 'th' ? r.title : r.titleEn}
                </div>
                <div className="font-mono" style={{ fontSize: 10.5, color:'var(--bp-ink-3)', marginTop: 2 }}>{r.id}</div>
                {r.status === 'in-progress' && <MiniProgress value={r.progress || 0}/>}
              </div>
              <div className="bp-cell-cat"><CategoryChip cat={c} lang={lang}/></div>
              <div className="bp-cell-reporter" style={{ fontSize: 12, color:'var(--bp-ink-2)', minWidth: 0, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
                {r.reporter} <span style={{ color:'var(--bp-ink-3)' }}>{r.grade}</span>
              </div>
              <div className="bp-cell-time" style={{ fontSize: 12, color:'var(--bp-ink-3)', whiteSpace:'nowrap' }}>{relTime(r.submittedAt, lang)}</div>
              <div className="bp-cell-status"><StatusPill status={r.status} lang={lang} t={t}/></div>
            </button>
          );
        })}

        {filtered.length === 0 && (
          <div style={{ padding: 40, textAlign:'center', color:'var(--bp-ink-3)', fontSize: 13 }}>
            {lang === 'th' ? 'ไม่พบรายการตามตัวกรอง' : 'No reports match the current filter'}
          </div>
        )}
      </div>
    </div>
  );
}

function FilterSelect({ value, onChange, options }) {
  return (
    <select value={value} onChange={e => onChange(e.target.value)} style={{
      appearance:'none', WebkitAppearance:'none',
      padding:'7px 28px 7px 12px', borderRadius: 9,
      background:'var(--bp-surface)', border:'1px solid var(--bp-line)',
      fontSize: 12, color:'var(--bp-ink-2)', fontFamily:'inherit',
      backgroundImage: "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='%2364607a' d='M0 0h10L5 6z'/></svg>\")",
      backgroundRepeat: 'no-repeat',
      backgroundPosition: 'right 10px center',
    }}>
      {options.map(([v, l]) => <option key={v} value={v}>{l}</option>)}
    </select>
  );
}

// ─── Progress card (teacher) ─────────────────────────────
function ProgressCard({ report, t, lang, onChange, onResolveSuggest }) {
  const saved = report.progress || 0;
  const [val, setVal] = useStateT(saved);

  // sync when report changes externally
  useEffectT(() => { setVal(saved); }, [saved]);

  const dirty = val !== saved;
  const color = val >= 100 ? 'oklch(0.55 0.16 155)'
              : val >= 50  ? 'oklch(0.56 0.20 265)'
              : val >= 25  ? 'oklch(0.62 0.20 290)'
              :              'oklch(0.68 0.18 75)';

  const stateLabel = val === 0
    ? (lang === 'th' ? 'ยังไม่ได้เริ่ม' : 'Not started')
    : val < 50
      ? (lang === 'th' ? 'เริ่มดำเนินการ' : 'Started')
      : val < 100
        ? (lang === 'th' ? 'ดำเนินการอยู่' : 'In progress')
        : (lang === 'th' ? 'เสร็จสมบูรณ์' : 'Complete');

  return (
    <div className="bp-card" style={{ padding: 22 }}>
      <div style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between' }}>
        <div>
          <div style={{ fontSize: 14, fontWeight: 600, color:'var(--bp-ink)' }}>
            {t.updateProgress}
          </div>
          <div style={{ fontSize: 11.5, color:'var(--bp-ink-3)', marginTop: 2 }}>{t.progressHint}</div>
        </div>
        <span style={{
          fontSize: 11, fontWeight: 600,
          padding:'4px 10px', borderRadius: 999,
          background: color + '1A', color,
        }}>● {stateLabel}</span>
      </div>

      {/* Big % display */}
      <div style={{ display:'flex', alignItems:'baseline', gap: 4, marginTop: 18 }}>
        <span className="font-num" style={{
          fontSize: 54, fontWeight: 700, color, letterSpacing:'-0.025em', lineHeight: 1,
        }}>{val}</span>
        <span style={{ fontSize: 22, color:'var(--bp-ink-3)', fontWeight: 500 }}>%</span>
        {dirty && (
          <span style={{
            marginLeft:'auto', fontSize: 11, fontWeight: 500, color:'oklch(0.55 0.18 70)',
            display:'inline-flex', alignItems:'center', gap: 5,
          }}>
            <span style={{ width: 6, height: 6, borderRadius:'50%', background:'oklch(0.65 0.20 75)' }}/>
            {lang === 'th' ? 'ยังไม่บันทึก' : 'Unsaved'}
          </span>
        )}
      </div>

      {/* Slider */}
      <input
        type="range" min="0" max="100" step="5" value={val}
        onChange={e => setVal(parseInt(e.target.value, 10))}
        className="bp-prog-slider"
        style={{
          '--bp-slider-color': color,
          '--bp-slider-pct': val + '%',
        }}/>

      <div style={{ display:'flex', justifyContent:'space-between', fontSize: 10, color:'var(--bp-ink-3)', marginTop: 6, fontFamily:'IBM Plex Mono', letterSpacing:'0.04em' }}>
        <span>0%</span><span>25%</span><span>50%</span><span>75%</span><span>100%</span>
      </div>

      {/* Quick buttons */}
      <div style={{ display:'flex', gap: 6, marginTop: 14 }}>
        {[0, 25, 50, 75, 100].map(q => {
          const active = val === q;
          return (
            <button key={q} onClick={() => setVal(q)} style={{
              flex: 1, appearance:'none', cursor:'pointer',
              padding:'7px 4px', borderRadius: 9,
              background: active ? color : 'var(--bp-soft)',
              color: active ? '#fff' : 'var(--bp-ink-2)',
              border: 0, fontSize: 11.5, fontWeight: 600,
              transition:'background .12s ease',
            }}>{q}%</button>
          );
        })}
      </div>

      {/* Save button + auto-log hint */}
      <div style={{
        marginTop: 16, paddingTop: 14, borderTop:'1px solid var(--bp-line)',
        display:'flex', alignItems:'center', gap: 12,
      }}>
        <div style={{ flex: 1, fontSize: 11, color:'var(--bp-ink-3)', display:'inline-flex', alignItems:'center', gap: 6 }}>
          <Icon name="clock" size={12}/> {t.autoLogged}
          {saved > 0 && (
            <span style={{ marginLeft: 6 }}>
              {lang === 'th' ? 'ล่าสุด' : 'last'}: <strong style={{ color:'var(--bp-ink-2)' }}>{saved}%</strong>
            </span>
          )}
        </div>
        <button onClick={() => onChange(val)} disabled={!dirty} style={{
          appearance:'none', border:0,
          cursor: dirty ? 'pointer' : 'not-allowed',
          padding:'9px 16px', borderRadius: 10,
          background: dirty ? 'var(--bp-grad)' : 'var(--bp-soft)',
          color: dirty ? '#fff' : 'var(--bp-ink-3)',
          fontSize: 12.5, fontWeight: 600,
          boxShadow: dirty ? '0 6px 14px rgba(80,50,180,0.22)' : 'none',
          display:'inline-flex', alignItems:'center', gap: 6,
        }}>
          <Icon name="check" size={14}/> {lang === 'th' ? 'บันทึก' : 'Save'}
        </button>
      </div>

      {/* 100% hint */}
      {val === 100 && (
        <div style={{
          marginTop: 12, padding:'10px 14px', borderRadius: 11,
          background:'oklch(0.96 0.06 155)', border:'1px solid oklch(0.88 0.08 155)',
          display:'flex', alignItems:'center', gap: 10,
        }}>
          <div style={{
            width: 26, height: 26, borderRadius: 8,
            background:'oklch(0.55 0.16 155)', color:'#fff',
            display:'flex', alignItems:'center', justifyContent:'center', flexShrink: 0,
          }}><Icon name="check" size={14} strokeWidth={2.4}/></div>
          <div style={{ flex: 1, fontSize: 12, color:'oklch(0.30 0.10 155)' }}>{t.completedFully}</div>
          <button onClick={onResolveSuggest} style={{
            appearance:'none', border:0, cursor:'pointer',
            background:'oklch(0.55 0.16 155)', color:'#fff',
            padding:'6px 12px', borderRadius: 8,
            fontSize: 11.5, fontWeight: 600,
          }}>
            {t.markResolved}
          </button>
        </div>
      )}
    </div>
  );
}

// ─── Issue detail ──────────────────────────────────────────
function TeacherDetail({ t, lang, report: r, goBack, prevPage, updateReport }) {
  const [showResolveModal, setShowResolveModal] = useStateT(false);
  const [note, setNote] = useStateT('');
  const [thanked, setThanked] = useStateT((r.thanks || 0) > 0);

  const backLabel = lang === 'th'
    ? ({ dashboard: 'กลับไปแดชบอร์ด', issues: 'กลับไปยังรายการ', timeline: 'กลับไปไทม์ไลน์' }[prevPage] || 'ย้อนกลับ')
    : ({ dashboard: 'Back to dashboard', issues: 'Back to list', timeline: 'Back to timeline' }[prevPage] || 'Back');

  if (!r) return null;
  const cat = CAT_BY_ID[r.category];

  function accept() {
    updateReport(r.id, prev => ({
      ...prev, status: 'in-progress',
      progress: Math.max(prev.progress || 0, 10),
      timeline: [...prev.timeline, ['in-progress', new Date().toISOString(), 'ครูประภาส']],
    }));
  }
  function resolve() {
    updateReport(r.id, prev => ({
      ...prev, status: 'resolved',
      progress: 100,
      // Preserve existing after photo if teacher uploaded one; only set placeholder if none yet
      after: prev.after || { hue: 155, label: 'AFTER · FIX COMPLETED' },
      timeline: [...prev.timeline, ['resolved', new Date().toISOString(), 'ครูประภาส', note || 'แก้ไขเสร็จเรียบร้อย']],
    }));
    setShowResolveModal(false);
    setNote('');
  }
  function setProgress(newPct) {
    updateReport(r.id, prev => {
      const note = lang === 'th'
        ? `อัปเดตความคืบหน้าเป็น ${newPct}% (จาก ${prev.progress || 0}%)`
        : `Progress updated to ${newPct}% (from ${prev.progress || 0}%)`;
      return {
        ...prev,
        progress: newPct,
        status: newPct === 100 ? prev.status : (prev.status === 'pending' && newPct > 0 ? 'in-progress' : prev.status),
        timeline: [...prev.timeline, ['progress', new Date().toISOString(), 'ครูประภาส', note]],
      };
    });
  }
  function thank() {
    updateReport(r.id, prev => ({ ...prev, thanks: (prev.thanks || 0) + 1 }));
    setThanked(true);
  }

  return (
    <div style={{ padding:'24px 28px 40px', display:'flex', flexDirection:'column', gap: 18 }}>
      <button onClick={goBack} style={{
        appearance:'none', border:'1px solid var(--bp-line)', background:'var(--bp-surface)', cursor:'pointer',
        color:'var(--bp-ink-2)', fontSize: 12.5, fontWeight: 500,
        display:'inline-flex', alignItems:'center', gap: 6,
        padding:'8px 14px 8px 11px', borderRadius: 999, alignSelf:'flex-start',
        boxShadow:'var(--bp-shadow-sm)',
      }}>
        <Icon name="chev_l" size={14}/> {backLabel}
      </button>

      <div className="bp-grid-detail">
        {/* Left column */}
        <div style={{ display:'flex', flexDirection:'column', gap: 16 }}>

          {/* Header card */}
          <div className="bp-card" style={{ padding: 22 }}>
            <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap: 14 }}>
              <div style={{ minWidth: 0 }}>
                <div style={{ display:'flex', gap: 8, alignItems:'center', marginBottom: 8 }}>
                  <CategoryChip cat={cat} lang={lang}/>
                  <StatusPill status={r.status} lang={lang} t={t}/>
                </div>
                <h1 style={{ margin: 0, fontSize: 22, fontWeight: 600, color:'var(--bp-ink)', letterSpacing:'-0.01em', lineHeight: 1.25 }}>
                  {lang === 'th' ? r.title : r.titleEn}
                </h1>
                <div className="font-mono" style={{ fontSize: 11, color:'var(--bp-ink-3)', marginTop: 6 }}>{r.id}</div>
              </div>
            </div>

            <p style={{ marginTop: 16, fontSize: 13.5, color:'var(--bp-ink-2)', lineHeight: 1.65 }}>
              {lang === 'th' ? r.desc : r.descEn}
            </p>

            <div className="bp-grid-meta3" style={{
              marginTop: 18,
              padding:'14px 0 0', borderTop:'1px solid var(--bp-line)',
            }}>
              <KV icon="user"   label={t.reporter}     value={`${r.reporter} · ${r.grade}`}/>
              <KV icon="pin"    label={t.location}     value={lang === 'th' ? r.location : r.locationEn}/>
              <KV icon="clock"  label={t.submittedOn}  value={fullDateTime(r.submittedAt, lang)}/>
            </div>
          </div>

          {/* Progress (in-progress only) */}
          {(r.status === 'in-progress' || r.status === 'pending') && (
            <ProgressCard report={r} t={t} lang={lang} onChange={setProgress} onResolveSuggest={() => setShowResolveModal(true)}/>
          )}

          {/* Photos */}
          <div className="bp-card" style={{ padding: 22 }}>
            <div style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between', marginBottom: 12 }}>
              <div style={{ fontSize: 14, fontWeight: 600 }}>{t.photoLabel}</div>
              <div style={{ fontSize: 11, color:'var(--bp-ink-3)' }}>{lang === 'th' ? 'เปรียบเทียบก่อน/หลัง' : 'Before / after'}</div>
            </div>
            <div className="bp-grid-photos">
              <div>
                <div style={{ fontSize: 11, fontWeight: 600, color:'var(--bp-ink-3)', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom: 6 }}>{t.before}</div>
                <Photo hue={r.before.hue} label={r.before.label} url={r.before.url} tag="BEFORE" height={220} style={{ borderRadius: 14, padding: 14 }}/>
              </div>
              <div>
                <div style={{ fontSize: 11, fontWeight: 600, color:'var(--bp-ink-3)', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom: 6 }}>{t.after}</div>
                {r.after ? (
                  <div>
                    <Photo hue={r.after.hue} label={r.after.label} url={r.after.url} tag="AFTER" after height={220} style={{ borderRadius: 14, padding: 14 }}/>
                    <label style={{
                      marginTop: 8, display:'flex', alignItems:'center', justifyContent:'center', gap: 6,
                      padding:'8px 12px', borderRadius: 10, border:'1px solid var(--bp-line)',
                      background:'var(--bp-soft)', color:'var(--bp-ink-2)', cursor:'pointer',
                      fontSize: 12, fontWeight: 500,
                    }}>
                      <input type="file" accept="image/*" capture="environment" onChange={async (e) => {
                        const file = e.target.files && e.target.files[0];
                        if (!file) return;
                        const reader = new FileReader();
                        reader.onload = ev => updateReport(r.id, prev => ({ ...prev, after: { hue: 155, label: 'AFTER', url: ev.target.result } }));
                        reader.readAsDataURL(file);
                        try {
                          const url = await sbUploadImage(file, r.id, 'after');
                          if (url) updateReport(r.id, prev => ({ ...prev, after: { ...(prev.after||{}), hue: 155, label: 'AFTER', url } }));
                        } catch {}
                        e.target.value = '';
                      }} style={{ display:'none' }}/>
                      <Icon name="refresh" size={13}/> {lang === 'th' ? 'เปลี่ยนรูป' : 'Change photo'}
                    </label>
                  </div>
                ) : (
                  <label style={{
                    height: 220, borderRadius: 14, border:'1.5px dashed var(--bp-line-2)',
                    display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center',
                    gap: 10, color:'var(--bp-ink-3)', cursor:'pointer',
                    background:'var(--bp-soft)',
                    transition:'background .15s ease',
                  }}>
                    <input type="file" accept="image/*" capture="environment" onChange={async (e) => {
                      const file = e.target.files && e.target.files[0];
                      if (!file) return;
                      const reader = new FileReader();
                      reader.onload = ev => updateReport(r.id, prev => ({ ...prev, after: { hue: 155, label: 'AFTER', url: ev.target.result } }));
                      reader.readAsDataURL(file);
                      try {
                        const url = await sbUploadImage(file, r.id, 'after');
                        if (url) updateReport(r.id, prev => ({ ...prev, after: { ...(prev.after||{}), hue: 155, label: 'AFTER', url } }));
                      } catch {}
                      e.target.value = '';
                    }} style={{ display:'none' }}/>
                    <Icon name="upload" size={28} stroke="var(--bp-blue)"/>
                    <div style={{ fontSize: 13, fontWeight: 500, color:'var(--bp-ink-2)' }}>{t.uploadAfter}</div>
                    <div style={{ fontSize: 11, color:'var(--bp-ink-3)' }}>JPG, PNG · ไม่เกิน 10 MB</div>
                  </label>
                )}
              </div>
            </div>
          </div>

          {/* Timeline */}
          <div className="bp-card" style={{ padding: 22 }}>
            <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 16 }}>{t.timelineEvents}</div>
            <Timeline events={r.timeline} t={t} lang={lang}/>
          </div>
        </div>

        {/* Right column — actions */}
        <div style={{ display:'flex', flexDirection:'column', gap: 14, position:'sticky', top: 0, alignSelf:'start' }}>
          <div className="bp-card" style={{ padding: 18, display:'flex', flexDirection:'column', gap: 10 }}>
            <div style={{ fontSize: 13, fontWeight: 600, marginBottom: 4 }}>
              {lang === 'th' ? 'การดำเนินการ' : 'Actions'}
            </div>

            {r.status === 'pending' && (
              <button onClick={accept} style={primaryBtn}>
                <Icon name="check" size={16}/> {t.markInProgress}
              </button>
            )}
            {r.status === 'in-progress' && (
              <button
                onClick={() => setShowResolveModal(true)}
                disabled={(r.progress || 0) < 100}
                style={(r.progress || 0) < 100
                  ? { ...primaryBtn, background:'var(--bp-soft)', color:'var(--bp-ink-3)', boxShadow:'none', cursor:'not-allowed', opacity: 0.7 }
                  : primaryBtn}>
                <Icon name="check" size={16}/> {(r.progress || 0) < 100
                  ? (lang === 'th' ? `ต้องครบ 100% (ตอนนี้ ${r.progress || 0}%)` : `Reach 100% first (${r.progress || 0}%)`)
                  : t.markResolved}
              </button>
            )}
            {r.status === 'resolved' && (
              <button disabled style={{ ...primaryBtn, background:'var(--bp-soft)', color:'var(--bp-ink-3)', boxShadow:'none', cursor:'default' }}>
                <Icon name="check" size={16}/> {lang === 'th' ? 'ปิดเรื่องแล้ว' : 'Already resolved'}
              </button>
            )}

            <button onClick={thank} disabled={thanked} style={{
              ...secondaryBtn,
              opacity: thanked ? 0.7 : 1,
              cursor: thanked ? 'default' : 'pointer',
              color: thanked ? 'var(--bp-violet)' : 'var(--bp-ink-2)',
              borderColor: thanked ? 'var(--bp-violet)' : 'var(--bp-line)',
            }}>
              <Icon name="heart" size={15} fill={thanked ? 'var(--bp-violet)' : 'none'}/>
              {thanked ? t.thanked : t.thank}
            </button>
          </div>

          {/* Reporter card */}
          <div className="bp-card" style={{ padding: 18 }}>
            <div style={{ fontSize: 12, color:'var(--bp-ink-3)', marginBottom: 12, textTransform:'uppercase', letterSpacing:'0.04em', fontWeight: 600 }}>
              {t.reporter}
            </div>
            <div style={{ display:'flex', alignItems:'center', gap: 12 }}>
              <div style={{
                width: 44, height: 44, borderRadius:'50%',
                background:'var(--bp-grad)', color:'#fff',
                display:'flex', alignItems:'center', justifyContent:'center',
                fontFamily:'Space Grotesk', fontWeight: 600,
              }}>{r.reporter.split('')[0]}</div>
              <div>
                <div style={{ fontSize: 14, fontWeight: 600 }}>{r.reporter}</div>
                <div style={{ fontSize: 11.5, color:'var(--bp-ink-3)' }}>{r.grade}</div>
              </div>
            </div>
            {r.thanks > 0 && (
              <div style={{
                marginTop: 12, padding:'8px 12px',
                background:'oklch(0.96 0.04 295)', borderRadius: 10,
                fontSize: 11.5, color:'var(--bp-violet)', fontWeight: 500,
                display:'inline-flex', alignItems:'center', gap: 6,
              }}>
                <Icon name="heart" size={12} fill="var(--bp-violet)"/> ขอบคุณ {r.thanks} ครั้ง
              </div>
            )}
          </div>

          {/* Quick info */}
          <div className="bp-card" style={{ padding: 18, fontSize: 12, color:'var(--bp-ink-2)', lineHeight: 1.7 }}>
            <div style={{ fontSize: 12, color:'var(--bp-ink-3)', marginBottom: 8, textTransform:'uppercase', letterSpacing:'0.04em', fontWeight: 600 }}>
              {lang === 'th' ? 'ข้อมูลเพิ่มเติม' : 'Metadata'}
            </div>
            <Row k={t.category} v={cat[lang]}/>
          </div>
        </div>
      </div>

      {/* Resolve modal */}
      {showResolveModal && (
        <div onClick={() => setShowResolveModal(false)} style={{
          position:'absolute', inset: 0,
          background:'rgba(20, 14, 60, 0.42)',
          backdropFilter:'blur(6px)', WebkitBackdropFilter:'blur(6px)',
          display:'flex', alignItems:'center', justifyContent:'center',
          zIndex: 50, padding: 30,
        }}>
          <div onClick={e => e.stopPropagation()} style={{
            background:'var(--bp-surface)', borderRadius: 20, padding: 26, width: 460, maxWidth:'100%',
            boxShadow:'var(--bp-shadow-lg)',
          }}>
            <div style={{ display:'flex', alignItems:'center', gap: 12, marginBottom: 12 }}>
              <div style={{
                width: 38, height: 38, borderRadius: 12,
                background:'oklch(0.94 0.07 155)', color:'oklch(0.45 0.16 155)',
                display:'flex', alignItems:'center', justifyContent:'center',
              }}><Icon name="check" size={18} strokeWidth={2.2}/></div>
              <div>
                <div style={{ fontSize: 16, fontWeight: 600 }}>{t.confirmResolve}</div>
                <div style={{ fontSize: 12, color:'var(--bp-ink-3)' }}>
                  {lang === 'th' ? 'ระบบจะแจ้งเตือนนักเรียนผู้รายงานทันที' : 'The reporter will be notified immediately.'}
                </div>
              </div>
            </div>

            <FormLabel style={{ marginTop: 12 }}>{t.note}</FormLabel>
            <textarea value={note} onChange={e => setNote(e.target.value)}
              placeholder={t.notePlaceholder}
              style={{ ...inputStyle('textarea'), minHeight: 80 }}/>

            <div style={{
              marginTop: 14, padding: 12, borderRadius: 12,
              background:'var(--bp-soft)', border:'1px solid var(--bp-line)',
              display:'flex', alignItems:'center', gap: 10,
            }}>
              <Icon name="bell" size={16} stroke="var(--bp-blue)"/>
              <div style={{ fontSize: 12, color:'var(--bp-ink-2)' }}>{t.notifSent}</div>
            </div>

            <div style={{ display:'flex', gap: 10, marginTop: 16, justifyContent:'flex-end' }}>
              <button onClick={() => setShowResolveModal(false)} style={{ ...secondaryBtn, width:'auto', padding:'10px 18px' }}>
                {t.cancel}
              </button>
              <button onClick={resolve} style={{ ...primaryBtn, width:'auto', padding:'10px 22px' }}>
                <Icon name="check" size={15}/> {t.markResolved}
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function KV({ icon, label, value }) {
  return (
    <div>
      <div style={{ fontSize: 10.5, color:'var(--bp-ink-3)', textTransform:'uppercase', letterSpacing:'0.06em', fontWeight: 600, display:'inline-flex', alignItems:'center', gap: 5 }}>
        <Icon name={icon} size={11}/> {label}
      </div>
      <div style={{ fontSize: 13, color:'var(--bp-ink)', marginTop: 4, lineHeight: 1.4 }}>{value}</div>
    </div>
  );
}

function Row({ k, v, accent }) {
  return (
    <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', padding:'4px 0' }}>
      <span style={{ color:'var(--bp-ink-3)' }}>{k}</span>
      <span style={{ color: accent || 'var(--bp-ink)', fontWeight: 500 }}>{v}</span>
    </div>
  );
}

const primaryBtn = {
  appearance:'none', border: 0, cursor:'pointer',
  width:'100%', padding:'12px 16px', borderRadius: 12,
  background:'var(--bp-grad)', color:'#fff',
  fontSize: 13.5, fontWeight: 600,
  display:'flex', alignItems:'center', justifyContent:'center', gap: 8,
  boxShadow:'0 8px 18px rgba(80,50,180,0.25)',
};
const secondaryBtn = {
  appearance:'none', cursor:'pointer',
  width:'100%', padding:'10px 16px', borderRadius: 12,
  background:'var(--bp-surface)', color:'var(--bp-ink-2)',
  border:'1px solid var(--bp-line)',
  fontSize: 13, fontWeight: 500,
  display:'flex', alignItems:'center', justifyContent:'center', gap: 8,
};

// ─── Timeline page (org-wide) ──────────────────────────────
function TeacherTimelinePage({ t, lang, reports, goToIssue }) {
  // Flatten all timeline events across reports, sort desc
  const events = [];
  reports.forEach(r => {
    r.timeline.forEach(([type, ts, actor, note]) => {
      events.push({ type, ts, actor, note, report: r });
    });
  });
  events.sort((a, b) => new Date(b.ts) - new Date(a.ts));

  return (
    <div style={{ padding:'24px 28px 40px' }}>
      <div className="bp-card" style={{ padding: 28 }}>
        <div style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between', marginBottom: 4 }}>
          <div style={{ fontSize: 16, fontWeight: 600 }}>{t.timeline}</div>
          <div style={{ fontSize: 12, color:'var(--bp-ink-3)' }}>{events.length} {lang === 'th' ? 'รายการ' : 'events'}</div>
        </div>
        <div style={{ fontSize: 12, color:'var(--bp-ink-3)', marginBottom: 20 }}>
          {lang === 'th' ? 'ประวัติการดำเนินการรวมจากทุกเรื่องแจ้ง' : 'Combined activity history across all reports'}
        </div>

        <div style={{ position:'relative', paddingLeft: 30 }}>
          <div style={{
            position:'absolute', left: 11, top: 6, bottom: 6,
            width: 2, background:'linear-gradient(to bottom, var(--bp-blue), var(--bp-violet) 60%, oklch(0.92 0.02 270))',
            opacity: 0.4, borderRadius: 2,
          }}/>
          {events.slice(0, 30).map((e, i) => {
            const evMap = {
              submitted: { icon:'plus', color:'var(--bp-blue)', th:'เรื่องใหม่จากนักเรียน', en:'New report submitted' },
              'in-progress': { icon:'clock', color:'oklch(0.55 0.18 70)', th:'รับเรื่องและเริ่มแก้ไข', en:'Started working' },
              progress: { icon:'chart', color:'oklch(0.56 0.20 265)', th:'อัปเดตความคืบหน้า', en:'Progress update' },
              resolved: { icon:'check', color:'oklch(0.55 0.16 155)', th:'แก้ไขเรียบร้อย', en:'Resolved' },
            };
            const m = evMap[e.type];
            const cat = CAT_BY_ID[e.report.category];
            return (
              <div key={i} style={{ position:'relative', paddingBottom: 20 }}>
                <div style={{
                  position:'absolute', left: -29, top: 0,
                  width: 24, height: 24, borderRadius:'50%',
                  background:'var(--bp-surface)', border:`2px solid ${m.color}`, color: m.color,
                  display:'flex', alignItems:'center', justifyContent:'center',
                  boxShadow:'0 2px 6px rgba(0,0,0,0.06)',
                }}>
                  <Icon name={m.icon} size={11} strokeWidth={2.3}/>
                </div>
                <button onClick={() => goToIssue(e.report.id)} style={{
                  appearance:'none', border:0, background:'transparent', cursor:'pointer',
                  textAlign:'left', display:'flex', flexDirection:'column', gap: 4, padding: 0,
                }}>
                  <div style={{ display:'flex', alignItems:'center', gap: 8, flexWrap:'wrap' }}>
                    <div style={{ fontSize: 13, fontWeight: 600, color:'var(--bp-ink)' }}>{m[lang]}</div>
                    <CategoryChip cat={cat} lang={lang}/>
                    <span className="font-mono" style={{ fontSize: 10.5, color:'var(--bp-ink-3)' }}>{e.report.id}</span>
                  </div>
                  <div style={{ fontSize: 12, color:'var(--bp-ink-2)' }}>
                    {lang === 'th' ? e.report.title : e.report.titleEn}
                  </div>
                  <div style={{ fontSize: 11, color:'var(--bp-ink-3)' }}>
                    {fullDateTime(e.ts, lang)} · {e.actor}
                  </div>
                  {e.note && (
                    <div style={{
                      marginTop: 4, padding:'8px 12px', borderRadius: 9,
                      background:'var(--bp-soft)', fontSize: 12, color:'var(--bp-ink-2)', lineHeight: 1.5,
                    }}>{e.note}</div>
                  )}
                </button>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

// ─── Settings page (placeholder light) ─────────────────────
function TeacherSettings({ t, lang, theme, setTheme, setLang, teacher, setTeacher }) {
  const [editingName, setEditingName] = useStateT(false);
  const [nameDraft, setNameDraft] = useStateT(teacher.name);
  const [showPwModal, setShowPwModal] = useStateT(false);
  const [showUserModal, setShowUserModal] = useStateT(false);
  const [showFeedback, setShowFeedback] = useStateT(false);

  function saveName() {
    const newName = nameDraft.trim();
    if (newName) {
      setTeacher({ ...teacher, name: newName });
      sbUpdateDisplayName(newName).catch(() => {});
    }
    setEditingName(false);
  }

  const L = lang === 'th' ? {
    profile: 'โปรไฟล์',
    profileSub: 'จัดการข้อมูลและตั้งค่าการใช้งานของคุณ',
    nameLabel: 'ชื่อที่แสดง',
    edit: 'แก้ไข',
    save: 'บันทึก',
    cancel: 'ยกเลิก',
    changePw: 'เปลี่ยนรหัสผ่าน',
    changePwSub: 'ปรับปรุงรหัสผ่านเป็นประจำเพื่อความปลอดภัย',
    changeUser: 'เปลี่ยนรหัสประจำตัว',
    changeUserSub: 'แก้ไข username ที่ใช้เข้าสู่ระบบ',
    feedback: 'ติชม / แก้ไขเว็บไซต์',
    feedbackSub: 'แจ้งปัญหาหรือเสนอแนะการปรับปรุงระบบ',
    appearance: 'การแสดงผล',
    theme: 'ธีม',
    light: 'สว่าง',
    dark: 'มืด',
    language: 'ภาษา',
    accountSettings: 'การตั้งค่าบัญชี',
    notifications: 'การแจ้งเตือน',
    role: 'ตำแหน่ง',
    employeeId: 'รหัสบุคลากร',
    department: 'หน่วยงาน',
  } : {
    profile: 'Profile',
    profileSub: 'Manage your account and preferences',
    nameLabel: 'Display name',
    edit: 'Edit',
    save: 'Save',
    cancel: 'Cancel',
    changePw: 'Change password',
    changePwSub: 'Update your password regularly for security',
    changeUser: 'Change username',
    changeUserSub: 'Edit the username you use to sign in',
    feedback: 'Feedback / Improve site',
    feedbackSub: 'Report a problem or suggest a system improvement',
    appearance: 'Appearance',
    theme: 'Theme',
    light: 'Light',
    dark: 'Dark',
    language: 'Language',
    accountSettings: 'Account settings',
    notifications: 'Notifications',
    role: 'Role',
    employeeId: 'Staff ID',
    department: 'Department',
  };

  return (
    <div style={{ padding:'24px 28px 40px', display:'flex', flexDirection:'column', gap: 16 }}>
      {/* Hero profile card */}
      <div className="bp-card" style={{ padding: 0, overflow:'hidden' }}>
        <div style={{
          background:'var(--bp-grad)', color:'#fff',
          padding:'28px 28px 70px', position:'relative', overflow:'hidden',
        }}>
          <div style={{ position:'absolute', right:-40, top:-30, width:200, height:200, borderRadius:'50%',
            background:'radial-gradient(circle, rgba(255,255,255,0.22), transparent 70%)' }}/>
          <div style={{ position:'absolute', left:-50, bottom:-60, width:200, height:200, borderRadius:'50%',
            background:'radial-gradient(circle, rgba(255,255,255,0.14), transparent 70%)' }}/>
          <div style={{ fontSize: 12, opacity: 0.88, fontWeight: 500, position:'relative' }}>{L.profile}</div>
          <div style={{ fontSize: 22, fontWeight: 700, marginTop: 4, letterSpacing:'-0.01em', position:'relative' }}>{L.profileSub}</div>
        </div>

        <div style={{
          padding:'0 28px 22px', marginTop: -50, position:'relative',
          display:'flex', gap: 18, alignItems:'flex-end', flexWrap:'wrap',
        }}>
          {/* Avatar */}
          <AvatarUpload
            photo={teacher.photo}
            name={teacher.name}
            onChange={(p) => { setTeacher({ ...teacher, photo: p }); sbUpdateAvatar(p).catch(() => {}); }}
            size={96}
            ring="var(--bp-surface)"
          />

          <div style={{ flex: 1, minWidth: 240, paddingBottom: 4 }}>
            {editingName ? (
              <div style={{ display:'flex', flexDirection:'column', gap: 8 }}>
                <input
                  autoFocus value={nameDraft}
                  onChange={e => setNameDraft(e.target.value)}
                  onKeyDown={e => { if (e.key === 'Enter') saveName(); if (e.key === 'Escape') setEditingName(false); }}
                  style={{
                    appearance:'none', border:'1px solid var(--bp-line)',
                    background:'var(--bp-surface)', color:'var(--bp-ink)',
                    fontSize: 22, fontWeight: 600, fontFamily:'inherit',
                    padding:'8px 12px', borderRadius: 10, outline:'none',
                    maxWidth: 360,
                  }}/>
                <div style={{ display:'flex', gap: 6 }}>
                  <button onClick={saveName} style={settingsBtn(true)}>{L.save}</button>
                  <button onClick={() => { setEditingName(false); setNameDraft(teacher.name); }} style={settingsBtn(false)}>{L.cancel}</button>
                </div>
              </div>
            ) : (
              <>
                <div style={{ display:'flex', alignItems:'center', gap: 10, flexWrap:'wrap' }}>
                  <div style={{ fontSize: 22, fontWeight: 700, color:'var(--bp-ink)', letterSpacing:'-0.01em' }}>{teacher.name}</div>
                  <button onClick={() => setEditingName(true)} style={{
                    appearance:'none', cursor:'pointer',
                    padding:'4px 10px', borderRadius: 999,
                    border:'1px solid var(--bp-line)', background:'var(--bp-surface)',
                    color:'var(--bp-ink-2)', fontSize: 11.5, fontWeight: 500, fontFamily:'inherit',
                    display:'inline-flex', alignItems:'center', gap: 5,
                  }}>
                    <Icon name="edit" size={11}/> {L.edit}
                  </button>
                </div>
              </>
            )}
          </div>
        </div>
      </div>

      {/* Appearance card */}
      <div className="bp-card" style={{ padding: 22 }}>
        <div style={{ fontSize: 14, fontWeight: 600, color:'var(--bp-ink)' }}>{L.appearance}</div>

        <div style={{
          display:'grid', gridTemplateColumns:'1fr 1fr', gap: 14, marginTop: 14,
        }} className="bp-grid-photos">
          <PrefRow icon="sparkle" tint="var(--bp-violet)" label={L.theme}>
            <PrefSegmented value={theme} onChange={setTheme} options={[
              ['light', L.light, 'sparkle'],
              ['dark',  L.dark,  'eye'],
            ]}/>
          </PrefRow>
          <PrefRow icon="globe" tint="var(--bp-blue)" label={L.language}>
            <PrefSegmented value={lang} onChange={setLang} options={[
              ['th', 'ไทย', null],
              ['en', 'English', null],
            ]}/>
          </PrefRow>
        </div>
      </div>

      {/* Account settings card */}
      <div className="bp-card" style={{ padding: 22 }}>
        <div style={{ fontSize: 14, fontWeight: 600, color:'var(--bp-ink)' }}>{L.accountSettings}</div>
        <div style={{ display:'grid', gap: 10, marginTop: 14 }}>
          <AccountAction icon="user" tint="var(--bp-blue)" label={L.nameLabel}
            detail={teacher.name} onClick={() => setEditingName(true)} actionLabel={L.edit}/>
          <AccountAction icon="cog" tint="var(--bp-violet)" label={L.changePw}
            detail={L.changePwSub} onClick={() => setShowPwModal(true)} actionLabel={L.edit}/>
          <AccountAction icon="user" tint="var(--bp-blue)" label={L.changeUser}
            detail={L.changeUserSub} onClick={() => setShowUserModal(true)} actionLabel={L.edit}/>
          <AccountAction icon="sparkle" tint="oklch(0.62 0.18 325)" label={L.feedback}
            detail={L.feedbackSub} onClick={() => window.open('https://docs.google.com/forms/d/e/1FAIpQLSeZw2qxHID5krUdD53pM_tE9lF80IzCWCv1tmkzFk7gX1Ww5Q/viewform', '_blank', 'noopener,noreferrer')} actionLabel={lang === 'th' ? 'เปิด' : 'Open'}/>
        </div>
      </div>

      {showPwModal && (
        <ChangePasswordModal lang={lang} onClose={() => setShowPwModal(false)}/>
      )}
      {showUserModal && (
        <ChangeUsernameModal lang={lang} onClose={() => setShowUserModal(false)}/>
      )}
      {showFeedback && (
        <FeedbackModal lang={lang} onClose={() => setShowFeedback(false)}/>
      )}
    </div>
  );
}

function settingsBtn(primary) {
  return {
    appearance:'none', border:0, cursor:'pointer',
    background: primary ? 'var(--bp-grad)' : 'var(--bp-soft)',
    color: primary ? '#fff' : 'var(--bp-ink-2)',
    fontFamily:'inherit', fontSize: 12, fontWeight: 600,
    padding:'7px 16px', borderRadius: 9,
    boxShadow: primary ? '0 4px 10px rgba(80,50,180,0.22)' : 'none',
  };
}

function ProfileMeta({ label, value }) {
  return (
    <div>
      <div style={{ fontSize: 10.5, textTransform:'uppercase', letterSpacing:'0.06em', fontWeight: 600, color:'var(--bp-ink-3)' }}>{label}</div>
      <div style={{ fontSize: 13, color:'var(--bp-ink-2)', marginTop: 3, fontWeight: 500 }}>{value}</div>
    </div>
  );
}

function PrefRow({ icon, tint, label, children }) {
  return (
    <div style={{
      padding:'14px 16px', borderRadius: 12, background:'var(--bp-soft)',
      display:'flex', alignItems:'center', gap: 12, minWidth: 0,
    }}>
      <div style={{
        width: 34, height: 34, borderRadius: 10,
        background: tint + '1A', color: tint,
        display:'flex', alignItems:'center', justifyContent:'center', flexShrink: 0,
      }}><Icon name={icon} size={16}/></div>
      <div style={{ flex: 1, fontSize: 13.5, color:'var(--bp-ink)', fontWeight: 500 }}>{label}</div>
      {children}
    </div>
  );
}

function PrefSegmented({ value, onChange, options }) {
  return (
    <div style={{
      display:'inline-flex', background:'var(--bp-surface)',
      borderRadius: 10, padding: 3, gap: 2,
      border:'1px solid var(--bp-line)',
    }}>
      {options.map(([v, lab, icon]) => {
        const active = value === v;
        return (
          <button key={v} onClick={() => onChange(v)} style={{
            appearance:'none', border:0, cursor:'pointer',
            padding:'6px 12px', borderRadius: 8,
            background: active ? 'var(--bp-grad)' : 'transparent',
            color: active ? '#fff' : 'var(--bp-ink-3)',
            fontFamily:'inherit', fontSize: 12, fontWeight: 600,
            display:'inline-flex', alignItems:'center', gap: 5,
            transition:'background .12s ease, color .12s ease',
          }}>
            {icon && <Icon name={icon} size={12} stroke={active ? '#fff' : 'currentColor'}/>}
            {lab}
          </button>
        );
      })}
    </div>
  );
}

function AccountAction({ icon, tint, label, detail, actionLabel, onClick }) {
  return (
    <div style={{
      display:'flex', alignItems:'center', gap: 12,
      padding:'14px 16px', borderRadius: 12, background:'var(--bp-soft)',
    }}>
      <div style={{
        width: 34, height: 34, borderRadius: 10,
        background: tint + '1A', color: tint,
        display:'flex', alignItems:'center', justifyContent:'center', flexShrink: 0,
      }}><Icon name={icon} size={16}/></div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13.5, fontWeight: 500, color:'var(--bp-ink)' }}>{label}</div>
        {detail && (
          <div style={{ fontSize: 11.5, color:'var(--bp-ink-3)', marginTop: 2,
            whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis',
          }}>{detail}</div>
        )}
      </div>
      <button onClick={onClick} style={{
        appearance:'none', cursor:'pointer',
        padding:'6px 14px', borderRadius: 999,
        background:'var(--bp-surface)', border:'1px solid var(--bp-line)',
        color:'var(--bp-ink-2)', fontSize: 11.5, fontWeight: 500, fontFamily:'inherit',
        display:'inline-flex', alignItems:'center', gap: 5,
      }}>
        <Icon name="edit" size={11}/> {actionLabel}
      </button>
    </div>
  );
}

function ToggleSwitch({ initial }) {
  const [on, setOn] = useStateT(initial);
  return (
    <button onClick={() => setOn(!on)} style={{
      appearance:'none', border:0, cursor:'pointer', padding: 0,
      width: 40, height: 24, borderRadius: 999,
      background: on ? 'var(--bp-grad)' : 'oklch(0.78 0.02 270)',
      position:'relative', transition:'background .2s',
    }}>
      <div style={{
        position:'absolute', top: 3, left: on ? 19 : 3,
        width: 18, height: 18, borderRadius:'50%', background:'#fff',
        boxShadow:'0 2px 4px rgba(0,0,0,0.18)', transition:'left .2s',
      }}/>
    </button>
  );
}

// ─── Teacher App container ─────────────────────────────────
function TeacherApp({ lang, setLang, reports, setReports, onSwitchRole, theme, setTheme, initialUser }) {
  const t = T[lang];
  const [page, setPage] = useStateT('dashboard');
  const [prevPage, setPrevPage] = useStateT('issues');
  const [activeIssueId, setActiveIssueId] = useStateT(null);
  const [menuOpen, setMenuOpen] = useStateT(false);
  const [teacher, setTeacher] = useStateT({
    name: initialUser?.name || 'ครูประภาส สุวรรณ',
    title: lang === 'th' ? 'หัวหน้าฝ่ายอาคารสถานที่' : 'Head of Facilities',
    dept: lang === 'th' ? 'กลุ่มบริหารทั่วไป' : 'General Affairs',
    id: initialUser?.id || 'BD-0241',
    photo: initialUser?.photo || null,
  });

  function goToIssue(id) {
    setActiveIssueId(id);
    setPrevPage(page === 'detail' ? prevPage : page);
    setPage('detail');
  }
  function updateReport(id, updater) {
    setReports(prev => prev.map(r => r.id === id ? updater(r) : r)); // optimistic
    const updated = updater(reports.find(r => r.id === id));
    sbUpdateReport(id, updated).catch(async () => {
      const fresh = await sbFetchReports().catch(() => null);
      if (fresh) setReports(fresh);
    });
  }

  const pendingCount = reports.filter(r => r.status === 'pending').length;
  const activeReport = reports.find(r => r.id === activeIssueId);

  const titles = {
    dashboard: { title: t.dashboard, sub: lang === 'th' ? 'ภาพรวมการรายงานทั่วโรงเรียน' : 'School-wide reporting overview' },
    issues: { title: t.issues, sub: lang === 'th' ? `รายการรับแจ้งทั้งหมด ${reports.length} เรื่อง` : `${reports.length} reports total` },
    detail: { title: activeReport ? activeReport.id : '', sub: activeReport ? (lang === 'th' ? activeReport.title : activeReport.titleEn) : '' },
    timeline: { title: t.timeline, sub: lang === 'th' ? 'ประวัติการแก้ไขย้อนหลัง' : 'Historical activity feed' },
    settings: { title: lang === 'th' ? 'โปรไฟล์' : 'Profile', sub: lang === 'th' ? 'จัดการข้อมูลและตั้งค่าการใช้งาน' : 'Account & preferences' },
  };

  return (
    <div className="bp-teacher-root" style={{ background:'var(--bp-canvas)' }}>
      <TeacherSidebar
        page={page === 'detail' ? 'issues' : page}
        setPage={setPage} t={t} lang={lang}
        pendingCount={pendingCount}
        open={menuOpen}
        onClose={() => setMenuOpen(false)}
        teacher={teacher}
      />
      <div
        className={`bp-sidebar-backdrop ${menuOpen ? 'open' : ''}`}
        onClick={() => setMenuOpen(false)}
      />
      <div className="bp-teacher-main">
        <TeacherTopBar
          title={titles[page]?.title || ''}
          subtitle={titles[page]?.sub}
          lang={lang} setLang={setLang}
          onSwitchRole={onSwitchRole}
          onMenuClick={() => setMenuOpen(true)}
          t={t}
          reports={reports}
          goToIssue={goToIssue}
        />
        <div className="bp-teacher-content">
          {page === 'dashboard' && (
            <TeacherDashboard t={t} lang={lang} reports={reports} goToIssue={goToIssue}/>
          )}
          {page === 'issues' && (
            <TeacherIssues t={t} lang={lang} reports={reports} goToIssue={goToIssue}/>
          )}
          {page === 'detail' && activeReport && (
            <TeacherDetail t={t} lang={lang} report={activeReport} goBack={() => setPage(prevPage)} prevPage={prevPage} updateReport={updateReport}/>
          )}
          {page === 'timeline' && (
            <TeacherTimelinePage t={t} lang={lang} reports={reports} goToIssue={goToIssue}/>
          )}
          {page === 'settings' && (
            <TeacherSettings t={t} lang={lang} setLang={setLang} theme={theme} setTheme={setTheme} teacher={teacher} setTeacher={setTeacher}/>
          )}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { TeacherApp });
