import { useState, useRef, useCallback, useEffect } from 'react';
import type { PresetName } from '@core/types.js';
import { getPreset, PRESET_DESCRIPTIONS } from '@core/presets.js';
import { streamExtractAndEmbed } from '../lib/video-io.js';
import StrengthSlider from './StrengthSlider.js';
import ComparisonView from './ComparisonView.js';
import RobustnessTest from './RobustnessTest.js';

const PLEASE_HOLD = [
  { art: '  (•_•)\n  ( •_•)>⌐■-■\n  (⌐■_■)', caption: 'Putting on invisibility shades...' },
  { art: '  ┌(▀Ĺ̯▀)┐\n  ┌(▀Ĺ̯▀)┘\n  └(▀Ĺ̯▀)┐', caption: 'Robot dance while we wait...' },
  { art: '  ╔══╗\n  ║▓▓║  ☕\n  ╚══╝', caption: 'Brewing the perfect watermark...' },
  { art: '  🎬 → 🔬 → 💎', caption: 'Turning pixels into secrets...' },
  { art: '  [▓▓▓░░░░░░░]\n  [▓▓▓▓▓░░░░░]\n  [▓▓▓▓▓▓▓▓░░]', caption: 'Hiding bits in plain sight...' },
  { art: '    /\\_/\\\n   ( o.o )\n    > ^ <', caption: 'Even the cat can\'t see the watermark...' },
  { art: '  ┌─────────┐\n  │ 01101001 │\n  └─────────┘', caption: 'Whispering bits into wavelets...' },
  { art: '  ~~ 🌊 ~~\n  ~🏄~ ~~ \n  ~~~~~~~~', caption: 'Surfing the frequency domain...' },
  { art: '  📼 ➜ 🧬 ➜ 📼', caption: 'Splicing invisible DNA into frames...' },
  { art: '  ¯\\_(ツ)_/¯', caption: 'Trust us, the watermark is there...' },
];

/** Max frames to keep in memory for the comparison view */
const COMPARISON_SAMPLE = 30;

