import React, { useState, useRef, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { UploadIcon, StackIcon, DownloadIcon, ArrowLeftIcon, CheckCircleIcon, XCircleIcon } from './Icons';
import { BatchItem } from '../types';
import { uploadMultiple, classifyMultipleStream, clearUploads, getSamples, useSample } from '../services/apiService';

const BatchAnalysis: React.FC = () => {
  const navigate = useNavigate();
  const [items, setItems] = useState<BatchItem[]>([]);
  const [processing, setProcessing] = useState(false);
  const [showSamples, setShowSamples] = useState(false);
  const [samples, setSamples] = useState<{ id: number, path: string, name: string }[]>([]);
  const fileInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    const fetchSamples = async () => {
      try {
        const data = await getSamples();
        if (Array.isArray(data)) {
          setSamples(data);
        }
      } catch (err) {
        console.error("Failed to fetch samples", err);
      }
    };
    fetchSamples();
  }, []);

  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files.length > 0) {
      const newFiles = Array.from(e.target.files) as File[];

      // Create preview items
      const newItems: BatchItem[] = newFiles.map(file => ({
        id: Math.random().toString(36).substr(2, 9),
        file: file,
        previewUrl: URL.createObjectURL(file),
        status: 'pending'
      }));

      setItems(prev => [...prev, ...newItems]);

      // Upload files immediately
      try {
        await uploadMultiple(newFiles);
      } catch (err) {
        console.error("Upload failed", err);
        // Mark these items as error
        setItems(prev => prev.map(item =>
          newItems.find(ni => ni.id === item.id) ? { ...item, status: 'error' } : item
        ));
      }
    }
  };

  const addSampleToQueue = async (filename: string, url: string) => {
    try {
      // Call backend to copy sample
      await useSample(filename, 'multiple');

      // Create a dummy file object for UI state consistency
      // The backend already has the file, so we don't need actual content here
      const file = new File([""], filename, { type: "image/png" });

      const newItem: BatchItem = {
        id: Math.random().toString(36).substr(2, 9),
        file,
        previewUrl: url,
        status: 'pending'
      };

      setItems(prev => [...prev, newItem]);

    } catch (err) {
      console.error("Failed to load sample", err);
    }
  };

  const normalizeFilename = (name: string) => {
    // Basic emulation of werkzeug.secure_filename behavior
    // 1. ASCII only (remove non-ascii) - simplified here to just keep standard chars
    // 2. Replace whitespace with underscore
    // 3. Remove invalid chars
    let normalized = name.replace(/\s+/g, '_');
    normalized = normalized.replace(/[^a-zA-Z0-9._-]/g, '');
    return normalized;
  };

  const runBatchProcessing = async () => {
    setProcessing(true);
    setItems(prev => prev.map(item => ({ ...item, status: 'processing', error: undefined })));

    try {
      // Use the generator helper which handles buffering and parsing correctly
      for await (const result of classifyMultipleStream()) {
        console.log("Received result:", result);

        if (result.error) {
          console.error("Error for file:", result.filename, result.error);
          setItems(prev => prev.map(item => {
            // Check exact match or normalized match
            if (item.file.name === result.filename || normalizeFilename(item.file.name) === result.filename) {
              return { ...item, status: 'error', error: result.error };
            }
            return item;
          }));
          continue;
        }

        setItems(prev => prev.map(item => {
          // Check exact match or normalized match
          if (item.file.name === result.filename || normalizeFilename(item.file.name) === result.filename) {
            return {
              ...item,
              status: 'completed',
              result: result.status === 'pass' ? 'pass' : 'fail',
              labels: result.labels
            };
          }
          return item;
        }));
      }

    } catch (err) {
      console.error("Batch processing error:", err);
      setItems(prev => prev.map(item =>
        item.status === 'processing' ? { ...item, status: 'error', error: 'Network or server error' } : item
      ));
    } finally {
      setProcessing(false);
      // Safety check: Mark any remaining processing items as error
      setItems(prev => prev.map(item =>
        item.status === 'processing' ? {
          ...item,
          status: 'error',
          error: 'No result from server (Filename mismatch or timeout)'
        } : item
      ));
    }
  };

  const getProgress = () => {
    if (items.length === 0) return 0;
    const completed = items.filter(i => i.status === 'completed' || i.status === 'error').length;
    return (completed / items.length) * 100;
  };

  const downloadReport = () => {
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
    const htmlContent = `
      <!DOCTYPE html>
      <html>
      <head>
        <title>Prism Batch Report - ${timestamp}</title>
        <style>
          body { font-family: sans-serif; background: #f8fafc; padding: 40px; }
          h1 { color: #0f172a; }
          table { width: 100%; border-collapse: collapse; background: white; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); border-radius: 8px; overflow: hidden; }
          th { background: #1e293b; color: white; text-align: left; padding: 12px 20px; }
          td { border-bottom: 1px solid #e2e8f0; padding: 12px 20px; color: #334155; }
          .pass { color: #059669; font-weight: bold; }
          .fail { color: #e11d48; font-weight: bold; }
          .labels { font-family: monospace; background: #f1f5f9; padding: 2px 6px; rounded: 4px; color: #475569; }
        </style>
      </head>
      <body>
        <h1>Batch Classification Report</h1>
        <p>Generated on: ${new Date().toLocaleString()}</p>
        <table>
          <thead>
            <tr>
              <th>Filename</th>
              <th>Status</th>
              <th>Result</th>
              <th>Failure Reason</th>
            </tr>
          </thead>
          <tbody>
            ${items.map(item => `
              <tr>
                <td>${item.file.name}</td>
                <td>${item.status}</td>
                <td class="${item.result}">${item.result ? item.result.toUpperCase() : '-'}</td>
                <td>${item.labels && item.labels.length > 0 ? `<span class="labels">${item.labels.join(', ')}</span>` : '-'}</td>
              </tr>
            `).join('')}
          </tbody>
        </table>
      </body>
      </html>
    `;

    const blob = new Blob([htmlContent], { type: 'text/html' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `prism-batch-report-${timestamp}.html`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  };

  const clearAll = async () => {
    setItems([]);
    await clearUploads();
  };

  const isComplete = items.length > 0 && items.every(i => i.status === 'completed' || i.status === 'error');

  return (
    <div className="min-h-screen flex flex-col p-4 md:p-8 max-w-7xl mx-auto">
      <header className="flex items-center justify-between mb-8">
        <h2 className="text-2xl font-light tracking-wide">Batch Image <span className="font-bold text-cyan-400">Analysis</span></h2>
      </header>

      {/* Controls */}
      <div className="glass-panel rounded-2xl p-6 mb-8">
        <div className="flex flex-col md:flex-row items-center justify-between gap-6">
          <div className="flex items-center gap-4 w-full md:w-auto">
            <button
              onClick={() => fileInputRef.current?.click()}
              className="flex items-center gap-2 bg-cyan-500 hover:bg-cyan-400 text-black font-bold py-3 px-6 rounded-lg transition-all hover:shadow-[0_0_20px_rgba(34,211,238,0.4)]"
            >
              <UploadIcon /> Upload Files
            </button>
            <input
              type="file"
              ref={fileInputRef}
              className="hidden"
              multiple
              accept="image/*"
              onChange={handleFileChange}
            />

            {items.length > 0 && (
              <button
                onClick={clearAll}
                className="text-slate-400 hover:text-white transition-colors text-sm"
              >
                Clear Queue
              </button>
            )}
          </div>

          <div className="flex items-center gap-4 w-full md:w-auto">
            <div className="flex-1 md:w-64 h-2 bg-slate-700 rounded-full overflow-hidden">
              <div
                className="h-full bg-cyan-400 transition-all duration-500 ease-out"
                style={{ width: `${getProgress()}%` }}
              />
            </div>
            <span className="text-sm font-mono text-cyan-400 w-12">{Math.round(getProgress())}%</span>
          </div>
        </div>

        {/* Sample Gallery Toggle */}
        <button
          onClick={() => setShowSamples(!showSamples)}
          className="mt-6 w-full py-2 border-t border-white/5 text-slate-400 hover:text-cyan-400 text-sm uppercase tracking-widest font-medium transition-colors flex items-center justify-center gap-2"
        >
          <StackIcon />
          {showSamples ? 'Close Test Deck' : 'Load Test Data'}
        </button>

        <div className={`w-full transition-all duration-500 ease-in-out overflow-hidden ${showSamples ? 'max-h-[400px] opacity-100' : 'max-h-0 opacity-0'}`}>
          <div className="p-6 bg-slate-800/30 rounded-b-2xl border-x border-b border-slate-700/50">
            <div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4 overflow-y-auto max-h-[350px] pr-2 custom-scrollbar">
              {samples.map((sample) => {
                const isSelected = items.some(item => item.previewUrl === sample.url);
                return (
                  <div
                    key={sample.id}
                    className={`group relative aspect-square rounded-xl overflow-hidden cursor-pointer border-2 transition-all duration-300 ${isSelected ? 'border-cyan-400 ring-2 ring-cyan-400/50' : 'border-slate-700 hover:border-cyan-500'
                      }`}
                    onClick={() => addSampleToQueue(sample.filename, sample.url)}
                  >
                    <img
                      src={sample.url}
                      alt={`Sample ${sample.id}`}
                      className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110"
                    />
                    <div className={`absolute inset-0 transition-colors duration-300 ${isSelected ? 'bg-cyan-500/20' : 'bg-black/0 group-hover:bg-black/20'
                      }`}>
                      {isSelected && (
                        <div className="absolute top-2 right-2 bg-cyan-500 rounded-full p-1">
                          <CheckCircleIcon className="w-4 h-4 text-white" />
                        </div>
                      )}
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      </div>

      {/* Status Bar */}
      {items.length > 0 && (
        <div className="flex items-center justify-between mb-6 animate-fade-in">
          <div>
            <p className="text-white font-medium">{items.length} items in queue</p>
            {processing && (
              <p className="text-[10px] text-center text-purple-300/80 animate-pulse">
                Running on CPU: Classification takes time, please be patient 🐨✨
              </p>
            )}
          </div>
          <div className="flex gap-4">
            <button
              onClick={runBatchProcessing}
              disabled={processing || isComplete}
              className="bg-white text-black font-bold py-2 px-6 rounded-lg hover:bg-slate-200 disabled:opacity-50 disabled:cursor-not-allowed transition-colors shadow-[0_0_20px_rgba(255,255,255,0.2)]"
            >
              {processing ? 'Processing...' : isComplete ? 'Analysis Complete' : 'Start Analysis'}
            </button>
            <button
              onClick={downloadReport}
              disabled={!isComplete}
              className="flex items-center gap-2 bg-slate-800 text-white py-2 px-6 rounded-lg border border-slate-700 hover:bg-slate-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
            >
              <DownloadIcon /> Report
            </button>
          </div>
        </div>
      )}

      {/* Grid */}
      <div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 gap-4 pb-20">
        {items.map((item) => (
          <div
            key={item.id}
            className={`relative aspect-[9/16] rounded-xl overflow-hidden group border animate-fade-in ${item.status === 'completed'
              ? (item.result === 'pass' ? 'border-emerald-500/50' : 'border-rose-500/50')
              : 'border-white/5'
              }`}
          >
            <img src={item.previewUrl} className="w-full h-full object-cover" alt="Batch Item" />

            {/* Overlay Status */}
            <div className="absolute inset-0 bg-gradient-to-t from-black/90 to-transparent opacity-80 flex flex-col justify-end p-3">
              {item.status === 'processing' && (
                <span className="text-cyan-400 text-xs font-bold animate-pulse">ANALYZING...</span>
              )}
              {item.status === 'pending' && (
                <span className="text-slate-400 text-xs">PENDING</span>
              )}
              {item.status === 'error' && (
                <div className="flex flex-col">
                  <span className="text-rose-400 text-xs font-bold">ERROR</span>
                  {item.error && (
                    <span className="text-[10px] text-rose-200 leading-tight mt-1 break-words">
                      {item.error.length > 50 ? item.error.substring(0, 50) + '...' : item.error}
                    </span>
                  )}
                </div>
              )}
              {item.status === 'completed' && (
                <div className="flex flex-col gap-1">
                  <div className="flex items-center gap-1">
                    {item.result === 'pass'
                      ? <CheckCircleIcon className="text-emerald-400 w-5 h-5" />
                      : <XCircleIcon className="text-rose-400 w-5 h-5" />
                    }
                    <span className={`text-sm font-bold uppercase ${item.result === 'pass' ? 'text-emerald-400' : 'text-rose-400'}`}>
                      {item.result}
                    </span>
                  </div>
                  {item.labels && item.labels.length > 0 && (
                    <div className="flex flex-wrap gap-1 mt-1">
                      {item.labels.map((label, idx) => (
                        <span key={idx} className="text-[10px] bg-rose-500/20 text-rose-200 px-1.5 py-0.5 rounded border border-rose-500/30">
                          {label}
                        </span>
                      ))}
                    </div>
                  )}
                </div>
              )}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default BatchAnalysis;