import { StrictMode, useCallback, useEffect, useRef, useState } from "react";
import { createRoot } from "react-dom/client";
import {
  Archive, ArrowLeft, Captions, Check, ChevronDown, ChevronLeft, ChevronRight,
  CircleHelp, Clock3, Copy, Download, Film, FolderOpen, Gauge, Grid2X2,
  Image, Layers3, LayoutPanelLeft, Link2, ListFilter, LoaderCircle, Lock,
  LogOut, Maximize2, Mic2, MoreHorizontal, MousePointer2, Music2,
  Pause, Play, Plus, Redo2, Scissors, Search, Settings2,
  Sparkles, Square, Text, Trash2, Undo2, Upload, UserRound, Volume2,
  WandSparkles, X, ZoomIn, ZoomOut
} from "lucide-react";
import "./styles.css";

type Scene = { id: string; start: number; end: number; speaker: string; score: number; title: string; transcript: string; tone: string };
type Clip = { id: string; sceneId: string; track: "video" | "audio" | "captions" | "effects"; start: number; end: number; label: string; color: string; muted?: boolean };
type Word = { text: string; start: number; end: number };
type Project = { id: string; title: string; status: "ready" | "processing" | "draft"; ratio: string; duration: string; edited: string; progress?: number; archived?: boolean };

const demoProjects: Project[] = [
  { id: "podcast-ai", title: "Masa Depan AI di Indonesia", status: "ready", ratio: "9:16", duration: "48:12", edited: "2 menit lalu" },
  { id: "founder-story", title: "Founder Story — Dari Nol", status: "processing", ratio: "9:16", duration: "1:12:04", edited: "18 menit lalu", progress: 68 },
  { id: "weekly-talk", title: "Weekly Creative Talk #12", status: "draft", ratio: "1:1", duration: "32:40", edited: "Kemarin" },
];

const scenes: Scene[] = [
  { id: "s1", start: 0, end: 8.4, speaker: "Person A", score: 96, title: "AI bukan pengganti manusia", transcript: "AI bukan pengganti manusia, tapi orang yang pakai AI akan menggantikan mereka yang tidak.", tone: "lime" },
  { id: "s2", start: 8.4, end: 15.9, speaker: "Person B", score: 91, title: "Peluang terbesar creator", transcript: "Ini peluang terbesar untuk creator Indonesia dalam lima tahun ke depan.", tone: "orange" },
  { id: "s3", start: 15.9, end: 23.6, speaker: "Person A", score: 87, title: "Mulai dari masalah", transcript: "Jangan mulai dari teknologinya. Mulai dari masalah yang benar-benar dirasakan.", tone: "purple" },
  { id: "s4", start: 23.6, end: 31.5, speaker: "Person B", score: 84, title: "Satu skill penting", transcript: "Skill paling penting sekarang adalah kemampuan bertanya dengan sangat jelas.", tone: "blue" },
  { id: "s5", start: 31.5, end: 40, speaker: "Person A", score: 78, title: "Eksekusi lebih cepat", transcript: "Dengan alat yang tepat, tim kecil bisa bergerak sepuluh kali lebih cepat.", tone: "pink" },
];
const words: Word[] = [
  { text: "AI", start: 0, end: .6 }, { text: "BUKAN", start: .6, end: 1.25 }, { text: "PENGGANTI", start: 1.25, end: 2.35 },
  { text: "MANUSIA", start: 2.35, end: 3.25 }, { text: "TAPI", start: 3.55, end: 4.1 }, { text: "ORANG", start: 4.1, end: 4.7 },
  { text: "YANG", start: 4.7, end: 5.15 }, { text: "PAKAI", start: 5.15, end: 5.8 }, { text: "AI", start: 5.8, end: 6.3 },
  { text: "AKAN MENANG.", start: 6.3, end: 8.1 }
];
const initialClips: Clip[] = [
  { id: "v1", sceneId: "s1", track: "video", start: 0, end: 8.4, label: "AI bukan pengganti manusia", color: "lime" },
  { id: "v2", sceneId: "s2", track: "video", start: 8.4, end: 15.9, label: "Peluang creator", color: "orange" },
  { id: "v3", sceneId: "s3", track: "video", start: 15.9, end: 23.6, label: "Mulai dari masalah", color: "purple" },
  { id: "a1", sceneId: "s1", track: "audio", start: 0, end: 23.6, label: "Source audio · Enhanced", color: "green" },
  { id: "c1", sceneId: "s1", track: "captions", start: 0, end: 8.1, label: "AI BUKAN PENGGANTI MANUSIA…", color: "yellow" },
  { id: "e1", sceneId: "s2", track: "effects", start: 8.4, end: 12.8, label: "Punch zoom", color: "blue" },
];

