/**
 * @license
 * SPDX-License-Identifier: Apache-2.0
 */
import React, { useState, useRef, useEffect, useCallback } from 'react';
import { 
  MonitorPlay, 
  SquareSquare,
  StopCircle, 
  Activity, 
  Settings2, 
  Video, 
  Radio,
  Eye,
  EyeOff,
  Copy,
  Check
} from 'lucide-react';
import { motion, AnimatePresence } from 'motion/react';
import flvjs from 'flv.js';
import { v4 as uuidv4 } from 'uuid';

export default function App() {
  const [isStreaming, setIsStreaming] = useState(false);
  const [streamConfig, setStreamConfig] = useState<{ rtmpUrl: string, streamKey: string, isNgrok?: boolean } | null>(null);
  const [showKey, setShowKey] = useState(false);
  const [copied, setCopied] = useState(false);
  const [isStreamActiveBackend, setIsStreamActiveBackend] = useState(false);
  
  const [stats, setStats] = useState({
    fps: 0, kbps: 0, droppedFrames: 0, codec: 'H.264/AAC', resolution: 'Awaiting Signal', jitter: 0
  });

  const videoRef = useRef<HTMLVideoElement>(null);
  const flvPlayerRef = useRef<flvjs.Player | null>(null);
  const statsIntervalRef = useRef<NodeJS.Timeout | null>(null);

  useEffect(() => {
    // Generate stream key and get RTMP URL on mount
    fetch('/api/config')
      .then(res => res.json())
      .then(data => {
        setStreamConfig({
          rtmpUrl: data.rtmpUrl,
          streamKey: uuidv4().substring(0, 13).replace(/-/g, ''), // e.g. a1b2c3d4e5f6
          isNgrok: data.isNgrok
        });
      });
  }, []);

  useEffect(() => {
    if (!streamConfig?.streamKey) return;

    let mounted = true;
    const checkBackendActive = async () => {
      try {
        const res = await fetch(`/api/streams/live/${streamConfig.streamKey}`);
        if (!res.ok) return;
        const data = await res.json();
        if (mounted) {
          setIsStreamActiveBackend(data.active);
        }
      } catch (e) {
        // ignore fetch errors
      }
    };

    checkBackendActive();
    const interval = setInterval(checkBackendActive, 2000);
    return () => {
      mounted = false;
      clearInterval(interval);
    };
  }, [streamConfig?.streamKey]);

  const copyToClipboard = () => {
    if (streamConfig) {
      navigator.clipboard.writeText(streamConfig.streamKey);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    }
  };

  const startPlayer = () => {
    if (!flvjs.isSupported() || !videoRef.current || !streamConfig) return;

    if (flvPlayerRef.current) {
      flvPlayerRef.current.destroy();
    }

    const protocol = window.location.protocol === 'https:' ? 'https:' : 'http:';
    const host = window.location.host;
    const fetchUrl = `${protocol}//${host}/live/${streamConfig.streamKey}.flv`;

    const flvPlayer = flvjs.createPlayer({
      type: 'flv',
      url: fetchUrl,
      isLive: true,
      hasAudio: true,
      hasVideo: true,
    });

    flvPlayer.attachMediaElement(videoRef.current);
    flvPlayer.load();
    
    // We try to play, but it might fail if there's no stream yet.
    // The user should start the player AFTER starting the stream in OBS, or we can handle errors.
    try {
      const playPromise = flvPlayer.play() as Promise<void> | undefined;
      if (playPromise !== undefined) {
        playPromise.catch(() => {
          console.log("Playback failed. Awaiting stream...");
        });
      }
    } catch (e) {
      console.log("Playback failed. Awaiting stream...", e);
    }

    flvPlayer.on(flvjs.Events.ERROR, (errType, errDetail) => {
      console.error("FLV Player Error:", errType, errDetail);
      if (errType === flvjs.ErrorTypes.NETWORK_ERROR) {
        // Stream not live yet, or disconnected
        setIsStreaming(false);
      }
    });

    flvPlayer.on(flvjs.Events.STATISTICS_INFO, (statInfo) => {
      setIsStreaming(true); // if we get stats, we are receiving video!
      
      setStats(prev => ({
        ...prev,
        fps: Math.round(statInfo.decodedFrames / Math.max(1, (videoRef.current?.currentTime || 1)) ), // Rough estimate or just rely on NMS
        kbps: Math.round(statInfo.speed * 8), // speed is usually bytes per second in some versions, or kbps
        droppedFrames: statInfo.droppedFrames || 0,
        resolution: `${videoRef.current?.videoWidth || 0}x${videoRef.current?.videoHeight || 0}`
      }));
    });

    flvPlayerRef.current = flvPlayer;
    setIsStreaming(true);

    // Simulated Stats polling (since flv.js stats might be limited)
    statsIntervalRef.current = setInterval(() => {
      if (videoRef.current && videoRef.current.videoWidth > 0) {
        setStats(prev => ({
          ...prev,
          resolution: `${videoRef.current?.videoWidth}x${videoRef.current?.videoHeight}`
        }));
      }
    }, 1000);
  };

  const stopPlayer = () => {
    if (flvPlayerRef.current) {
      flvPlayerRef.current.destroy();
      flvPlayerRef.current = null;
    }
    if (statsIntervalRef.current) {
      clearInterval(statsIntervalRef.current);
    }
    if (videoRef.current) {
      videoRef.current.src = ""; // Clear video
    }
    setIsStreaming(false);
    setStats({
      fps: 0, kbps: 0, droppedFrames: 0, codec: 'H.264/AAC', resolution: 'Awaiting Signal', jitter: 0
    });
  };

  useEffect(() => {
    return stopPlayer;
  }, []);

  return (
    <div className="min-h-screen bg-[#0a0a0b] text-zinc-400 font-sans p-6 overflow-hidden flex flex-col">
      {/* Header Section */}
      <header className="flex items-center justify-between mb-6 border-b border-zinc-800 pb-4">
        <div className="flex items-center gap-4">
          <div className="w-3 h-3 bg-red-600 rounded-full shadow-[0_0_8px_#dc2626] animate-pulse"></div>
          <h1 className="text-xl font-bold tracking-tight text-zinc-100 flex items-center gap-2">
            <Radio className="w-5 h-5 text-emerald-400" />
            RTMP COMMAND CENTER <span className="text-zinc-600 font-normal ml-2 text-sm hidden sm:inline">v2.4.0</span>
          </h1>
        </div>
        <div className="flex gap-6 items-center">
          <div className="text-right">
            <p className="text-[10px] uppercase tracking-widest text-zinc-500">Node Media Server</p>
            <p className="text-emerald-500 font-mono text-sm">OPERATIONAL</p>
          </div>
          <div className="h-8 w-px bg-zinc-800 hidden sm:block"></div>
          <div className="text-right hidden sm:block">
            <p className="text-[10px] uppercase tracking-widest text-zinc-500">Player State</p>
            <p className="text-zinc-100 font-mono text-sm">{isStreaming ? 'CONNECTED' : 'DISCONNECTED'}</p>
          </div>
        </div>
      </header>

      <main className="flex-1 flex flex-col lg:flex-row gap-6 min-h-0 overflow-y-auto lg:overflow-visible">
        
        {/* Sidebar Left: Config */}
        <div className="w-full lg:w-80 flex flex-col gap-4 z-20">
          
          <div className="bg-zinc-900/50 border border-zinc-800 p-4 rounded-lg">
            <h3 className="text-[10px] font-bold uppercase tracking-widest mb-4 text-zinc-500 flex items-center gap-2">
              <Settings2 className="w-3 h-3" />
              Ingest Configuration
            </h3>
            <div className="space-y-4">
              <div className="space-y-1">
                <label className="text-[11px] text-zinc-400">Server URL (OBS / Streamlabs)</label>
                <div className="bg-black border border-zinc-700 px-3 py-2 text-xs font-mono text-emerald-400 rounded break-all">
                  {streamConfig?.rtmpUrl || 'Loading...'}
                </div>
              </div>
              <div className="space-y-1">
                <label className="text-[11px] text-zinc-400">Stream Key</label>
                <div className="bg-black border border-zinc-700 px-3 py-2 text-xs font-mono text-zinc-500 rounded flex justify-between items-center group">
                  <span className={showKey ? "text-zinc-100" : ""}>
                    {showKey ? streamConfig?.streamKey : "•••• •••• •••• ••••"}
                  </span>
                  <div className="flex items-center gap-2">
                    <button 
                      onClick={() => setShowKey(!showKey)}
                      className="text-zinc-600 hover:text-zinc-400 transition-colors"
                    >
                      {showKey ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
                    </button>
                    <button 
                      onClick={copyToClipboard}
                      className="text-zinc-600 hover:text-zinc-400 transition-colors"
                    >
                      {copied ? <Check className="w-4 h-4 text-emerald-500" /> : <Copy className="w-4 h-4" />}
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div className="bg-zinc-900/50 border border-zinc-800 p-4 rounded-lg">
             <h3 className="text-[10px] font-bold uppercase tracking-widest mb-4 text-zinc-500 flex items-center gap-2">
              <SquareSquare className="w-3 h-3" />
              Source Details
            </h3>
            <div className="space-y-3">
              <div className="flex justify-between items-end border-b border-zinc-800 pb-2">
                <span className="text-xs">Incoming Resp</span>
                <span className="text-sm font-mono text-zinc-100">{stats.resolution}</span>
              </div>
              <div className="flex justify-between items-end border-b border-zinc-800 pb-2">
                <span className="text-xs">Video Codec</span>
                <span className="text-sm font-mono text-zinc-100">H.264 / AVC</span>
              </div>
              <div className="flex justify-between items-end border-b border-zinc-800 pb-2">
                <span className="text-xs">Audio Codec</span>
                <span className="text-sm font-mono text-zinc-100">AAC 48kHz</span>
              </div>
            </div>
          </div>
          
          <div className="bg-zinc-900/50 border border-zinc-800 p-4 rounded-lg flex-1">
            <h3 className="text-[10px] font-bold uppercase tracking-widest mb-4 text-zinc-500">System Logs</h3>
            <div className="text-xs text-zinc-500 font-mono space-y-2">
              <p><span className="text-zinc-700">[SYSTEM]</span> RTMP Server bound to :1935</p>
              <p><span className="text-zinc-700">[SYSTEM]</span> HTTP-FLV muxing active</p>
              {streamConfig?.isNgrok ? (
                <p className="text-emerald-500 font-bold mt-2">
                  Bore.pub TCP Tunnel is ACTIVE! Ready for Streamlabs connection.
                </p>
              ) : (
                <>
                  <p className="text-amber-500/80 mt-2">
                    Establishing proxy tunnel for OBS / Streamlabs compatibility...
                  </p>
                </>
              )}
            </div>
          </div>

          {!isStreaming ? (
            <motion.button 
              whileHover={isStreamActiveBackend ? { scale: 1.02 } : {}}
              whileTap={isStreamActiveBackend ? { scale: 0.98 } : {}}
              onClick={isStreamActiveBackend ? startPlayer : undefined}
              className={`w-full py-3 font-bold text-xs rounded transition-colors flex items-center justify-center gap-2 ${
                isStreamActiveBackend 
                  ? 'bg-zinc-100 text-black hover:bg-white cursor-pointer' 
                  : 'bg-zinc-800 text-zinc-500 cursor-not-allowed border border-zinc-700'
              }`}
            >
              {isStreamActiveBackend ? (
                <>
                  <MonitorPlay className="w-4 h-4" />
                  CONNECT PLAYER
                </>
              ) : (
                <>
                  <div className="w-3 h-3 border-2 border-zinc-500 border-t-zinc-400 rounded-full animate-spin"></div>
                  AWAITING STREAM...
                </>
              )}
            </motion.button>
          ) : (
             <motion.button 
              whileHover={{ scale: 1.02 }}
              whileTap={{ scale: 0.98 }}
              onClick={stopPlayer}
              className="w-full py-3 bg-black text-rose-500 border border-rose-900 font-bold text-xs rounded hover:bg-rose-950 transition-colors flex items-center justify-center gap-2"
            >
              <StopCircle className="w-4 h-4" />
              DISCONNECT PLAYER
            </motion.button>
          )}
        </div>

        {/* Main Video View */}
        <div className="flex-1 flex flex-col min-w-0">
          <div className="relative bg-black rounded-xl overflow-hidden border border-zinc-700 aspect-video group shadow-2xl">
            
            {/* Placeholder if not streaming */}
            <AnimatePresence>
              {!isStreaming && (
                <motion.div 
                  initial={{ opacity: 0, scale: 0.9 }}
                  animate={{ opacity: 1, scale: 1 }}
                  exit={{ opacity: 0, scale: 0.9 }}
                  className="absolute inset-0 flex flex-col items-center justify-center text-zinc-600 z-10"
                >
                  <div className="w-16 h-16 border-2 border-zinc-700/50 rounded-full flex items-center justify-center mb-4">
                    <Video className="w-6 h-6 opacity-50" />
                  </div>
                  <h3 className="text-sm font-bold text-zinc-500 tracking-widest uppercase mb-1">AWAITING RTMP SIGNAL</h3>
                  <p className="text-[10px] uppercase text-zinc-600 mt-2 text-center max-w-xs">
                    Start streaming from OBS to the Server URL, then click Connect Player.
                  </p>
                </motion.div>
              )}
            </AnimatePresence>

            <video 
              ref={videoRef} 
              autoPlay 
              playsInline 
              muted 
              className={`w-full h-full object-contain transition-opacity duration-500 ${isStreaming ? 'opacity-100' : 'opacity-0'}`}
            />
            
            {/* Tech HUD on Video */}
            <AnimatePresence>
              {isStreaming && (
                <motion.div initial={{opacity: 0}} animate={{opacity: 1}} exit={{opacity: 0}}>
                  {/* Top Left */}
                  <div className="absolute top-4 left-4 flex gap-2">
                    <span className="bg-red-600/90 text-white text-[10px] font-bold px-2 py-0.5 rounded animate-pulse">LIVE</span>
                    <span className="bg-black/60 text-white text-[10px] font-mono px-2 py-0.5 rounded backdrop-blur-md border border-white/10">{stats.resolution}</span>
                  </div>
                  {/* Bottom Right */}
                  <div className="absolute bottom-4 right-4">
                    <span className="bg-black/60 text-emerald-400 text-[10px] font-mono px-2 py-0.5 rounded border border-emerald-400/20">FLV.JS DEMUXER</span>
                  </div>
                  {/* Viewfinder Corners */}
                  <div className="absolute top-4 right-4 w-4 h-4 border-t-2 border-r-2 border-white/20"></div>
                  <div className="absolute bottom-4 left-4 w-4 h-4 border-b-2 border-l-2 border-white/20"></div>
                </motion.div>
              )}
            </AnimatePresence>
          </div>

          {/* Telemetry Dashboard */}
          <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mt-6">
            <div className="bg-zinc-900 border border-zinc-800 p-3 rounded-lg overflow-hidden relative">
              <p className="text-[10px] uppercase text-zinc-500 mb-1 tracking-widest">Network</p>
              <div className="flex items-end gap-2">
                <span className="text-xl md:text-2xl font-mono text-zinc-100">{stats.kbps.toLocaleString()}</span>
                <span className="text-[10px] mb-1">kbps</span>
              </div>
            </div>
            <div className="bg-zinc-900 border border-zinc-800 p-3 rounded-lg overflow-hidden relative">
              <p className="text-[10px] uppercase text-zinc-500 mb-1 tracking-widest">Client Frame Rate</p>
              <div className="flex items-end gap-2">
                <span className="text-xl md:text-2xl font-mono text-emerald-400">{stats.fps > 0 ? stats.fps : '-'}</span>
                <span className="text-[10px] mb-1">FPS</span>
              </div>
            </div>
            <div className="bg-zinc-900 border border-zinc-800 p-3 rounded-lg overflow-hidden relative">
              <p className="text-[10px] uppercase text-zinc-500 mb-1 tracking-widest">Client Dropped</p>
              <div className="flex items-end gap-2">
                <span className={`text-xl md:text-2xl font-mono ${stats.droppedFrames > 0 ? 'text-rose-400' : 'text-zinc-100'}`}>{stats.droppedFrames}</span>
                <span className="text-[10px] mb-1">Frames</span>
              </div>
            </div>
            <div className="bg-zinc-900 border border-zinc-800 p-3 rounded-lg overflow-hidden relative">
              <p className="text-[10px] uppercase text-zinc-500 mb-1 tracking-widest">Demuxer</p>
              <div className="flex items-end gap-2">
                <span className="text-xl font-mono text-zinc-100 truncate">{stats.codec.toUpperCase()}</span>
              </div>
            </div>
          </div>
        </div>
      </main>

    </div>
  );
}
