import React from 'react';
import { createWistiaPlayerElement, ensureWistiaPlayerAssets } from '../wistia-player';

type Progress={percent:number;currentTime:number;duration:number};
type Props={provider:'upload'|'youtube'|'wistia'|'direct';mediaId?:number;mediaUrl?:string;externalId?:string;directUrl?:string;title?:string;posterUrl?:string;captionUrl?:string;initialTime?:number;onProgress?:(progress:Progress)=>void};

type YouTubePlayerInstance={getCurrentTime?:()=>number;getDuration?:()=>number;seekTo?:(seconds:number,allowSeekAhead?:boolean)=>void;destroy?:()=>void};
type YouTubeApi={Player:new(target:HTMLElement,options:Record<string,unknown>)=>YouTubePlayerInstance};
declare global{interface Window{YT?:YouTubeApi;onYouTubeIframeAPIReady?:()=>void}}

function emitProgress(player:{currentTime?:number;duration?:number},onProgress?:Props['onProgress']){const duration=Number(player.duration||0),currentTime=Number(player.currentTime||0);if(duration>0)onProgress?.({percent:Math.min(100,Math.max(0,currentTime/duration*100)),currentTime,duration});}
function PlayerError({provider,id,message}:{provider:string;id?:string;message:string}){return <div className="interactive-learn-video-error" role="alert"><strong>Video unavailable</strong><p>{message}</p>{provider==='youtube'&&id?<a className="interactive-button interactive-button-secondary" href={`https://www.youtube.com/watch?v=${encodeURIComponent(id)}`} target="_blank" rel="noreferrer">Open on YouTube</a>:provider==='wistia'&&id?<a className="interactive-button interactive-button-secondary" href={`https://home.wistia.com/medias/${encodeURIComponent(id)}`} target="_blank" rel="noreferrer">Open Wistia video</a>:null}</div>}

function Html5Player({src,title,posterUrl,captionUrl,initialTime,onProgress}:{src:string;title?:string;posterUrl?:string;captionUrl?:string;initialTime?:number;onProgress?:Props['onProgress']}){const ref=React.useRef<HTMLVideoElement>(null);React.useEffect(()=>{const video=ref.current;if(!video)return;const ready=()=>{if(initialTime&&initialTime>0&&(!video.duration||initialTime<video.duration-2))video.currentTime=initialTime;emitProgress(video,onProgress)};const update=()=>emitProgress(video,onProgress);video.addEventListener('loadedmetadata',ready);video.addEventListener('timeupdate',update);video.addEventListener('pause',update);video.addEventListener('ended',update);return()=>{video.removeEventListener('loadedmetadata',ready);video.removeEventListener('timeupdate',update);video.removeEventListener('pause',update);video.removeEventListener('ended',update)}},[src,initialTime,onProgress]);return <video ref={ref} className="interactive-learn-video-player" controls playsInline preload="metadata" poster={posterUrl} aria-label={title||'Lesson video'}><source src={src}/>{captionUrl?<track kind="captions" src={captionUrl} srcLang="en" label="Captions" default/>:null}</video>}