const fmt = (time: number) => `00:${String(Math.floor(time / 60)).padStart(2, "0")}:${String(Math.floor(time % 60)).padStart(2, "0")}.${String(Math.floor((time % 1) * 10))}`;
const shortTime = (time: number) => `${Math.floor(time / 60)}:${String(Math.floor(time % 60)).padStart(2, "0")}`;
const uid = () => Math.random().toString(36).slice(2, 9);

function Logo({ compact = false }: { compact?: boolean }) {
  return <div className="logo"><span className="logo-mark"><Scissors size={18}/></span>{!compact && <b>CLIP<span>MASBRO</span></b>}</div>;
}

function Login({ onLogin }: { onLogin: () => void }) {
  const [register, setRegister] = useState(false);
  const [loading, setLoading] = useState(false);
  const submit = (e: React.FormEvent) => { e.preventDefault(); setLoading(true); setTimeout(onLogin, 650); };
  return <main className="auth-page">
    <div className="auth-art"><Logo/><div className="hero-copy"><div className="eyebrow"><Sparkles size={14}/> AI VIDEO WORKSPACE</div><h1>Long video.<br/><em>Short impact.</em></h1><p>Temukan momen terbaik, edit seperti pro, dan publish lebih cepat.</p></div><div className="art-timeline"><span/><span/><span/></div></div>
    <section className="auth-card"><div className="mobile-logo"><Logo/></div><div><span className="muted kicker">MULAI SEKARANG</span><h2>{register ? "Buat akun baru" : "Selamat datang kembali"}</h2><p className="muted">{register ? "Buat short pertama dalam hitungan menit." : "Masuk ke workspace ClipMasbro kamu."}</p></div>
      <form onSubmit={submit}>{register && <label>Nama lengkap<input required placeholder="Nama kamu"/></label>}<label>Email<input required type="email" defaultValue="demo@clipmasbro.id"/></label><label>Password<input required type="password" defaultValue="demomasbro"/></label>{!register && <button type="button" className="link-btn">Lupa password?</button>}<button className="primary wide" disabled={loading}>{loading ? <LoaderCircle className="spin" size={18}/> : <Sparkles size={17}/>} {loading ? "Menyiapkan workspace…" : register ? "Buat akun" : "Masuk ke workspace"}</button></form>
      <p className="auth-switch">{register ? "Sudah punya akun?" : "Belum punya akun?"} <button onClick={() => setRegister(!register)}>{register ? "Masuk" : "Daftar gratis"}</button></p><div className="demo-note"><Check size={14}/> Mode demo · Tidak perlu layanan AI eksternal</div>
    </section>
  </main>;
}

function ProjectCard({ project, onOpen, onAction }: { project: Project; onOpen: () => void; onAction: (a: string) => void }) {
  const [menu, setMenu] = useState(false);
  return <article className="project-card"><button className={`thumb gradient-${project.id.length % 3}`} onClick={onOpen}><span className="ratio">{project.ratio}</span><div className="fake-face left"/><div className="fake-face right"/><div className="thumb-caption">IDE BESAR<br/><mark>DIMULAI DARI SINI</mark></div>{project.status === "processing" && <div className="processing-overlay"><LoaderCircle className="spin"/><b>Menganalisis {project.progress}%</b></div>}<span className="duration">{project.duration}</span></button>
    <div className="card-body"><div className="card-title"><div><h3>{project.title}</h3><p><Clock3 size={13}/>{project.edited}</p></div><button className="icon-btn" onClick={() => setMenu(!menu)} aria-label="Menu proyek"><MoreHorizontal size={18}/></button>{menu && <div className="pop-menu"><button onClick={() => {onOpen();setMenu(false)}}><FolderOpen/> Buka editor</button><button onClick={() => onAction("duplicate")}><Copy/> Duplikat</button><button onClick={() => onAction("archive")}><Archive/> Arsipkan</button><button className="danger" onClick={() => onAction("delete")}><Trash2/> Hapus</button></div>}</div><div className="status-line"><span className={`status ${project.status}`}>{project.status === "ready" ? "Siap edit" : project.status === "processing" ? `Processing · ${project.progress}%` : "Draft"}</span><span>{project.ratio}</span></div>{project.progress && <div className="mini-progress"><i style={{width:`${project.progress}%`}}/></div>}</div>
  </article>;
}

