'use client';

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

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

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

  // Handle URL params on mount
  useEffect(() => {
    const assetIdsParam = searchParams.get('assetIds');
    const singleAssetId = searchParams.get('assetId');

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

      Promise.all(ids.map(id => assetsApi.get(id)))
        .then(responses => {
          const newItems = responses.map((res: any) => {
            const asset = res.data;
            return {
              id: Math.random().toString(36).substring(7),
              assetId: asset.id,
              filename: asset.original_filename,
              status: 'pending' as const
            };
          });

          setQueue(prev => {
            // Dedup
            const existing = new Set(prev.map(p => p.assetId));
            return [...prev, ...newItems.filter(i => !existing.has(i.assetId))];
          });

          // Clear URL
          router.replace('/text/alt-text');

          if (ids.length > 0) {
            toast.success(`${ids.length} images added from library`);
          }
        })
        .catch(err => {
          console.error('Failed to load assets', err);
          toast.error('Failed to load some assets');
        });
    }
  }, [searchParams, router]);

  // Handle drag-and-drop from carousel
  useDragFromCarousel({
    onAssetDrop: async (assetIds) => {
      try {
        const responses = await Promise.all(assetIds.map(id => assetsApi.get(id)));
        const newItems = responses
          .map((r: any) => r.data)
          .filter((asset: any) => asset.file_type === 'image')
          .map((asset: any) => ({
            id: Math.random().toString(36).substring(7),
            assetId: asset.id,
            filename: asset.original_filename,
            status: 'pending' as const
          }));

        if (newItems.length > 0) {
          setQueue(prev => {
            const existing = new Set(prev.map(p => p.assetId));
            return [...prev, ...newItems.filter(i => !existing.has(i.assetId))];
          });
          toast.success(`${newItems.length} images added from carousel`);
        } else {
          toast.error('No valid images in selection');
        }
      } catch (err) {
        console.error('Failed to load dragged assets', err);
        toast.error('Failed to add assets');
      }
    },
    enabled: true
  });

  const handleFileUpload = (files: File[]) => {
    const newItems: QueueItem[] = files.map(file => ({
      id: Math.random().toString(36).substring(7),
      file,
      filename: file.name,
      status: 'pending'
    }));
    setQueue(prev => [...prev, ...newItems]);
    toast.success(`${files.length} images 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));
      }

      // 2. Generate
      setQueue(prev => prev.map(i => i.id === item.id ? { ...i, status: 'processing' } : i));
      const response = await modulesApi.generateAltText({ asset_id: assetId });
      const job = response.data;

      // Add to global store to track there too
      addJob({
        id: job.id,
        module: 'alt_text_generator',
        status: job.status,
        progress: job.progress,
        created_at: job.created_at,
      });

      // Simple polling for the queue item
      let currentJob = job;
      while (currentJob.status !== 'completed' && currentJob.status !== 'failed') {
        await new Promise(resolve => setTimeout(resolve, 2000));
        const pollRes = await jobsApi.get(job.id);

        if (pollRes?.data) currentJob = pollRes.data;
        else break;
      }

      if (currentJob.status === 'completed' && currentJob.output_data) {
        const result = {
          shortAlt: currentJob.output_data.short_alt_text,
          longAlt: currentJob.output_data.long_alt_text
        };
        setQueue(prev => prev.map(i => i.id === item.id ? { ...i, status: 'completed', result, jobId: job.id } : i));
        return { ...item, status: 'completed', result };
      } else {
        throw new Error(currentJob.error_message || 'Job failed');
      }

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

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

    // Process strictly sequentially to avoid rate limits? Or parallel?
    // Parallel limit 3
    const limit = 3;
    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('Queue processing complete');
  };

  const handleDownloadCSV = () => {
    const completed = queue.filter(i => i.status === 'completed' && i.result);
    if (!completed.length) return;

    const headers = ['Filename', 'Short Alt Text', 'Long Alt Text'];
    const rows = completed.map(item => [
      item.filename || 'unknown',
      `"${(item.result?.shortAlt || '').replace(/"/g, '""')}"`,
      `"${(item.result?.longAlt || '').replace(/"/g, '""')}"`
    ]);

    const csvContent = [headers.join(','), ...rows.map(r => r.join(','))].join('\n');
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', 'alt_text_results.csv');
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };

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

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

  const copyToClipboard = (text: string) => {
    navigator.clipboard.writeText(text);
    toast.success('Copied!');
  };

  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">
          <FileText className="w-6 h-6 text-forge-yellow" />
        </div>
        <div>
          <h1 className="text-2xl font-bold text-white">Alt Text Generator</h1>
          <p className="text-gray-500">Batch generate accessible alt text for images</p>
        </div>
      </div>

      <div
        className="grid grid-cols-1 gap-8"
        onDragOver={(e) => e.preventDefault()}
        onDrop={(e) => {
          e.preventDefault();
          try {
            const raw = e.dataTransfer.getData('application/json');
            if (!raw) return;
            const data = JSON.parse(raw);
            if (data.type === 'forge-asset') {
              if (data.mime_type && !data.mime_type.startsWith('image/')) {
                toast.error('Only images are supported for Alt Text');
                return;
              }
              setQueue(prev => {
                // Dedup
                if (prev.some(i => i.assetId === data.id)) return prev;
                return [...prev, {
                  id: Math.random().toString(36).substring(7),
                  assetId: data.id,
                  filename: data.filename,
                  status: 'pending'
                }];
              });
              toast.success('Image added to queue');
            }
          } catch (err) {
            console.error('Invalid drop', err);
          }
        }}
      >
        {/* Upload Section */}
        <div className="space-y-4">
          <FileUpload
            onUploadMultiple={handleFileUpload}
            accept={{ 'image/*': ['.png', '.jpg', '.jpeg', '.webp', '.gif'] }}
            label="Upload images to analyze (Multiple allowed)"
            multiple={true}
          />
        </div>

        {/* Queue Actions */}
        {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 Queue'}
              </button>
              <button
                onClick={handleDownloadCSV}
                disabled={!queue.some(i => i.status === 'completed')}
                className="btn-secondary text-sm flex items-center gap-2 disabled:opacity-50"
              >
                <Download className="w-4 h-4" /> Download CSV
              </button>
            </div>
          </div>
        )}

        {/* Queue List */}
        <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-start">
              {/* Thumbnail */}
              <div className="w-24 h-24 bg-black/40 rounded-lg flex-shrink-0 overflow-hidden relative">
                <img
                  src={item.file ? URL.createObjectURL(item.file) : `/api/v1/assets/${item.assetId}/download`}
                  alt="thumb"
                  className="w-full h-full object-cover"
                />
              </div>

              {/* Content */}
              <div className="flex-1 min-w-0 space-y-2">
                <div className="flex justify-between items-start">
                  <h3 className="text-white font-medium truncate">{item.filename || item.file?.name}</h3>
                  <button onClick={() => removeItem(item.id)} className="text-gray-500 hover:text-red-400">
                    <Trash2 className="w-4 h-4" />
                  </button>
                </div>

                {/* Status / Result */}
                {item.status === 'completed' && item.result ? (
                  <div className="space-y-2 text-sm">
                    <div className="bg-black/20 p-2 rounded">
                      <div className="flex justify-between text-gray-400 text-xs mb-1">
                        <span>Short Alt</span>
                        <button onClick={() => copyToClipboard(item.result!.shortAlt)}><Copy className="w-3 h-3 hover:text-white" /></button>
                      </div>
                      <p className="text-gray-300">{item.result.shortAlt}</p>
                    </div>
                    <div className="bg-black/20 p-2 rounded">
                      <div className="flex justify-between text-gray-400 text-xs mb-1">
                        <span>Long Alt</span>
                        <button onClick={() => copyToClipboard(item.result!.longAlt)}><Copy className="w-3 h-3 hover:text-white" /></button>
                      </div>
                      <p className="text-gray-300 line-clamp-2">{item.result.longAlt}</p>
                    </div>
                  </div>
                ) : (
                  <div className="text-sm text-gray-400 flex items-center gap-2">
                    {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">Analyzing...</span>}
                    {item.status === 'error' && <span className="text-red-400">Error: {item.error}</span>}
                  </div>
                )}
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}