let youtubeApiPromise:Promise<YouTubeApi>|undefined;
function ensureYouTubeApi(){if(typeof window==='undefined')return Promise.reject(new Error('youtube_browser_required'));if(window.YT?.Player)return Promise.resolve(window.YT);if(!youtubeApiPromise)youtubeApiPromise=new Promise((resolve,reject)=>{const previous=window.onYouTubeIframeAPIReady;window.onYouTubeIframeAPIReady=()=>{previous?.();window.YT?.Player?resolve(window.YT):reject(new Error('youtube_api_unavailable'))};const existing=document.querySelector<HTMLScriptElement>('script[data-interactive-learn-youtube-api]');if(existing){existing.addEventListener('error',()=>reject(new Error('youtube_api_load_failed')),{once:true});return;}const script=document.createElement('script');script.src='https://www.youtube.com/iframe_api';script.async=true;script.dataset.interactiveLearnYoutubeApi='1';script.addEventListener('error',()=>reject(new Error('youtube_api_load_failed')),{once:true});document.head.append(script)});return youtubeApiPromise;}
function YouTubePlayer({id,title,initialTime,onProgress}:{id:string;title?:string;initialTime?:number;onProgress?:Props['onProgress']}){const host=React.useRef<HTMLDivElement>(null);const [error,setError]=React.useState('');React.useEffect(()=>{let disposed=false,interval:ReturnType<typeof setInterval>|undefined;let player:YouTubePlayerInstance|undefined;const report=()=>{if(!player)return;const duration=Number(player.getDuration?.()||0),currentTime=Number(player.getCurrentTime?.()||0);if(duration>0)onProgress?.({percent:Math.min(100,Math.max(0,currentTime/duration*100)),currentTime,duration})};void ensureYouTubeApi().then(YT=>{if(disposed||!host.current)return;player=new YT.Player(host.current,{host:'https://www.youtube-nocookie.com',videoId:id,playerVars:{rel:0,modestbranding:1,playsinline:1,origin:window.location.origin},events:{onReady:()=>{if(initialTime&&initialTime>0)player?.seekTo?.(initialTime,true);report();interval=setInterval(report,1000)},onStateChange:report,onError:()=>setError('This YouTube video could not be loaded by the course player.')}})}).catch(()=>setError('The YouTube player API could not be loaded.'));return()=>{disposed=true;if(interval)clearInterval(interval);try{player?.destroy?.()}catch{/* best effort */}}},[id,initialTime,onProgress]);return error?<PlayerError provider="youtube" id={id} message={error}/>:<div className="interactive-learn-video-provider" aria-label={title||'YouTube video'}><div ref={host}/></div>}

function WistiaPlayer({id,title,initialTime,onProgress}:{id:string;title?:string;initialTime?:number;onProgress?:Props['onProgress']}){const host=React.useRef<HTMLDivElement>(null);const [error,setError]=React.useState('');React.useEffect(()=>{const container=host.current;if(!container)return;setError('');const player=createWistiaPlayerElement(id,{title,initialTime});container.replaceChildren(player);const report=()=>{const duration=Number(player.duration||0),currentTime=Number(player.currentTime||0);if(duration>0)onProgress?.({percent:Math.min(100,Math.max(0,currentTime/duration*100)),currentTime,duration})};const ready=()=>{if(initialTime&&initialTime>0&&initialTime<Number(player.duration||Number.POSITIVE_INFINITY)-2)player.currentTime=initialTime;report()};for(const event of ['api-ready','time-update','pause','ended'])player.addEventListener(event,event==='api-ready'?ready:report);void ensureWistiaPlayerAssets(id).catch(()=>setError('The Wistia player could not be loaded.'));return()=>{for(const event of ['api-ready','time-update','pause','ended'])player.removeEventListener(event,event==='api-ready'?ready:report);if(container.contains(player))player.remove()}},[id,initialTime,onProgress,title]);return error?<PlayerError provider="wistia" id={id} message={error}/>:<div className="interactive-learn-video-provider" aria-label={title||'Wistia video'}><div ref={host}/></div>}

export function LearnVideoPlayer(props:Props){let content:React.ReactNode=null;if(props.provider==='youtube'&&props.externalId)content=<YouTubePlayer id={props.externalId} title={props.title} initialTime={props.initialTime} onProgress={props.onProgress}/>;else if(props.provider==='wistia'&&props.externalId)content=<WistiaPlayer id={props.externalId} title={props.title} initialTime={props.initialTime} onProgress={props.onProgress}/>;else if(props.provider==='direct'&&props.directUrl)content=<Html5Player src={props.directUrl} title={props.title} posterUrl={props.posterUrl} captionUrl={props.captionUrl} initialTime={props.initialTime} onProgress={props.onProgress}/>;else if(props.mediaUrl)content=<Html5Player src={props.mediaUrl} title={props.title} posterUrl={props.posterUrl} captionUrl={props.captionUrl} initialTime={props.initialTime} onProgress={props.onProgress}/>;else if(props.mediaId)content=<Html5Player src={`/api/learn/media/${props.mediaId}`} title={props.title} posterUrl={props.posterUrl} captionUrl={props.captionUrl} initialTime={props.initialTime} onProgress={props.onProgress}/>;return <div className={`interactive-learn-video-shell provider-${props.provider}`}>{content}</div>}