function Dashboard({ onOpen, onLogout }: { onOpen: (id: string) => void; onLogout: () => void }) {
  const [projects, setProjects] = useState(demoProjects);
  const [query, setQuery] = useState(""); const [filter, setFilter] = useState("Semua"); const [create, setCreate] = useState(false); const [profile, setProfile] = useState(false);
  const filtered = projects.filter(p => !p.archived && p.title.toLowerCase().includes(query.toLowerCase()) && (filter === "Semua" || p.status === filter));
  const action = (id: string, a: string) => { if (a === "delete" && confirm("Hapus project ini secara permanen?")) setProjects(v => v.filter(p => p.id !== id)); if (a === "archive") setProjects(v => v.map(p => p.id === id ? {...p, archived:true}:p)); if (a === "duplicate") setProjects(v => [{...v.find(p=>p.id===id)!, id:uid(), title:`${v.find(p=>p.id===id)?.title} (Copy)`, status:"draft"},...v]); };
  return <main className="dashboard"><header className="dash-nav"><Logo/><nav><button className="active">Projects</button><button onClick={() => alert("Preset brand akan tersedia setelah media service dikonfigurasi.")}>Brand kit</button></nav><div className="nav-actions"><span className="service"><i/> Service UI aktif</span><button className="avatar" onClick={() => setProfile(!profile)}>AR</button>{profile && <div className="profile-menu"><b>Arif Rahman</b><small>demo@clipmasbro.id</small><button><Settings2/> Pengaturan</button><button onClick={onLogout}><LogOut/> Keluar</button></div>}</div></header>
    <section className="dash-content"><div className="welcome"><div><span className="eyebrow">WORKSPACE / PROJECTS</span><h1>Halo, Arif! <span>👋</span></h1><p>Ubah percakapan panjang jadi klip yang bikin orang berhenti scroll.</p></div><button className="primary big" onClick={() => setCreate(true)}><Plus/> Project baru</button></div>
      <div className="stats"><div><Film/><span><b>{projects.filter(p=>!p.archived).length}</b> Total project</span></div><div><WandSparkles/><span><b>14</b> Clips dibuat</span></div><div><Clock3/><span><b>2.8 jam</b> Waktu dihemat</span></div><div className="accent"><Gauge/><span><b>94</b> Best moment score</span></div></div>
      <div className="project-head"><div><h2>Project terbaru</h2><span>{filtered.length} project</span></div><div className="tools"><label className="search"><Search/><input value={query} onChange={e=>setQuery(e.target.value)} placeholder="Cari project…"/></label><select value={filter} onChange={e=>setFilter(e.target.value)}><option>Semua</option><option value="ready">Siap edit</option><option value="processing">Processing</option><option value="draft">Draft</option></select><button className="icon-btn"><Grid2X2/></button></div></div>
      {filtered.length ? <div className="project-grid">{filtered.map(p=><ProjectCard key={p.id} project={p} onOpen={()=>onOpen(p.id)} onAction={a=>action(p.id,a)}/>)}</div> : <div className="empty"><Search/><h3>Project tidak ditemukan</h3><p>Coba kata kunci atau filter lain.</p></div>}
    </section>{create && <CreateModal onClose={()=>setCreate(false)} onCreate={title=>{const id=uid();setProjects(v=>[{id,title,status:"draft",ratio:"9:16",duration:"0:00",edited:"Baru saja"},...v]);setCreate(false);onOpen(id)}}/>}
  </main>;
}

function CreateModal({onClose,onCreate}:{onClose:()=>void;onCreate:(name:string)=>void}) { const [mode,setMode]=useState<"upload"|"youtube">("upload"); const [name,setName]=useState("Podcast terbaru"); const [url,setUrl]=useState(""); const [file,setFile]=useState(""); return <div className="modal-backdrop" onMouseDown={onClose}><div className="modal" onMouseDown={e=>e.stopPropagation()}><div className="modal-title"><div><span className="eyebrow">PROJECT BARU</span><h2>Masukkan video sumber</h2></div><button className="icon-btn" onClick={onClose}><X/></button></div><div className="mode-tabs"><button className={mode==="upload"?"active":""} onClick={()=>setMode("upload")}><Upload/> Upload MP4</button><button className={mode==="youtube"?"active":""} onClick={()=>setMode("youtube")}><Link2/> URL YouTube</button></div><label>Nama project<input value={name} onChange={e=>setName(e.target.value)}/></label>{mode==="upload"?<label className="dropzone"><input type="file" accept="video/mp4" onChange={e=>setFile(e.target.files?.[0]?.name||"")}/><Upload/><b>{file||"Tarik MP4 ke sini"}</b><span>{file?"File siap ditambahkan":"atau klik untuk pilih · Maks. 2 GB"}</span></label>:<><label>URL video<input value={url} onChange={e=>setUrl(e.target.value)} placeholder="https://youtube.com/watch?v=…"/></label><div className="config-note"><CircleHelp/> Unduhan YouTube membutuhkan media service yt-dlp. Project tetap dapat dibuat sekarang.</div></>}<div className="form-row"><label>Rasio awal<select><option>9:16 · Shorts</option><option>16:9 · Landscape</option><option>1:1 · Square</option></select></label><label>Bahasa<select><option>Indonesia</option><option>English</option><option>Deteksi otomatis</option></select></label></div><div className="modal-actions"><button className="secondary" onClick={onClose}>Batal</button><button className="primary" disabled={!name || (mode==="youtube" && !url.startsWith("https://"))} onClick={()=>onCreate(name)}><Sparkles/> Buat & analisis</button></div></div></div> }

