'use client';

import { useState, useEffect } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { toast } from 'react-hot-toast';
import { Maximize, Download, Sparkles, Trash2, RefreshCw, FileVideo } from 'lucide-react';
import FileUpload from '@/components/FileUpload';
import { modulesApi, assetsApi, jobsApi } from '@/lib/api';
import { useStore } from '@/lib/store';

const scaleOptions = [
  { value: 2, label: '2x' },
  { value: 4, label: '4x' },
];

const modelOptions = [
  { value: 'prob-3', label: 'Proteus (General)' },
  { value: 'ahq-12', label: 'Artemis High Quality' },
  { value: 'amq-13', label: 'Artemis Medium Quality' },
  { value: 'alq-13', label: 'Artemis Low Quality' },
  { value: 'ghq-5', label: 'Gaia High Quality (CG/Anime)' },
  { value: 'gcg-5', label: 'Gaia CG' },
  { value: 'thd-3', label: 'Theia Detail' },
  { value: 'thf-4', label: 'Theia Fidelity' },
  { value: 'nyx-1', label: 'Nyx (Denoise)' },
  { value: 'nyx-fast', label: 'Nyx Fast' },
  { value: 'ddv-3', label: 'Dione DV (Interlaced)' },
  { value: 'dtv-4', label: 'Dione TV (Interlaced)' },
  { value: 'iris-1', label: 'Iris (Face Enhancement)' },
  { value: 'Auto', label: 'Auto' },
];

interface QueueItem {
  id: string;
  file?: File;
  assetId?: string;
  filename?: string;
  jobId?: string;
  outputAssetId?: string;
  status: 'pending' | 'uploading' | 'processing' | 'completed' | 'error';
  error?: string;
  result?: any;
}

