(() => {
function Player({camera,onFocus,focused}){
 const video=React.useRef(null),[status,setStatus]=React.useState('Menghubungkan'),[retry,setRetry]=React.useState(0);
 React.useEffect(()=>{
  const element=video.current;let hls,stopped=false,lastTime=-1,lastProgress=Date.now();setStatus('Menghubungkan');
  const play=()=>element.play().catch(()=>{if(!stopped)setStatus('Klik Putar')});
  const progress=()=>{if(!element.paused&&element.readyState>=2&&element.currentTime!==lastTime){lastTime=element.currentTime;lastProgress=Date.now();setStatus('Live')}};
  const waiting=()=>setStatus('Buffering'),pause=()=>setStatus('Dijeda'),error=()=>setStatus('Tidak tersedia');
  element.addEventListener('timeupdate',progress);element.addEventListener('waiting',waiting);element.addEventListener('pause',pause);element.addEventListener('error',error);
  if(element.canPlayType('application/vnd.apple.mpegurl')){element.src=camera.stream_url;play()}
  else if(window.Hls?.isSupported()){hls=new Hls({enableWorker:false,lowLatencyMode:true,maxBufferLength:15});hls.loadSource(camera.stream_url);hls.attachMedia(element);hls.on(Hls.Events.MANIFEST_PARSED,play);hls.on(Hls.Events.ERROR,(_,data)=>{if(data.fatal){setStatus('Tidak tersedia');hls.destroy()}})}
  else setStatus('Browser tidak mendukung HLS');
  const timer=setInterval(()=>{if(Date.now()-lastProgress>15000)setStatus('Tidak tersedia')},5000);
  return()=>{stopped=true;clearInterval(timer);hls?.destroy();element.removeEventListener('timeupdate',progress);element.removeEventListener('waiting',waiting);element.removeEventListener('pause',pause);element.removeEventListener('error',error);element.pause();element.removeAttribute('src');element.load()};
 },[camera.stream_url,retry]);
 return <article className="cctv-player"><div className="cctv-player-heading"><h2>{camera.name}</h2><span role="status" className={'cctv-live '+(status==='Live'?'online':'')}>{status==='Live'?'● Live':status}</span></div><video ref={video} controls muted autoPlay playsInline aria-label={'Live CCTV '+camera.name}/><div className="cctv-player-actions"><button type="button" onClick={()=>setRetry(v=>v+1)}>Hubungkan ulang</button>{!focused&&<button type="button" onClick={onFocus}>Fokus kamera</button>}<button type="button" onClick={()=>{const v=video.current;if(v.requestFullscreen)v.requestFullscreen().catch(()=>setStatus('Fullscreen tidak tersedia'));else if(v.webkitEnterFullscreen)v.webkitEnterFullscreen();}}>Layar penuh</button></div></article>;
}
function CCTVPage(){
 const [cameras,setCameras]=React.useState([]),[selected,setSelected]=React.useState('all'),[loading,setLoading]=React.useState(true),[error,setError]=React.useState('');
 React.useEffect(()=>{const controller=new AbortController();let active=true;const load=async()=>{try{const r=await fetch('/api/public/cctvs',{signal:controller.signal});const b=await r.json();if(!r.ok)throw Error(b.error||'Gagal memuat kamera.');if(active){setCameras(b.data);setSelected(value=>value==='all'||b.data.some(c=>String(c.id)===value)?value:'all');setError('')}}catch(e){if(active)setError(e.message)}finally{if(active)setLoading(false)}};load();const timer=setInterval(load,30000);return()=>{active=false;controller.abort();clearInterval(timer)}},[]);
 const visible=selected==='all'?cameras:cameras.filter(c=>String(c.id)===selected);
 return <section className="cctv-public"><div className="cctv-public-heading"><h1>Live Streaming CCTV</h1><p>Pantau aktivitas di berbagai area peternakan.</p></div>{error&&<p role="alert" className="cctv-message error">{error}</p>}{loading?<p role="status">Memuat kamera...</p>:!cameras.length?<div className="cctv-empty"><h2>Belum ada kamera aktif</h2><p>Siaran akan tampil saat kamera diaktifkan oleh pengelola.</p></div>:<><div className="cctv-view-controls"><label>Tampilan<select value={selected} onChange={e=>setSelected(e.target.value)}><option value="all">Semua kamera ({cameras.length})</option>{cameras.map(c=><option key={c.id} value={String(c.id)}>{c.name}</option>)}</select></label>{selected!=='all'&&<button onClick={()=>setSelected('all')}>Kembali ke semua kamera</button>}<span>{visible.length} kamera ditampilkan</span></div><div className={'cctv-grid '+(selected!=='all'?'focused':'')}>{visible.map(camera=><Player key={camera.id} camera={camera} focused={selected!=='all'} onFocus={()=>setSelected(String(camera.id))}/>)}</div><p className="cctv-footnote">Indikator Live muncul saat video berjalan. Siaran dapat mengalami jeda; gunakan Hubungkan ulang jika koneksi terputus.</p></>}</section>;
}
window.CCTVPage=CCTVPage;
})();