function Editor({ onBack }: { onBack: () => void }) {
  const [title,setTitle]=useState("Masa Depan AI di Indonesia"); const [playing,setPlaying]=useState(false); const [time,setTime]=useState(2.7); const [clips,setClips]=useState(initialClips); const [selected,setSelected]=useState("v1"); const [tab,setTab]=useState("Scenes"); const [zoom,setZoom]=useState(1); const [leftOpen,setLeftOpen]=useState(true); const [rightOpen,setRightOpen]=useState(true); const [layout,setLayout]=useState("single"); const [exportOpen,setExportOpen]=useState(false); const [saved,setSaved]=useState("Tersimpan"); const [toast,setToast]=useState(""); const [history,setHistory]=useState<Clip[][]>([]); const [future,setFuture]=useState<Clip[][]>([]); const [trackState,setTrackState]=useState<Record<string,{muted:boolean;locked:boolean}>>({});
  const clipsRef=useRef(clips); clipsRef.current=clips;
  const commit=useCallback((next:Clip[])=>{setHistory(h=>[...h.slice(-24),clipsRef.current]);setFuture([]);setClips(next);setSaved("Menyimpan…");setTimeout(()=>setSaved("Tersimpan"),800)},[]);
  const undo=()=>{const last=history.at(-1);if(!last)return;setFuture(f=>[clips,...f]);setClips(last);setHistory(h=>h.slice(0,-1));setSaved("Menyimpan…")}; const redo=()=>{const next=future[0];if(!next)return;setHistory(h=>[...h,clips]);setClips(next);setFuture(f=>f.slice(1))};
  const remove=()=>{if(selected){commit(clips.filter(c=>c.id!==selected));setSelected("");setToast("Clip dihapus")}};
  const split=()=>{const c=clips.find(x=>x.id===selected);if(!c||time<=c.start||time>=c.end){setToast("Posisikan playhead di dalam clip");return;}commit(clips.flatMap(x=>x.id===c.id?[{...x,end:time},{...x,id:uid(),start:time,label:`${x.label} · split`}]:[x]));setToast("Clip dipisah")};
  const duplicate=()=>{const c=clips.find(x=>x.id===selected);if(c)commit([...clips,{...c,id:uid(),start:c.end+.2,end:c.end+.2+(c.end-c.start),label:`${c.label} · copy`}])};
  useEffect(()=>{if(!playing)return;const i=setInterval(()=>setTime(t=>t>=40?0:t+.1),100);return()=>clearInterval(i)},[playing]);
  useEffect(()=>{const key=(e:KeyboardEvent)=>{if(["INPUT","TEXTAREA","SELECT"].includes((e.target as HTMLElement).tagName))return;const mod=e.ctrlKey||e.metaKey;if(e.code==="Space"){e.preventDefault();setPlaying(v=>!v)}else if(e.key.toLowerCase()==="s")split();else if(e.key==="Delete"||e.key==="Backspace")remove();else if(mod&&e.key.toLowerCase()==="z"){e.preventDefault();e.shiftKey?redo():undo()}else if(mod&&e.key.toLowerCase()==="d"){e.preventDefault();duplicate()}else if(e.key==="ArrowRight")setTime(t=>Math.min(40,t+.1));else if(e.key==="ArrowLeft")setTime(t=>Math.max(0,t-.1))};window.addEventListener("keydown",key);return()=>window.removeEventListener("keydown",key)});
  const addScene=(s:Scene)=>{const end=Math.max(0,...clips.filter(c=>c.track==="video").map(c=>c.end));const clip:Clip={id:uid(),sceneId:s.id,track:"video",start:end,end:end+s.end-s.start,label:s.title,color:s.tone};commit([...clips,clip]);setSelected(clip.id);setToast("Scene ditambahkan ke timeline")};
  const selectedClip=clips.find(c=>c.id===selected); const activeWord=words.findIndex(w=>time>=w.start&&time<w.end);
  return <main className="editor"><header className="editor-top"><button className="icon-btn" onClick={onBack} title="Kembali ke projects"><ArrowLeft/></button><Logo compact/><span className="crumb">Projects <ChevronRight/> </span><input className="title-input" value={title} onChange={e=>{setTitle(e.target.value);setSaved("Menyimpan…")}} onBlur={()=>setSaved("Tersimpan")}/><span className={`save ${saved==="Tersimpan"?"ok":""}`}>{saved==="Tersimpan"?<Check/>:<LoaderCircle className="spin"/>}{saved}</span><div className="top-spacer"/><button className="icon-btn" disabled={!history.length} onClick={undo} title="Undo (Ctrl+Z)"><Undo2/></button><button className="icon-btn" disabled={!future.length} onClick={redo} title="Redo"><Redo2/></button><span className="timecode">{fmt(time)}</span><select className="compact-select"><option>9:16</option><option>16:9</option><option>1:1</option></select><button className="primary export-btn" onClick={()=>setExportOpen(true)}><Download/> Export</button></header>
    <div className={`workspace ${leftOpen?"":"left-closed"} ${rightOpen?"":"right-closed"}`}>
      <aside className="assets"><div className="panel-title"><div><Layers3/><b>Assets</b></div><button className="icon-btn" onClick={()=>setLeftOpen(false)}><ChevronLeft/></button></div><div className="asset-tabs">{[["Scenes",Film],["Captions",Captions],["Text",Text],["Media",Image]].map(([x,I])=><button key={x as string} className={tab===x?"active":""} onClick={()=>setTab(x as string)}><I size={15}/>{x as string}</button>)}</div>{tab==="Scenes"&&<ScenePanel onAdd={addScene} onPreview={s=>{setTime(s.start);setPlaying(true)}}/>}{tab==="Captions"&&<CaptionAssets/>}{tab==="Text"&&<TextAssets onAdd={label=>{const c:Clip={id:uid(),sceneId:"",track:"effects",start:time,end:time+4,label,color:"blue"};commit([...clips,c]);setSelected(c.id)}}/>}{tab==="Media"&&<MediaAssets/>}</aside>
      <section className="stage"><div className="stage-toolbar">{!leftOpen&&<button className="icon-btn" onClick={()=>setLeftOpen(true)}><LayoutPanelLeft/></button>}<div className="layout-switch"><button className={layout==="single"?"active":""} onClick={()=>setLayout("single")}>Single</button><button className={layout==="side"?"active":""} onClick={()=>setLayout("side")}>Side by side</button><button className={layout==="pip"?"active":""} onClick={()=>setLayout("pip")}>PiP</button></div><button className="icon-btn" onClick={()=>document.documentElement.requestFullscreen?.()}><Maximize2/></button>{!rightOpen&&<button className="icon-btn" onClick={()=>setRightOpen(true)}><Settings2/></button>}</div><div className={`preview-frame ${layout}`}><div className="speaker-video speaker-a"><span>PERSON A</span><div className="silhouette"/></div>{layout!=="single"&&<div className="speaker-video speaker-b"><span>PERSON B</span><div className="silhouette alt"/></div>}<div className="preview-gradient"/><div className="karaoke">{words.map((w,i)=><span key={i} className={i===activeWord?"active":i<activeWord?"past":""}>{w.text} </span>)}</div><div className="safe-guides"/></div><div className="transport"><button className="icon-btn"><ChevronLeft/></button><button className="play" onClick={()=>setPlaying(!playing)}>{playing?<Pause/>:<Play/>}</button><button className="icon-btn"><ChevronRight/></button><span>{fmt(time)} <i>/ 00:00:40.0</i></span><div className="transport-spacer"/><button className="icon-btn"><Volume2/></button><button className="icon-btn"><Maximize2/></button></div><div className="config-banner"><Sparkles/><span><b>Preview menggunakan proxy demo</b> · Hubungkan media service untuk source dan render produksi.</span><button onClick={()=>setToast("Buka README untuk kontrak media service")}>Pelajari</button></div></section>
      <aside className="properties"><div className="panel-title"><div><Settings2/><b>Properties</b></div><button className="icon-btn" onClick={()=>setRightOpen(false)}><ChevronRight/></button></div><Properties clip={selectedClip} onChange={patch=>selectedClip&&commit(clips.map(c=>c.id===selectedClip.id?{...c,...patch}:c))} onDelete={remove}/></aside>
      <Timeline clips={clips} selected={selected} time={time} zoom={zoom} trackState={trackState} onTrackState={setTrackState} onTime={setTime} onSelect={setSelected} onSplit={split} onDelete={remove} onDuplicate={duplicate} onZoom={setZoom}/>
    </div>{exportOpen&&<ExportModal onClose={()=>setExportOpen(false)}/>} {toast&&<div className="toast" onAnimationEnd={()=>setToast("")}><Check/>{toast}</div>}
  </main>;
}