export default function EmbedPanel() {
  const [videoUrl, setVideoUrl] = useState<string | null>(null);
  const [videoName, setVideoName] = useState('');
  const [key, setKey] = useState('');
  const [payload, setPayload] = useState('DEADBEEF');
  const [preset, setPreset] = useState<PresetName>('light');
  const [alpha, setAlpha] = useState(0.00);
  const [processing, setProcessing] = useState(false);
  const [progress, setProgress] = useState({ phase: '', current: 0, total: 0 });
  const [jokeIndex, setJokeIndex] = useState(0);
  const [result, setResult] = useState<{
    blob: Blob;
    psnr: number;
    frames: number;
    originalFrames: ImageData[];
    watermarkedFrames: ImageData[];
    width: number;
    height: number;
    fps: number;
    embedTimeMs: number;
    pixelsPerSecond: number;
  } | null>(null);
  const fileRef = useRef<HTMLInputElement>(null);

  // Rotate jokes every 4s while processing
  useEffect(() => {
    if (!processing) return;
    setJokeIndex(Math.floor(Math.random() * PLEASE_HOLD.length));
    const id = setInterval(() => {
      setJokeIndex((i) => (i + 1) % PLEASE_HOLD.length);
    }, 4000);
    return () => clearInterval(id);
  }, [processing]);

  const handleFile = useCallback((file: File) => {
    const url = URL.createObjectURL(file);
    setVideoUrl(url);
    setVideoName(file.name);
    setResult(null);
  }, [result]);

  const handleDrop = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();
      const file = e.dataTransfer.files[0];
      if (file?.type.startsWith('video/')) handleFile(file);
    },
    [handleFile]
  );

  const handleEmbed = async () => {
    if (!videoUrl || !key) return;
    setProcessing(true);
    setResult(null);

    try {
      // Parse payload
      const payloadHex = payload.replace(/^0x/, '');
      const payloadBytes = new Uint8Array(
        (payloadHex.length % 2 ? '0' + payloadHex : payloadHex)
          .match(/.{2}/g)!
          .map((b) => parseInt(b, 16))
      );

      const config = getPreset(preset);

      // Stream: extract -> watermark -> encode in chunks
      const embedResult = await streamExtractAndEmbed(
        videoUrl,
        payloadBytes,
        key,
        config,
        COMPARISON_SAMPLE,
        (phase, current, total) => setProgress({ phase, current, total })
      );

      setResult({
        blob: embedResult.blob,
        psnr: embedResult.avgPsnr,
        frames: embedResult.totalFrames,
        originalFrames: embedResult.sampleOriginal,
        watermarkedFrames: embedResult.sampleWatermarked,
        width: embedResult.width,
        height: embedResult.height,
        fps: embedResult.fps,
        embedTimeMs: embedResult.embedTimeMs,
        pixelsPerSecond: embedResult.pixelsPerSecond,
      });
    } catch (e) {
      console.error('Embed error:', e);
      alert(`Error: ${e}`);
    } finally {
      setProcessing(false);
    }
  };

  const handleDownload = () => {
    if (!result) return;
    const url = URL.createObjectURL(result.blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = videoName.replace(/\.[^.]+$/, '') + '_watermarked.mp4';
    a.click();
    URL.revokeObjectURL(url);
  };

  const maxPayloadHexChars = 8; // Always 32 bits = 8 hex chars

  return (
    <div className="space-y-8">
      {/* Upload area */}
      <div
        onDrop={handleDrop}
        onDragOver={(e) => e.preventDefault()}
        onClick={() => fileRef.current?.click()}
        className={`group cursor-pointer rounded-2xl border-2 border-dashed p-10 text-center transition-all duration-200
          ${videoUrl
            ? 'border-zinc-700 bg-zinc-900/30'
            : 'border-zinc-800 bg-zinc-900/20 hover:border-blue-600/40 hover:bg-zinc-900/40 hover:shadow-lg hover:shadow-blue-600/5'
          }`}
      >
        <input
          ref={fileRef}
          type="file"
          accept="video/*"
          className="hidden"
          onChange={(e) => {
            const file = e.target.files?.[0];
            if (file) handleFile(file);
          }}
        />
        {videoUrl ? (
          <div className="space-y-2">
            <p className="text-sm font-medium text-zinc-300">🎬 {videoName}</p>
            <p className="text-xs text-zinc-500">Click or drop to replace</p>
          </div>
        ) : (
          <div className="space-y-3">
            <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-xl bg-zinc-800/80 transition-colors group-hover:bg-blue-600/10">
              <svg className="h-6 w-6 text-zinc-500 transition-colors group-hover:text-blue-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
                <path strokeLinecap="round" strokeLinejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5" />
              </svg>
            </div>
            <p className="text-sm text-zinc-400">Drop a video file or click to browse</p>
            <p className="text-xs text-zinc-600">MP4, WebM, MOV supported</p>
          </div>
        )}
      </div>

      {/* Configuration */}
      <div className="grid gap-6 sm:grid-cols-2">
        <div className="space-y-1.5">
          <label className="text-sm font-medium text-zinc-300">🔑 Secret Key</label>
          <input
            type="text"
            value={key}
            onChange={(e) => setKey(e.target.value)}
            placeholder="Enter a secret key..."
            className="w-full rounded-lg border border-zinc-800 bg-zinc-900/50 px-3 py-2 text-sm text-zinc-100
              placeholder:text-zinc-600 focus:border-blue-600 focus:outline-none focus:ring-1 focus:ring-blue-600
              transition-colors"
          />
        </div>

        <div className="space-y-1.5">
          <label className="text-sm font-medium text-zinc-300">📦 Payload (hex)</label>
          <input
            type="text"
            value={payload}
            onChange={(e) => setPayload(e.target.value.replace(/[^0-9a-fA-F]/g, '').slice(0, maxPayloadHexChars))}
            placeholder="DEADBEEF"
            className="w-full rounded-lg border border-zinc-800 bg-zinc-900/50 px-3 py-2 font-mono text-sm text-zinc-100
              placeholder:text-zinc-600 focus:border-blue-600 focus:outline-none focus:ring-1 focus:ring-blue-600
              transition-colors"
          />
          <p className="text-[10px] text-zinc-600">32-bit payload, 4 bytes hex</p>
        </div>
      </div>

      <StrengthSlider
        value={alpha}
        onChange={(v, p) => {
          setAlpha(v);
          setPreset(p);
        }}
        disabled={processing}
      />

      <p className="text-xs text-zinc-500">
        {PRESET_DESCRIPTIONS[preset]}
      </p>

      {/* Embed button */}
      <button
        onClick={handleEmbed}
        disabled={!videoUrl || !key || processing}
        className="w-full rounded-xl bg-gradient-to-r from-blue-600 to-blue-500 px-4 py-3 text-sm font-semibold text-white
          shadow-lg shadow-blue-600/20 transition-all hover:from-blue-500 hover:to-blue-400 hover:shadow-blue-500/30
          disabled:cursor-not-allowed disabled:from-zinc-800 disabled:to-zinc-800 disabled:text-zinc-500 disabled:shadow-none"
      >
        {processing ? (
          <span className="flex items-center justify-center gap-2">
            <span className="h-4 w-4 animate-spin rounded-full border-2 border-zinc-400 border-t-white" />
            {progress.phase} {progress.total > 0 ? `${progress.current}/${progress.total}` : ''}
          </span>
        ) : (
          '✨ Embed Watermark'
        )}
      </button>

      {/* Please-hold jokes while processing */}
      {processing && (
        <div className="flex flex-col items-center gap-2 rounded-xl bg-zinc-900/50 py-6 text-center">
          <pre className="font-mono text-sm leading-tight text-zinc-400">
            {PLEASE_HOLD[jokeIndex].art}
          </pre>
          <p className="text-xs text-zinc-500">{PLEASE_HOLD[jokeIndex].caption}</p>
        </div>
      )}

      {/* Results */}
      {result && (
        <div className="space-y-6 rounded-2xl border border-emerald-800/30 bg-emerald-950/10 p-6">
          <div className="flex items-center justify-between">
            <div>
              <h3 className="text-sm font-semibold text-emerald-400">✅ Embedding Complete</h3>
              <p className="mt-1 text-xs text-zinc-500">
                {result.frames} frames processed — Average PSNR: {result.psnr.toFixed(1)} dB
                <br />
                Embedded in {(result.embedTimeMs / 1000).toFixed(1)}s — {(result.pixelsPerSecond / 1e6).toFixed(1)} Mpx/s
              </p>
            </div>
            <button
              onClick={handleDownload}
              className="rounded-lg bg-emerald-600/20 px-4 py-2 text-sm font-medium text-emerald-400
                ring-1 ring-emerald-600/30 transition-all hover:bg-emerald-600/30 hover:ring-emerald-500/40"
            >
              ⬇️ Download
            </button>
          </div>

          <ComparisonView
            originalFrames={result.originalFrames}
            watermarkedFrames={result.watermarkedFrames}
            width={result.width}
            height={result.height}
            fps={result.fps}
          />

          <RobustnessTest
            blob={result.blob}
            width={result.width}
            height={result.height}
            payload={payload}
            secretKey={key}
          />
        </div>
      )}
    </div>
  );
}
