// Social — teleprompter & small helpers (split from social.jsx).
// SfTeleprompter, PromControl, SfLoading, SfEmpty. Owns window.SocialView export.


// ── Teleprompter (auto-scroll, mirror, fullscreen, touch-friendly) ──
const SF_PROMPT_KEY = 'sf_prompter_text';
function SfTeleprompter({ text, onText, onToast }) {
  const [draft, setDraft] = useState(text || (() => { try { return localStorage.getItem(SF_PROMPT_KEY) || ''; } catch { return ''; } })());
  const [playing, setPlaying] = useState(false);
  const [speed, setSpeed] = useState(40);        // px per second
  const [fontSize, setFontSize] = useState(44);
  const [mirror, setMirror] = useState(false);   // flip horizontally (for glass rigs)
  const [align, setAlign] = useState('center');
  const [countdown, setCountdown] = useState(0);
  const [running, setRunning] = useState(false); // teleprompter open (vs editor)
  const scrollRef = React.useRef(null);
  const rafRef = React.useRef(0);
  const lastTsRef = React.useRef(0);

  // Camera + recording
  const [camOn, setCamOn] = useState(false);
  const [facing, setFacing] = useState('user');     // 'user' (front) | 'environment' (back)
  const [recording, setRecording] = useState(false);
  const [recSec, setRecSec] = useState(0);
  const [videoUrl, setVideoUrl] = useState('');
  const videoRef = React.useRef(null);
  const streamRef = React.useRef(null);
  const recRef = React.useRef(null);
  const chunksRef = React.useRef([]);
  const recTimerRef = React.useRef(0);
  const recBlobRef = React.useRef(null);

  // Reel export kit (subtitles + caption) built from the recorded clip
  const [kit, setKit] = useState(null);   // { srt, caption, hashtags }
  const [kitBusy, setKitBusy] = useState('');

  // When a script is pushed from the AI Studio, load it into the editor.
  useEffect(() => { if (text) { setDraft(text); setRunning(false); setPlaying(false); } }, [text]);
  useEffect(() => { try { localStorage.setItem(SF_PROMPT_KEY, draft); } catch {} }, [draft]);

  const stopStream = () => {
    if (streamRef.current) { streamRef.current.getTracks().forEach(t => t.stop()); streamRef.current = null; }
  };
  const startCam = async (face = facing) => {
    if (!navigator.mediaDevices?.getUserMedia) { onToast('อุปกรณ์นี้ไม่รองรับกล้อง'); return; }
    try {
      stopStream();
      const stream = await navigator.mediaDevices.getUserMedia({
        video: { facingMode: face, width: { ideal: 1280 }, height: { ideal: 720 } },
        audio: true,
      });
      streamRef.current = stream;
      if (videoRef.current) { videoRef.current.srcObject = stream; videoRef.current.play().catch(() => {}); }
      setCamOn(true);
    } catch (e) { onToast('เปิดกล้องไม่ได้: ' + (e.message || 'ปฏิเสธสิทธิ์')); }
  };
  const stopCam = () => { stopStream(); setCamOn(false); if (videoRef.current) videoRef.current.srcObject = null; };
  const flipCam = async () => { const next = facing === 'user' ? 'environment' : 'user'; setFacing(next); if (camOn) await startCam(next); };

  const startRec = () => {
    const stream = streamRef.current;
    if (!stream) { onToast('เปิดกล้องก่อนเริ่มอัด'); return; }
    chunksRef.current = [];
    const mime = ['video/mp4;codecs=h264,aac', 'video/webm;codecs=vp9,opus', 'video/webm'].find(m => window.MediaRecorder && MediaRecorder.isTypeSupported(m)) || '';
    let rec; try { rec = new MediaRecorder(stream, mime ? { mimeType: mime } : undefined); } catch { onToast('อุปกรณ์นี้อัดวิดีโอไม่ได้'); return; }
    rec.ondataavailable = e => { if (e.data.size) chunksRef.current.push(e.data); };
    rec.onstop = () => {
      const blob = new Blob(chunksRef.current, { type: chunksRef.current[0]?.type || 'video/webm' });
      recBlobRef.current = blob;
      setKit(null);
      setVideoUrl(u => { if (u) URL.revokeObjectURL(u); return URL.createObjectURL(blob); });
    };
    rec.start();
    recRef.current = rec; setRecording(true); setRecSec(0);
    recTimerRef.current = setInterval(() => setRecSec(s => s + 1), 1000);
    // also auto-start the scroll
    if (scrollRef.current) scrollRef.current.scrollTop = 0;
    setPlaying(true);
  };
  const stopRec = () => {
    if (recRef.current && recRef.current.state !== 'inactive') recRef.current.stop();
    clearInterval(recTimerRef.current); setRecording(false); setPlaying(false);
  };
  // cleanup on leaving the stage / unmount
  useEffect(() => () => { stopStream(); clearInterval(recTimerRef.current); }, []);
  useEffect(() => { if (!running) { stopCam(); if (recording) stopRec(); } }, [running]);

  const _dl = (blob, name) => { const u = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = u; a.download = name; a.click(); setTimeout(() => URL.revokeObjectURL(u), 4000); };
  // Build the Reel export kit: SRT subtitles (Whisper) + caption/hashtags (Claude).
  const buildKit = async () => {
    const blob = recBlobRef.current;
    if (!blob) { onToast('อัดคลิปก่อน'); return; }
    setKitBusy('sub');
    let srt = '';
    try {
      const fd = new FormData(); fd.append('file', blob, 'reel.webm');
      const d = await _sfTranscribe(fd);
      srt = d?.srt || '';
      if (!srt && d?.transcript) srt = '1\n00:00:00,000 --> 00:00:30,000\n' + d.transcript + '\n';
    } catch (e) { onToast('ถอดซับไม่ได้: ' + (e.message || '')); }
    // caption + hashtags from the script we just read
    setKitBusy('cap');
    let caption = '', hashtags = [];
    try {
      const d = await _sfAskJSON(`จากสคริปต์รีลนี้:\n"""${draft.slice(0, 1500)}"""\nเขียนแคปชัน IG/TikTok ที่ดึงดูด 2-3 บรรทัด + แฮชแท็กที่เกี่ยวข้อง 6-10 อัน. JSON {"caption":"","hashtags":[""]}`);
      caption = d.caption || ''; hashtags = d.hashtags || [];
    } catch {
      caption = (draft.split('\n').filter(Boolean)[0] || '').slice(0, 90) + '\n\n💬 คอมเมนต์ "สนใจ" รับรายละเอียด';
      hashtags = ['#รีล', '#คอนเทนต์', '#ธุรกิจ', '#การตลาด'];
    }
    setKit({ srt, caption, hashtags });
    setKitBusy('');
    onToast('สร้างชุดเตรียมลง Reel แล้ว');
  };
  const dlVideo = () => { if (recBlobRef.current) _dl(recBlobRef.current, `reel-${Date.now()}.webm`); };
  const dlSrt = () => { if (kit?.srt) _dl(new Blob([kit.srt], { type: 'text/plain' }), `reel-subtitles-${Date.now()}.srt`); };
  const copyCaption = () => { const t = (kit?.caption || '') + '\n\n' + (kit?.hashtags || []).join(' '); try { navigator.clipboard.writeText(t); } catch {} onToast('คัดลอกแคปชันแล้ว'); };

  // Auto-scroll loop (rAF, framerate-independent via timestamp delta).
  useEffect(() => {
    if (!playing || !running) { cancelAnimationFrame(rafRef.current); lastTsRef.current = 0; return; }
    const step = (ts) => {
      const el = scrollRef.current;
      if (el) {
        if (lastTsRef.current) { el.scrollTop += (speed * (ts - lastTsRef.current)) / 1000; }
        lastTsRef.current = ts;
        if (el.scrollTop + el.clientHeight >= el.scrollHeight - 2) { setPlaying(false); return; }
      }
      rafRef.current = requestAnimationFrame(step);
    };
    rafRef.current = requestAnimationFrame(step);
    return () => cancelAnimationFrame(rafRef.current);
  }, [playing, running, speed]);

  const start = () => {
    if (!draft.trim()) { onToast('ใส่สคริปต์ก่อน'); return; }
    setRunning(true); setPlaying(false);
    if (scrollRef.current) scrollRef.current.scrollTop = 0;
    // 3-2-1 countdown then play
    let n = 3; setCountdown(n);
    const tick = () => { n -= 1; setCountdown(n); if (n > 0) setTimeout(tick, 800); else { setCountdown(0); setPlaying(true); } };
    setTimeout(tick, 800);
  };
  const resetScroll = () => { if (scrollRef.current) scrollRef.current.scrollTop = 0; setPlaying(false); };
  const enterFullscreen = () => { const el = document.getElementById('sf-prompter-stage'); if (el?.requestFullscreen) el.requestFullscreen().catch(() => {}); };

  const wordCount = draft.trim() ? draft.trim().split(/\s+/).length : 0;
  const estSec = Math.round((wordCount / 130) * 60); // ~130 wpm reading pace

  // ── Editor view ──
  if (!running) {
    return (
      <div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
        <div className="lg:col-span-2">
          <Card pad={false} title={<div><div className="text-sm font-semibold text-ink-900">สคริปต์</div><div className="text-[11px] text-ink-400 mt-0.5">{wordCount} คำ · อ่านประมาณ {estSec >= 60 ? Math.floor(estSec / 60) + ' นาที ' : ''}{estSec % 60} วิ</div></div>}
            action={<button onClick={() => { setDraft(''); onText && onText(''); }} className="text-xs text-rose-500 hover:text-rose-700">ล้าง</button>}>
            <div className="p-4">
              <textarea value={draft} onChange={e => { setDraft(e.target.value); onText && onText(e.target.value); }} rows={14}
                className="w-full text-[15px] leading-relaxed border border-ink-200 rounded-xl p-3 outline-none focus:border-brand-500 resize-none"
                placeholder="วางหรือพิมพ์สคริปต์ที่นี่ — หรือกด 'ส่งไปเทเลพรอมป์เตอร์' จากผู้ช่วยคิดคอนเทนต์" />
            </div>
          </Card>
        </div>
        <div className="space-y-4">
          <Card title="ตั้งค่าการเล่น">
            <div className="space-y-3 mt-1">
              <PromControl label={`ความเร็ว · ${speed}`}><input type="range" min="10" max="150" value={speed} onChange={e => setSpeed(+e.target.value)} className="w-full" /></PromControl>
              <PromControl label={`ขนาดตัวอักษร · ${fontSize}px`}><input type="range" min="24" max="96" value={fontSize} onChange={e => setFontSize(+e.target.value)} className="w-full" /></PromControl>
              <div className="flex items-center justify-between">
                <span className="text-[12px] text-ink-600">กระจกสะท้อน (mirror)</span>
                <button onClick={() => setMirror(m => !m)} className={`relative w-10 h-6 rounded-full transition-colors ${mirror ? 'bg-brand-500' : 'bg-ink-300'}`}><span className={`absolute top-0.5 left-0.5 w-5 h-5 rounded-full bg-white shadow transition-transform ${mirror ? 'translate-x-4' : ''}`} /></button>
              </div>
              <div className="flex items-center justify-between">
                <span className="text-[12px] text-ink-600">จัดวางข้อความ</span>
                <div className="flex bg-ink-100 rounded-lg p-0.5">{[['left','ซ้าย'],['center','กลาง']].map(([v,l]) => <button key={v} onClick={() => setAlign(v)} className={_segBtn(align === v)}>{l}</button>)}</div>
              </div>
            </div>
          </Card>
          <button onClick={start} className="w-full h-12 rounded-xl bg-gradient-to-r from-purple-600 to-brand-600 text-white font-bold text-[15px] inline-flex items-center justify-center gap-2">▶ เริ่มเทเลพรอมป์เตอร์</button>
          <div className="text-[10px] text-ink-400 text-center leading-relaxed">เคล็ดลับ: ในจอเล่นมีปุ่ม 📷 เปิดกล้อง + ⏺ อัดวิดีโอได้เลย · แตะที่ข้อความเพื่อหยุด/เล่น · บนมือถือกดเต็มจอ</div>
        </div>
      </div>
    );
  }

  // ── Teleprompter stage ──
  const fmtRec = (s) => `${String(Math.floor(s / 60)).padStart(2, '0')}:${String(s % 60).padStart(2, '0')}`;
  return (
    <div id="sf-prompter-stage" className="relative bg-black rounded-2xl overflow-hidden" style={{ height: '72vh' }}>
      {/* camera background (mirror the front cam so it looks natural) */}
      <video ref={videoRef} muted playsInline
        className="absolute inset-0 w-full h-full object-cover z-0"
        style={{ display: camOn ? 'block' : 'none', transform: facing === 'user' ? 'scaleX(-1)' : 'none' }} />
      {/* dim overlay so text stays readable over video */}
      {camOn && <div className="absolute inset-0 bg-black/45 z-[1] pointer-events-none" />}

      {/* recording indicator */}
      {recording && (
        <div className="absolute top-3 left-3 z-20 flex items-center gap-1.5 bg-black/50 rounded-full px-2.5 py-1 backdrop-blur">
          <span className="w-2.5 h-2.5 rounded-full bg-red-500 animate-pulse" />
          <span className="text-white text-xs font-semibold num">{fmtRec(recSec)}</span>
        </div>
      )}

      {/* reading guide line */}
      <div className="absolute left-0 right-0 top-1/3 h-0.5 bg-brand-500/40 z-10 pointer-events-none" />
      <div className="absolute left-2 top-1/3 -translate-y-1/2 text-brand-500 z-10 pointer-events-none">▶</div>

      <div ref={scrollRef}
        onClick={() => setPlaying(p => !p)}
        className="relative h-full overflow-y-auto px-8 py-[33vh] scroll-thin cursor-pointer z-[2]"
        style={{ transform: mirror ? 'scaleX(-1)' : 'none' }}>
        <div className="text-white font-bold whitespace-pre-wrap mx-auto max-w-3xl"
          style={{ fontSize, lineHeight: 1.5, textAlign: align, textShadow: camOn ? '0 2px 12px rgba(0,0,0,0.9)' : 'none' }}>
          {draft}
        </div>
      </div>

      {/* countdown overlay */}
      {countdown > 0 && (
        <div className="absolute inset-0 bg-black/70 flex items-center justify-center z-20">
          <div className="text-white font-bold" style={{ fontSize: 120 }}>{countdown}</div>
        </div>
      )}

      {/* control bar */}
      <div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/90 to-transparent px-3 py-3 flex items-center gap-2 z-20 flex-wrap">
        <button onClick={() => setPlaying(p => !p)} className="px-3 h-9 rounded-lg bg-white/15 text-white text-sm font-semibold backdrop-blur">{playing ? '⏸ หยุด' : '▶ เล่น'}</button>
        <button onClick={resetScroll} className="px-3 h-9 rounded-lg bg-white/15 text-white text-sm backdrop-blur">↺ เริ่มใหม่</button>
        <div className="flex items-center gap-1.5 text-white/80 text-xs bg-white/10 rounded-lg px-2 h-9 backdrop-blur">
          <button onClick={() => setSpeed(s => Math.max(10, s - 10))} className="px-1 text-lg leading-none">−</button>
          <span className="num w-14 text-center">เร็ว {speed}</span>
          <button onClick={() => setSpeed(s => Math.min(150, s + 10))} className="px-1 text-lg leading-none">＋</button>
        </div>
        <div className="flex items-center gap-1.5 text-white/80 text-xs bg-white/10 rounded-lg px-2 h-9 backdrop-blur">
          <button onClick={() => setFontSize(s => Math.max(24, s - 4))} className="px-1 text-lg leading-none">A−</button>
          <span className="num w-10 text-center">{fontSize}</span>
          <button onClick={() => setFontSize(s => Math.min(96, s + 4))} className="px-1 text-lg leading-none">A＋</button>
        </div>
        <button onClick={() => setMirror(m => !m)} className={`px-3 h-9 rounded-lg text-white text-sm backdrop-blur ${mirror ? 'bg-brand-500' : 'bg-white/15'}`}>🪞</button>

        {/* Camera + recording */}
        {!camOn
          ? <button onClick={() => startCam()} className="px-3 h-9 rounded-lg bg-white/15 text-white text-sm backdrop-blur">📷 เปิดกล้อง</button>
          : <>
              {!recording
                ? <button onClick={startRec} className="px-3 h-9 rounded-lg bg-red-600 text-white text-sm font-semibold">⏺ อัด</button>
                : <button onClick={stopRec} className="px-3 h-9 rounded-lg bg-white text-red-600 text-sm font-bold">⏹ หยุดอัด</button>}
              <button onClick={flipCam} title="สลับกล้อง" className="px-3 h-9 rounded-lg bg-white/15 text-white text-sm backdrop-blur">🔄</button>
              {!recording && <button onClick={stopCam} className="px-3 h-9 rounded-lg bg-white/15 text-white text-sm backdrop-blur">ปิดกล้อง</button>}
            </>}
        {videoUrl && !recording && (
          <button onClick={() => { setKit(k => k || 'open'); buildKit(); }} disabled={!!kitBusy} className="px-3 h-9 rounded-lg bg-emerald-500 text-white text-sm font-semibold inline-flex items-center disabled:opacity-60">{kitBusy ? '⏳ กำลังเตรียม…' : '🎬 เตรียมลง Reel'}</button>
        )}

        <button onClick={enterFullscreen} className="px-3 h-9 rounded-lg bg-white/15 text-white text-sm backdrop-blur">⛶ เต็มจอ</button>
        <button onClick={() => { setRunning(false); setPlaying(false); }} className="px-3 h-9 rounded-lg bg-white/15 text-white text-sm backdrop-blur ml-auto">✎ แก้สคริปต์</button>
      </div>

      {/* recorded clip thumbnail preview (small, on-stage) */}
      {videoUrl && !recording && !(kit && typeof kit === 'object') && (
        <div className="absolute bottom-16 right-3 z-20 w-36 rounded-lg overflow-hidden border-2 border-white/40 shadow-lift bg-black">
          <video src={videoUrl} controls className="w-full" />
        </div>
      )}

      {/* Reel export kit drawer */}
      {kit && typeof kit === 'object' && (
        <div className="absolute inset-0 z-30 bg-black/80 backdrop-blur-sm overflow-y-auto p-4 sm:p-6">
          <div className="max-w-lg mx-auto bg-white rounded-2xl overflow-hidden">
            <div className="px-4 py-3 border-b border-ink-100 flex items-center justify-between">
              <div className="text-sm font-bold text-ink-900">🎬 เตรียมลง Reel</div>
              <button onClick={() => setKit(null)} className="text-ink-400 hover:text-ink-700 text-lg leading-none">✕</button>
            </div>
            <div className="p-4 space-y-3">
              <video src={videoUrl} controls className="w-full rounded-lg bg-black" style={{ maxHeight: 220 }} />

              <div className="grid grid-cols-2 gap-2">
                <button onClick={dlVideo} className="h-10 rounded-lg bg-ink-900 text-white text-[13px] font-semibold">⬇︎ ดาวน์โหลดคลิป</button>
                <button onClick={dlSrt} disabled={!kit.srt} className="h-10 rounded-lg bg-brand-600 text-white text-[13px] font-semibold disabled:opacity-50">💬 ดาวน์โหลดซับ (.srt)</button>
              </div>

              {kit.caption && (
                <div className="rounded-lg border border-ink-100 p-3">
                  <div className="flex items-center justify-between mb-1">
                    <span className="text-[11px] font-bold text-ink-400">CAPTION</span>
                    <button onClick={copyCaption} className="text-[11px] font-semibold text-brand-600">📋 คัดลอก</button>
                  </div>
                  <div className="text-[13px] text-ink-800 whitespace-pre-wrap leading-relaxed">{kit.caption}</div>
                  <div className="flex flex-wrap gap-1 mt-2">{(kit.hashtags || []).map((h, i) => <span key={i} className="text-[11px] text-brand-600">{h}</span>)}</div>
                </div>
              )}

              <div className="rounded-lg bg-ink-50 p-3">
                <div className="text-[12px] font-bold text-ink-700 mb-1.5">📱 ขั้นตอนตัดต่อใน CapCut</div>
                <ol className="text-[12px] text-ink-600 space-y-1 list-decimal list-inside leading-relaxed">
                  <li>เปิด CapCut → New Project → เลือกคลิปที่ดาวน์โหลด</li>
                  <li>ตั้งสัดส่วน <b>9:16</b> (Format) สำหรับ Reel/TikTok</li>
                  <li>แตะ <b>Captions → Import</b> ลากไฟล์ <b>.srt</b> เข้าไป (ซับขึ้นอัตโนมัติ)</li>
                  <li>ตัดหัว-ท้าย, ใส่เพลง/เอฟเฟกต์, ปรับสไตล์ตัวอักษร</li>
                  <li>Export <b>1080p · 30fps</b> → อัปโหลดพร้อมแคปชันด้านบน</li>
                </ol>
              </div>
              <div className="text-[10px] text-ink-400 text-center">ซับสร้างจาก Whisper · แคปชันจาก AI — ปรับแก้ได้ก่อนโพสต์</div>
            </div>
          </div>
        </div>
      )}
    </div>
  );

  // (kit panel rendered below the editor — see editor return)
}
function PromControl({ label, children }) {
  return <div><div className="text-[12px] text-ink-600 mb-1">{label}</div>{children}</div>;
}

function SfLoading({ label }) {
  return <Card><div className="py-10 flex flex-col items-center gap-3 text-ink-400">
    <svg className="w-7 h-7 animate-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M21 12a9 9 0 1 1-6.2-8.55" strokeLinecap="round" /></svg>
    <div className="text-sm">{label}</div></div></Card>;
}
function SfEmpty({ ico, ttl, sub }) {
  return <Card><div className="py-10 text-center"><div className="text-4xl mb-2">{ico}</div><div className="text-sm font-semibold text-ink-700">{ttl}</div><div className="text-[12px] text-ink-400 mt-1 max-w-xs mx-auto leading-relaxed">{sub}</div></div></Card>;
}

window.SocialView = SocialView;