function ScenePanel({onAdd,onPreview}:{onAdd:(s:Scene)=>void;onPreview:(s:Scene)=>void}) { const [q,setQ]=useState("");const [min,setMin]=useState(0);const list=scenes.filter(s=>s.title.toLowerCase().includes(q.toLowerCase())&&s.score>=min);return <div className="scene-panel"><div className="asset-search"><Search/><input value={q} onChange={e=>setQ(e.target.value)} placeholder="Cari scene…"/><button className="icon-btn" onClick={()=>setMin(min?0:85)} title="Filter score 85+"><ListFilter className={min?"lime-text":""}/></button></div><div className="scene-summary"><span>{list.length} scenes</span><button onClick={()=>setMin(min?0:85)}>Best moments <ChevronDown/></button></div><div className="scene-list">{list.map(s=><article className="scene-card" key={s.id} draggable onDragEnd={()=>onAdd(s)}><button className={`scene-thumb ${s.tone}`} onClick={()=>onPreview(s)}><div className="tiny-face"/><span className="score"><Sparkles/> {s.score}</span><span className="scene-duration">{(s.end-s.start).toFixed(1)}s</span><i><Play/></i></button><div className="scene-info"><div><span className={`speaker-dot ${s.tone}`}/><b>{s.speaker}</b><small>{shortTime(s.start)}</small></div><h4>{s.title}</h4><p>{s.transcript}</p><button onClick={()=>onAdd(s)}><Plus/> Tambah ke timeline</button></div></article>)}</div></div> }
function CaptionAssets(){return <div className="simple-assets"><div className="asset-callout"><Captions/><b>Subtitle karaoke</b><p>10 kata · Bahasa Indonesia · Word-level timing</p><button className="secondary"><Plus/> Track subtitle</button></div>{words.map((w,i)=><button className="word-row" key={i}><span>{fmt(w.start)}</span><b>{w.text}</b><i style={{width:`${(w.end-w.start)*55}px`}}/></button>)}</div>}
function TextAssets({onAdd}:{onAdd:(s:string)=>void}){return <div className="simple-assets"><p className="section-label">TEXT PRESETS</p>{["Judul besar","Lower third · Nama","💡 Emoji reaction","Call to action"].map((x,i)=><button className={`text-preset p${i}`} key={x} onClick={()=>onAdd(x)}><Text/>{x}<Plus/></button>)}</div>}
function MediaAssets(){return <div className="simple-assets"><div className="asset-callout"><Upload/><b>Source video</b><p>podcast-ai-proxy.mp4 · 48:12</p><span className="status ready">Proxy tersedia</span></div><div className="config-note"><Lock/> Original tersimpan sebagai object key. Signed URL dibutuhkan untuk produksi.</div></div>}