export default function VideoUpscalePage() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const { addJob, updateJob } = useStore();
  const [mounted, setMounted] = useState(false);
  const [queue, setQueue] = useState<QueueItem[]>([]);
  const [processing, setProcessing] = useState(false);

  // Settings
  const [scale, setScale] = useState(2);
  const [model, setModel] = useState('Auto');
  const [denoiseStrength, setDenoiseStrength] = useState(0.3); // Map to something or ignore?
  const [fps, setFps] = useState('');
  const [sharpening, setSharpening] = useState(15);
  const [recoverDetail, setRecoverDetail] = useState(20);
  const [addNoise, setAddNoise] = useState(0);
  const [faceEnhancement, setFaceEnhancement] = useState(false);

  useEffect(() => {
    setMounted(true);

    // Check for assetIds (batch) or assetId (single) in URL
    const assetIdsParam = searchParams.get('assetIds');
    const singleAssetId = searchParams.get('assetId');

    if ((assetIdsParam || singleAssetId) && assetsApi) {
      const idsToFetch = assetIdsParam ? assetIdsParam.split(',') : [singleAssetId!];

      Promise.all(idsToFetch.map(id => assetsApi.get(id)))
        .then((responses) => {
          setQueue(prev => {
            // Avoid duplicates
            const existingIds = new Set(prev.map(p => p.assetId));
            const newItems = responses
              .map((r: any) => r.data)
              .filter((asset: any) => !existingIds.has(asset.id))
              .map((asset: any) => ({
                id: Math.random().toString(36).substring(7),
                assetId: asset.id,
                status: 'pending' as const,
                filename: asset.original_filename || asset.filename
              }));
            return [...prev, ...newItems];
          });

          router.replace('/video/upscale');
          if (idsToFetch.length > 0) toast.success(`${idsToFetch.length} videos added from library`);
        }).catch((err: any) => {
          console.error("Failed to load assets", err);
          toast.error("Failed to load some assets from URL");
        });
    }
  }, [searchParams]);

  if (!mounted) return null;

  const handleFileUpload = (files: File[]) => {
    const newItems: QueueItem[] = files.map(file => ({
      id: Math.random().toString(36).substring(7),
      file,
      status: 'pending'
    }));
    setQueue(prev => [...prev, ...newItems]);
    toast.success(`${files.length} videos added to queue`);
  };

  const processItem = async (item: QueueItem) => {
    if (item.status === 'completed' || item.status === 'processing') return item;

    try {
      // 1. Upload if needed
      let assetId = item.assetId;
      if (!assetId && item.file) {
        setQueue(prev => prev.map(i => i.id === item.id ? { ...i, status: 'uploading' } : i));
        try {
          const uploadRes = await assetsApi.upload(item.file);
          assetId = uploadRes.data.id;
        } catch (uploadErr: any) {
          if (uploadErr.response?.status === 409) {
            const existingAssetId = uploadErr.response.data.detail.asset_id;
            const shouldOverwrite = window.confirm(
              `File "${item.file.name}" already exists. \nClick OK to Overwrite, Cancel to Use Existing.`
            );

            if (shouldOverwrite) {
              const uploadRes = await assetsApi.upload(item.file, undefined, false, true); // overwrite=true
              assetId = uploadRes.data.id;
            } else {
              assetId = existingAssetId;
            }
          } else {
            throw uploadErr;
          }
        }
        setQueue(prev => prev.map(i => i.id === item.id ? { ...i, assetId, status: 'pending' } : i));
      }

      if (!assetId) throw new Error("No asset ID");

      // 2. Start Upscale Job
      setQueue(prev => prev.map(i => i.id === item.id ? { ...i, status: 'processing' } : i));

      const response = await modulesApi.upscaleVideo({
        asset_id: assetId,
        scale,
        model,
        sharpening,
        recover_detail: recoverDetail,
        add_noise: addNoise,
        face_enhancement: faceEnhancement,
        fps: fps ? parseFloat(fps) : undefined,
      });

      const job = response.data;
      addJob({
        id: job.id,
        module: 'video_upscaling',
        status: job.status,
        progress: job.progress,
        created_at: job.created_at,
      });

      // Poll locally
      let currentJob = job;
      while (currentJob.status !== 'completed' && currentJob.status !== 'failed') {
        await new Promise(resolve => setTimeout(resolve, 5000)); // Polling slower for video
        const pollRes = await jobsApi.get(job.id);
        if (pollRes?.data) currentJob = pollRes.data;
        else break;
      }

      if (currentJob.status === 'completed' && currentJob.output_asset_ids?.[0]) {
        const assetRes = await assetsApi.get(currentJob.output_asset_ids[0]);
        const outputAsset = assetRes.data;

        setQueue(prev => prev.map(i => i.id === item.id ? {
          ...i,
          status: 'completed',
          jobId: job.id,
          outputAssetId: outputAsset.id,
          result: outputAsset
        } : i));

        return { ...item, status: 'completed', result: outputAsset };
      } else {
        throw new Error(currentJob.error_message || 'Job failed');
      }

    } catch (err: any) {
      console.error(err);
      const errorMsg = err.message || 'Failed';
      setQueue(prev => prev.map(i => i.id === item.id ? { ...i, status: 'error', error: errorMsg } : i));
      return { ...item, status: 'error', error: errorMsg };
    }
  };

  const handleProcessQueue = async () => {
    setProcessing(true);
    const pending = queue.filter(i => i.status === 'pending' || i.status === 'error');

    // Sequential processing
    const limit = 1;
    for (let i = 0; i < pending.length; i += limit) {
      const chunk = pending.slice(i, i + limit);
      await Promise.all(chunk.map(item => processItem(item)));
    }

    setProcessing(false);
    toast.success('Batch processing complete');
  };

  const removeItem = (id: string) => {
    setQueue(prev => prev.filter(i => i.id !== id));
  };

  const handleClearQueue = () => {
    setQueue([]);
  };

  const handleDownload = async (item: QueueItem) => {
    if (!item.result) return;
    try {
      const url = `/api/v1/assets/${item.result.id}/download`;
      const link = document.createElement('a');
      link.href = url;
      link.download = item.result.original_filename;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    } catch (err) {
      toast.error('Failed to download video');
    }
  };

  return (
    <div className="max-w-6xl mx-auto space-y-8">
      <div className="flex items-center gap-4">
        <div className="w-12 h-12 bg-forge-yellow/10 rounded-lg flex items-center justify-center">
          <Maximize className="w-6 h-6 text-forge-yellow" />
        </div>
        <div>
          <h1 className="text-2xl font-bold text-white">Video Upscaler</h1>
          <p className="text-gray-500">Enhance multiple videos with Topaz Labs AI</p>
        </div>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">

        {/* Left: Settings */}
        <div className="space-y-6 lg:col-span-1">
          <div className="bg-forge-dark p-6 rounded-xl border border-gray-800 space-y-6">
            <h3 className="text-lg font-semibold text-white">Batch Settings</h3>

            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">Scale Factor</label>
              <div className="flex gap-2">
                {scaleOptions.map((option) => (
                  <button
                    key={option.value}
                    onClick={() => setScale(option.value)}
                    className={`flex-1 py-2 rounded-lg font-medium transition-colors text-sm ${scale === option.value ? 'bg-forge-yellow text-black' : 'bg-black/40 border border-gray-700 text-gray-300 hover:border-gray-600'}`}
                  >
                    {option.label}
                  </button>
                ))}
              </div>
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">Model</label>
              <select value={model} onChange={(e: React.ChangeEvent<HTMLSelectElement>) => setModel(e.target.value)} className="select-field w-full">
                {modelOptions.map((option) => (
                  <option key={option.value} value={option.value}>{option.label}</option>
                ))}
              </select>
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">Sharpening: {sharpening}</label>
              <input type="range" min={0} max={100} value={sharpening} onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSharpening(parseInt(e.target.value))} className="w-full accent-forge-yellow" />
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">Recover Detail: {recoverDetail}</label>
              <input type="range" min={0} max={100} value={recoverDetail} onChange={(e: React.ChangeEvent<HTMLInputElement>) => setRecoverDetail(parseInt(e.target.value))} className="w-full accent-forge-yellow" />
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">Add Noise: {addNoise}</label>
              <input type="range" min={0} max={100} value={addNoise} onChange={(e: React.ChangeEvent<HTMLInputElement>) => setAddNoise(parseInt(e.target.value))} className="w-full accent-forge-yellow" />
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">Target FPS</label>
              <select value={fps} onChange={(e: React.ChangeEvent<HTMLSelectElement>) => setFps(e.target.value)} className="select-field w-full">
                <option value="">Original</option>
                <option value="24">24 FPS</option>
                <option value="30">30 FPS</option>
                <option value="60">60 FPS</option>
                <option value="120">120 FPS</option>
              </select>
            </div>

            <div className="flex items-center gap-2">
              <input type="checkbox" checked={faceEnhancement} onChange={(e: React.ChangeEvent<HTMLInputElement>) => setFaceEnhancement(e.target.checked)} className="rounded border-gray-700 bg-forge-dark text-forge-yellow" />
              <label className="text-sm text-gray-300">Face Enhancement</label>
            </div>

          </div>
        </div>

        {/* Right: Queue */}
        <div className="lg:col-span-2 space-y-6">
          <FileUpload
            onUploadMultiple={handleFileUpload}
            accept={{ 'video/*': ['.mp4', '.mov', '.avi', '.webm'] }}
            label="Drag & drop videos here (Multiple allowed)"
            multiple={true}
          />

          {queue.length > 0 && (
            <div className="flex flex-wrap gap-4 items-center justify-between bg-forge-dark p-4 rounded-xl border border-gray-800">
              <div className="text-white font-medium">Queue: {queue.length} items ({queue.filter(i => i.status === 'completed').length} completed)</div>
              <div className="flex gap-2">
                <button onClick={handleClearQueue} className="btn-secondary text-sm flex items-center gap-2" disabled={processing}><Trash2 className="w-4 h-4" /> Clear</button>
                <button onClick={handleProcessQueue} disabled={processing || !queue.some(i => i.status === 'pending' || i.status === 'error')} className="btn-primary text-sm flex items-center gap-2 disabled:opacity-50">
                  {processing ? <RefreshCw className="w-4 h-4 animate-spin" /> : <Sparkles className="w-4 h-4" />}
                  {processing ? 'Processing...' : 'Process Batch'}
                </button>
              </div>
            </div>
          )}

          <div className="space-y-4">
            {queue.map(item => (
              <div key={item.id} className="bg-forge-dark rounded-xl border border-gray-800 p-4 flex gap-4 items-center">
                <div className="w-20 h-20 bg-black/40 rounded-lg flex-shrink-0 flex items-center justify-center border border-gray-800">
                  <FileVideo className="w-8 h-8 text-gray-500" />
                </div>
                <div className="flex-1 min-w-0">
                  <h4 className="text-white font-medium truncate">{item.file?.name || item.filename || 'Unknown File'}</h4>
                  <div className="text-sm mt-1">
                    {item.status === 'pending' && <span className="text-gray-500">Waiting...</span>}
                    {item.status === 'uploading' && <span className="text-blue-400">Uploading...</span>}
                    {item.status === 'processing' && <span className="text-forge-yellow flex items-center gap-2"><RefreshCw className="w-3 h-3 animate-spin" /> Upscaling...</span>}
                    {item.status === 'completed' && <span className="text-green-400 flex items-center gap-2"><Sparkles className="w-3 h-3" /> Complete</span>}
                    {item.status === 'error' && <span className="text-red-400">Error: {item.error}</span>}
                  </div>
                </div>
                <div className="flex items-center gap-2">
                  {item.status === 'completed' && item.result && (
                    <button onClick={() => handleDownload(item)} className="p-2 hover:bg-white/10 rounded text-forge-yellow transition-colors"><Download className="w-5 h-5" /></button>
                  )}
                  <button onClick={() => removeItem(item.id)} className="p-2 hover:bg-white/10 rounded text-gray-500 hover:text-red-400 transition-colors" disabled={processing && item.status === 'processing'}><Trash2 className="w-5 h-5" /></button>
                </div>
              </div>
            ))}
            {queue.length === 0 && !processing && (
              <div className="text-center py-12 text-gray-500">Add videos to start batch upscaling</div>
            )}
          </div>

        </div>
      </div>
    </div>
  );
}