function Properties({clip,onChange,onDelete}:{clip?:Clip;onChange:(p:Partial<Clip>)=>void;onDelete:()=>void}) { const [section,setSection]=useState("Transform"); if(!clip)return <div className="no-selection"><MousePointer2/><h3>Pilih item</h3><p>Klik clip, caption, atau effect di timeline untuk mengedit.</p></div>; return <div className="prop-content"><div className="selected-kind"><span className={`kind-dot ${clip.color}`}/><div><small>{clip.track.toUpperCase()}</small><b>{clip.label}</b></div></div><div className="prop-tabs"><button className={section==="Transform"?"active":""} onClick={()=>setSection("Transform")}>Transform</button><button className={section==="Style"?"active":""} onClick={()=>setSection("Style")}>Style</button><button className={section==="Animate"?"active":""} onClick={()=>setSection("Animate")}>Animate</button></div><div className="prop-section"><h4>Timing</h4><div className="form-row"><label>Start<input type="number" step=".1" value={clip.start} onChange={e=>onChange({start:+e.target.value})}/></label><label>End<input type="number" step=".1" value={clip.end} onChange={e=>onChange({end:+e.target.value})}/></label></div></div>{section==="Transform"&&<><div className="prop-section"><h4>Layout speaker</h4><div className="layout-grid">{["Single","Dual","PiP","Side"].map(x=><button key={x}>{x}</button>)}</div></div><div className="prop-section"><h4>Transform</h4><div className="form-row"><label>Scale<input defaultValue="100%"/></label><label>Rotation<input defaultValue="0°"/></label></div><label>Opacity <span>100%</span><input type="range" min="0" max="100" defaultValue="100"/></label></div><div className="prop-section"><h4>Audio</h4><label>Volume <span>{clip.muted?"0%":"100%"}</span><input type="range" min="0" max="100" defaultValue={clip.muted?0:100}/></label><button className="secondary wide" onClick={()=>onChange({muted:!clip.muted})}>{clip.muted?"Unmute clip":"Mute clip"}</button></div></>}{section==="Style"&&<div className="prop-section"><h4>Caption style</h4><label>Font<select><option>Inter Black</option><option>Montserrat</option><option>Bebas Neue</option></select></label><div className="color-row"><button className="swatch white"/><button className="swatch lime active"/><button className="swatch orange"/><button className="swatch purple"/></div><label>Ukuran <span>52px</span><input type="range" min="20" max="100" defaultValue="52"/></label></div>}{section==="Animate"&&<div className="prop-section"><h4>Animasi masuk</h4><div className="layout-grid"><button className="active">Pop</button><button>Scale</button><button>Glow</button><button>None</button></div><label>Intensity <span>64%</span><input type="range" defaultValue="64"/></label></div>}<button className="delete-btn" onClick={onDelete}><Trash2/> Hapus item</button></div> }

const trackMeta=[{id:"video",label:"VIDEO",icon:Film},{id:"audio",label:"AUDIO",icon:Music2},{id:"captions",label:"CAPTIONS",icon:Captions},{id:"effects",label:"EFFECTS",icon:Sparkles}];
function Timeline({clips,selected,time,zoom,trackState,onTrackState,onTime,onSelect,onSplit,onDelete,onDuplicate,onZoom}:{clips:Clip[];selected:string;time:number;zoom:number;trackState:Record<string,{muted:boolean;locked:boolean}>;onTrackState:(v:Record<string,{muted:boolean;locked:boolean}>)=>void;onTime:(n:number)=>void;onSelect:(id:string)=>void;onSplit:()=>void;onDelete:()=>void;onDuplicate:()=>void;onZoom:(n:number)=>void}) { const width=1100*zoom; const [menu,setMenu]=useState<{x:number;y:number}|null>(null);return <section className="timeline"><div className="timeline-tools"><div className="tool-group"><button className="icon-btn active"><MousePointer2/></button><button className="icon-btn" onClick={onSplit} title="Split (S)"><Scissors/></button></div><span className="separator"/><button className="icon-btn" onClick={onDuplicate}><Copy/></button><button className="icon-btn" onClick={onDelete}><Trash2/></button><div className="timeline-spacer"/><span className="snap"><span>⌁</span> Snap</span><button className="icon-btn"><ZoomOut/></button><input type="range" min=".65" max="2" step=".05" value={zoom} onChange={e=>onZoom(+e.target.value)}/><button className="icon-btn"><ZoomIn/></button><button className="icon-btn"><Maximize2/></button></div><div className="timeline-body"><div className="track-heads"><div className="ruler-head">TRACKS</div>{trackMeta.map(t=>{const I=t.icon;const state=trackState[t.id]||{muted:false,locked:false};return <div className="track-head" key={t.id}><I/><b>{t.label}</b><div/><button onClick={()=>onTrackState({...trackState,[t.id]:{...state,muted:!state.muted}})} className={state.muted?"off":""}><Volume2/></button><button onClick={()=>onTrackState({...trackState,[t.id]:{...state,locked:!state.locked}})} className={state.locked?"on":""}><Lock/></button></div>})}</div><div className="tracks-scroll"><div style={{width}} className="tracks-canvas" onClick={e=>{const r=e.currentTarget.getBoundingClientRect();onTime(Math.max(0,Math.min(40,(e.clientX-r.left)/width*40)))}}><div className="ruler">{Array.from({length:9},(_,i)=><span key={i} style={{left:`${i*12.5}%`}}><i/>{shortTime(i*5)}</span>)}</div>{trackMeta.map(t=><div className={`track-row ${trackState[t.id]?.locked?"locked":""}`} key={t.id}>{clips.filter(c=>c.track===t.id).map(c=><button key={c.id} className={`timeline-clip ${c.color} ${selected===c.id?"selected":""}`} style={{left:`${c.start/40*100}%`,width:`${(c.end-c.start)/40*100}%`}} onClick={e=>{e.stopPropagation();onSelect(c.id)}} onContextMenu={e=>{e.preventDefault();onSelect(c.id);setMenu({x:e.clientX,y:e.clientY})}}><span className="clip-grip"/><b>{c.track==="video"&&<Film/>}{c.track==="audio"&&<Music2/>}{c.track==="captions"&&<Captions/>}{c.track==="effects"&&<Sparkles/>}{c.label}</b>{c.track==="audio"&&<span className="wave">▂▅▃▇▄▆▂▅▇▃▄▆▂▇▅</span>}<span className="clip-grip right"/></button>)}</div>)}<div className="playhead" style={{left:`${time/40*100}%`}}><i/><span/></div></div></div></div>{menu&&<div className="context-menu" style={{left:menu.x,top:menu.y}} onMouseLeave={()=>setMenu(null)}><button onClick={()=>{onSplit();setMenu(null)}}><Scissors/> Split at playhead <kbd>S</kbd></button><button onClick={()=>{onDuplicate();setMenu(null)}}><Copy/> Duplicate <kbd>⌘D</kbd></button><button><Mic2/> Extract audio</button><button><UserRound/> Switch person</button><hr/><button className="danger" onClick={()=>{onDelete();setMenu(null)}}><Trash2/> Delete <kbd>⌫</kbd></button></div>}</section> }

function ExportModal({onClose}:{onClose:()=>void}) { const [ratio,setRatio]=useState("9:16");const [quality,setQuality]=useState("1080p");const [subtitle,setSubtitle]=useState("burn");const [state,setState]=useState<"idle"|"config">("idle");return <div className="modal-backdrop" onMouseDown={onClose}><div className="modal export-modal" onMouseDown={e=>e.stopPropagation()}><div className="modal-title"><div><span className="eyebrow">SERVER-SIDE RENDER</span><h2>Export video</h2></div><button className="icon-btn" onClick={onClose}><X/></button></div><div className="export-preview"><div className={`mini-video r-${ratio.replace(":","")}`}><Sparkles/><b>AI BUKAN<br/><mark>PENGGANTI MANUSIA</mark></b></div><div><h3>Masa Depan AI — Short 01</h3><p>Durasi 00:40 · H.264 MP4</p><span>Estimasi ukuran 34–48 MB</span></div></div><div className="prop-section"><h4>Aspect ratio</h4><div className="choice-grid">{["9:16","16:9","1:1"].map(x=><button className={ratio===x?"active":""} onClick={()=>setRatio(x)} key={x}><Square/>{x}<small>{x==="9:16"?"Shorts":x==="16:9"?"Landscape":"Square"}</small></button>)}</div></div><div className="form-row"><label>Quality<select value={quality} onChange={e=>setQuality(e.target.value)}><option>1080p</option><option>720p</option></select></label><label>Frame rate<select><option>30 fps</option><option>60 fps</option><option>24 fps</option></select></label></div><div className="prop-section"><h4>Subtitle</h4><label className="radio"><input type="radio" checked={subtitle==="burn"} onChange={()=>setSubtitle("burn")}/><span><b>Burn-in</b><small>Style karaoke menyatu dengan video</small></span></label><label className="radio"><input type="radio" checked={subtitle==="soft"} onChange={()=>setSubtitle("soft")}/><span><b>Soft subtitle</b><small>Track subtitle terpisah</small></span></label></div>{state==="config"&&<div className="error-note"><CircleHelp/><span><b>Media service belum terhubung</b>Konfigurasikan MEDIA_SERVICE_URL untuk menjalankan FFmpeg renderer. Snapshot export sudah siap.</span></div>}<div className="modal-actions"><button className="secondary" onClick={onClose}>Batal</button><button className="primary" onClick={()=>setState("config")}><Download/> Mulai render {quality}</button></div></div></div> }

function App(){ const [logged,setLogged]=useState(()=>sessionStorage.getItem("cm-login")==="1"); const path=location.pathname; const [route,setRoute]=useState(path.startsWith("/editor")?"editor":path==="/login"?"login":"projects"); const nav=(r:string)=>{history.pushState({},"",r==="editor"?"/editor/podcast-ai":`/${r}`);setRoute(r)}; useEffect(()=>{const f=()=>setRoute(location.pathname.startsWith("/editor")?"editor":location.pathname==="/login"?"login":"projects");addEventListener("popstate",f);return()=>removeEventListener("popstate",f)},[]); if(!logged||route==="login")return <Login onLogin={()=>{sessionStorage.setItem("cm-login","1");setLogged(true);nav("projects")}}/>; if(route==="editor")return <Editor onBack={()=>nav("projects")}/>; return <Dashboard onOpen={()=>nav("editor")} onLogout={()=>{sessionStorage.removeItem("cm-login");setLogged(false);nav("login")}}/> }
createRoot(document.getElementById("root") as HTMLElement).render(<StrictMode><App/></StrictMode>);
