import { useState, useCallback } from 'react';
import { Link } from 'wouter';
import {
  Zap, Settings, Download, RotateCcw, Upload, Image as ImageIcon,
  RefreshCw, Expand, Layers, Smartphone, SlidersHorizontal, Shapes, Columns2, Gauge, Rocket, Lock
} from 'lucide-react';
import { Button } from '@/components/UI/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/UI/card';
import { Label } from '@/components/UI/label';
import { Slider } from '@/components/UI/slider';
import { RadioGroup, RadioGroupItem } from '@/components/UI/radio-group';
import { Badge } from '@/components/UI/badge';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/UI/accordion';
import { useDropzone } from 'react-dropzone';
import { saveAs } from 'file-saver';
import { CompressionSettings } from '@/types/image';

const recommendedTools = [
  { id: 'format-converter', name: 'Format Converter', icon: RefreshCw },
  { id: 'image-resizer', name: 'Image Resizer', icon: Expand },
  { id: 'batch-processor', name: 'Batch Processor', icon: Layers },
  { id: 'heic-converter', name: 'HEIC to JPG', icon: Smartphone },
];

const goodToKnow = [
  { icon: SlidersHorizontal, text: 'Quality slider updates the estimated file size instantly' },
  { icon: Shapes, text: 'Export as JPEG, PNG, or WebP depending on what you need' },
  { icon: Columns2, text: 'Side-by-side preview shows exactly what you\'re trading off' },
  { icon: Gauge, text: 'Typically cuts file size by 60-80% with barely any visible loss' },
  { icon: Rocket, text: 'Lighter images mean a page that loads noticeably faster' },
  { icon: Lock, text: 'Runs locally — images never get uploaded anywhere' },
];

interface CompressedImage {
  originalFile: File;
  compressedFile: File;
  originalSize: number;
  compressedSize: number;
  compressionRatio: number;
  originalUrl: string;
  compressedUrl: string;
}

export default function ImageCompressor() {
  const [currentImage, setCurrentImage] = useState<File | null>(null);
  const [compressedImage, setCompressedImage] = useState<CompressedImage | null>(null);
  const [isProcessing, setIsProcessing] = useState(false);
  const [settingsChanged, setSettingsChanged] = useState(false);
  const [lastUsedSettings, setLastUsedSettings] = useState<CompressionSettings | null>(null);
  const [settings, setSettings] = useState<CompressionSettings>({
    quality: 85,
    format: 'jpeg',
    progressive: true,
    removeExif: false,
    optimizeForWeb: true,
    resize: {
      enabled: false,
      maintainAspectRatio: true
    }
  });

  // Compress image function
  const compressImage = useCallback(async (file: File, quality: number, format: string) => {
    return new Promise<File>((resolve, reject) => {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const img = new Image();

      img.onload = () => {
        canvas.width = img.naturalWidth;
        canvas.height = img.naturalHeight;
        
        if (ctx) {
          ctx.drawImage(img, 0, 0);
          
          canvas.toBlob((blob) => {
            if (blob) {
              const compressedFile = new File([blob], file.name, {
                type: `image/${format}`,
                lastModified: Date.now()
              });
              resolve(compressedFile);
            } else {
              reject(new Error('Compression failed'));
            }
          }, `image/${format}`, quality / 100);
        } else {
          reject(new Error('Canvas context not available'));
        }
      };

      img.onerror = () => reject(new Error('Failed to load image'));
      img.src = URL.createObjectURL(file);
    });
  }, []);

  // Handle file upload
  const onDrop = useCallback(async (acceptedFiles: File[]) => {
    const file = acceptedFiles[0];
    if (!file || !file.type.startsWith('image/')) {
      alert('Please upload an image file');
      return;
    }

    setCurrentImage(file);
    setCompressedImage(null);
  }, []);

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    accept: {
      'image/*': ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']
    },
    multiple: false
  });

  // Check if settings have changed after compression
  const hasSettingsChanged = () => {
    if (!lastUsedSettings || !compressedImage) return false;
    return JSON.stringify(settings) !== JSON.stringify(lastUsedSettings);
  };

  // Process compression
  const handleCompress = async () => {
    if (!currentImage) return;

    setIsProcessing(true);
    try {
      const compressed = await compressImage(currentImage, settings.quality, settings.format);
      const compressionRatio = Math.max(0, Math.round((1 - compressed.size / currentImage.size) * 100));
      
      setCompressedImage({
        originalFile: currentImage,
        compressedFile: compressed,
        originalSize: currentImage.size,
        compressedSize: compressed.size,
        compressionRatio,
        originalUrl: URL.createObjectURL(currentImage),
        compressedUrl: URL.createObjectURL(compressed)
      });
      
      // Save settings used for this compression
      setLastUsedSettings({ ...settings });
      setSettingsChanged(false);
    } catch (error) {
      console.error('Compression failed:', error);
      alert('Compression failed. Please try again.');
    } finally {
      setIsProcessing(false);
    }
  };

  const downloadCompressed = () => {
    if (compressedImage?.compressedFile && currentImage) {
      const extension = settings.format === 'jpeg' ? 'jpg' : settings.format;
      const filename = currentImage.name.replace(/\.[^/.]+$/, '') + `_compressed.${extension}`;
      saveAs(compressedImage.compressedFile, filename);
    }
  };

  const resetSettings = () => {
    setSettings({
      quality: 85,
      format: 'jpeg',
      progressive: true,
      removeExif: false,
      optimizeForWeb: true,
      resize: { enabled: false, maintainAspectRatio: true }
    });
  };

  const startOver = () => {
    setCurrentImage(null);
    setCompressedImage(null);
  };

  const formatFileSize = (bytes: number) => {
    if (bytes === 0) return '0 Bytes';
    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
  };

  const getQualityLabel = (quality: number) => {
    if (quality >= 95) return { label: 'Maximum', color: 'text-green-600' };
    if (quality >= 85) return { label: 'High', color: 'text-green-500' };
    if (quality >= 70) return { label: 'Medium', color: 'text-yellow-500' };
    if (quality >= 50) return { label: 'Low', color: 'text-orange-500' };
    return { label: 'Very Low', color: 'text-red-500' };
  };

  const qualityInfo = getQualityLabel(settings.quality);

  return (
    <div className="w-full max-w-4xl mx-auto p-6 space-y-6">
      {/* Header */}
      <div className="text-left mb-8">
        <div className="flex items-center gap-3 mb-4">
          <div className="p-3 bg-primary/10 rounded-lg">
            <Zap className="w-8 h-8 text-primary" />
          </div>
          <div>
            <h1 className="text-2xl font-bold text-textPrimary">Smart Image Compressor</h1>
            <p className="text-textMuted text-sm">Reduce file size by 60-80% while maintaining professional quality with advanced smart compression.</p>
          </div>
        </div>
      </div>

      {!currentImage ? (
        /* Upload Area */
        <Card className="border-dashed">
          <CardContent className="p-8">
            <div
              {...getRootProps()}
              className={`border-2 border-dashed rounded-lg p-12 text-center cursor-pointer transition-colors
                ${isDragActive ? 'border-primary bg-primary/5' : 'border-border hover:border-primary/50'}`}
            >
              <input {...getInputProps()} />
              <div className="flex flex-col items-center space-y-4">
                <div className="p-4 bg-primary/10 rounded-full">
                  <ImageIcon className="w-12 h-12 text-primary" />
                </div>
                <div>
                  <p className="text-xl font-medium text-textPrimary">
                    {isDragActive ? 'Drop image here' : 'Upload Image to Compress'}
                  </p>
                  <p className="text-textMuted mt-2">
                    Drag & drop or click to select • Supports JPG, PNG, WebP, GIF
                  </p>
                </div>
                <Badge variant="outline" className="text-sm">
                  Fast • Simple • Effective
                </Badge>
              </div>
            </div>
          </CardContent>
        </Card>
      ) : (
        /* Main Interface */
        <div className="space-y-6">
          {/* Image Preview */}
          <Card>
            <CardHeader>
              <CardTitle>Image Preview</CardTitle>
              {compressedImage && (
                <div className="flex flex-wrap items-center gap-4 text-sm">
                  <div className="flex items-center gap-2">
                    <div className="w-3 h-3 bg-primary rounded-full"></div>
                    <span>Original: <strong>{formatFileSize(compressedImage.originalSize)}</strong></span>
                  </div>
                  <div className="flex items-center gap-2">
                    <div className="w-3 h-3 bg-green-500 rounded-full"></div>
                    <span>Compressed: <strong className="text-green-600">{formatFileSize(compressedImage.compressedSize)}</strong></span>
                  </div>
                  <Badge variant="secondary" className="bg-green-100 text-green-800">
                    {compressedImage.compressionRatio}% smaller
                  </Badge>
                </div>
              )}
            </CardHeader>
            <CardContent>
              <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                {/* Original */}
                <div className="space-y-2">
                  <h4 className="font-medium text-center">Original</h4>
                  <div className="bg-checkerboard rounded-lg overflow-hidden h-[300px] flex items-center justify-center">
                    <img
                      src={URL.createObjectURL(currentImage)}
                      alt="Original"
                      className="max-w-full max-h-full object-contain"
                    />
                  </div>
                  <p className="text-center text-sm text-textMuted">{formatFileSize(currentImage.size)}</p>
                </div>

                {/* Compressed */}
                <div className="space-y-2">
                  <h4 className="font-medium text-center">
                    {compressedImage ? 'Compressed' : 'Preview'}
                  </h4>
                  <div className="bg-checkerboard rounded-lg overflow-hidden h-[300px] flex items-center justify-center">
                    {compressedImage ? (
                      <img
                        src={compressedImage.compressedUrl}
                        alt="Compressed"
                        className="max-w-full max-h-full object-contain"
                      />
                    ) : (
                      <div className="text-center text-textMuted">
                        <Settings className="w-12 h-12 mx-auto mb-2 opacity-50" />
                        <p>Adjust settings and compress</p>
                      </div>
                    )}
                  </div>
                  <p className="text-center text-sm text-textMuted">
                    {compressedImage ? formatFileSize(compressedImage.compressedSize) : 'Not compressed yet'}
                  </p>
                </div>
              </div>
            </CardContent>
          </Card>

          {/* Settings Panel */}
          <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
            {/* Quality Settings */}
            <Card>
              <CardHeader className="pb-4">
                <CardTitle className="text-lg">Quality Control</CardTitle>
              </CardHeader>
              <CardContent className="space-y-4">
                <div>
                  <div className="flex items-center justify-between mb-3">
                    <Label className="font-medium">Quality</Label>
                    <div className="flex items-center gap-2">
                      <span className="text-lg font-bold">{settings.quality}%</span>
                      <Badge variant="outline" className={qualityInfo.color}>
                        {qualityInfo.label}
                      </Badge>
                    </div>
                  </div>
                  <Slider
                    value={[settings.quality]}
                    onValueChange={([value]) => {
                      setSettings(prev => ({ ...prev, quality: value }));
                      setSettingsChanged(true);
                    }}
                    min={1}
                    max={100}
                    step={1}
                    className="w-full"
                  />
                  <div className="flex justify-between text-xs text-textMuted mt-2">
                    <span>Smallest</span>
                    <span>Best Quality</span>
                  </div>
                </div>
              </CardContent>
            </Card>

            {/* Format Settings */}
            <Card>
              <CardHeader className="pb-4">
                <CardTitle className="text-lg">Format & Options</CardTitle>
              </CardHeader>
              <CardContent className="space-y-4">
                <div>
                  <Label className="text-sm font-medium mb-2 block">Output Format</Label>
                  <RadioGroup
                    value={settings.format}
                    onValueChange={(value) => {
                      setSettings(prev => ({ ...prev, format: value as 'jpeg' | 'png' | 'webp' }));
                      setSettingsChanged(true);
                    }}
                    className="grid grid-cols-3 gap-2"
                  >
                    <div className="flex items-center space-x-2">
                      <RadioGroupItem value="jpeg" id="jpeg" />
                      <Label htmlFor="jpeg" className="text-sm">JPG</Label>
                    </div>
                    <div className="flex items-center space-x-2">
                      <RadioGroupItem value="png" id="png" />
                      <Label htmlFor="png" className="text-sm">PNG</Label>
                    </div>
                    <div className="flex items-center space-x-2">
                      <RadioGroupItem value="webp" id="webp" />
                      <Label htmlFor="webp" className="text-sm">WebP</Label>
                    </div>
                  </RadioGroup>
                </div>
              </CardContent>
            </Card>
          </div>

          {/* Actions - Full Width */}
          <Card>
            <CardContent className="pt-6">
              <div className="space-y-3">
                {!compressedImage ? (
                  <Button
                    onClick={handleCompress}
                    disabled={isProcessing}
                    className="w-full"
                    size="lg"
                  >
                    {isProcessing ? (
                      <>
                        <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2"></div>
                        Compressing...
                      </>
                    ) : (
                      <>
                        <Zap className="w-4 h-4 mr-2" />
                        Compress Image
                      </>
                    )}
                  </Button>
                ) : (
                  <>
                    {/* Show re-compress button if settings changed */}
                    {hasSettingsChanged() && (
                      <Button
                        onClick={handleCompress}
                        disabled={isProcessing}
                        className="w-full"
                        size="lg"
                        variant="default"
                      >
                        {isProcessing ? (
                          <>
                            <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2"></div>
                            Re-compressing...
                          </>
                        ) : (
                          <>
                            <Zap className="w-4 h-4 mr-2" />
                            Re-compress with New Settings
                          </>
                        )}
                      </Button>
                    )}
                    
                    <Button
                      onClick={downloadCompressed}
                      className="w-full"
                      size="lg"
                      variant={hasSettingsChanged() ? "outline" : "default"}
                    >
                      <Download className="w-4 h-4 mr-2" />
                      Download Compressed
                    </Button>
                  </>
                )}
                
                <Button
                  variant="outline"
                  onClick={resetSettings}
                  className="w-full"
                  size="lg"
                >
                  <RotateCcw className="w-4 h-4 mr-2" />
                  Reset Settings
                </Button>
                
                <Button
                  variant="outline"
                  onClick={startOver}
                  className="w-full"
                  size="lg"
                >
                  <Upload className="w-4 h-4 mr-2" />
                  New Image
                </Button>
              </div>
            </CardContent>
          </Card>
        </div>
      )}

      {/* Recommended Tools */}
      <div className="mt-10">
        <h2 className="text-sm font-semibold text-textMuted uppercase tracking-wide mb-3">
          You Might Also Need
        </h2>
        <div className="flex flex-wrap gap-3">
          {recommendedTools.map((t) => (
            <Link
              key={t.id}
              href={`/tools/${t.id}`}
              className="flex items-center gap-2 px-4 py-2.5 rounded-full border border-border bg-surface hover:border-primary/40 hover:bg-accent transition-colors text-sm font-medium text-textPrimary"
              data-testid={`link-recommended-${t.id}`}
            >
              <t.icon className="w-4 h-4 text-primary" />
              {t.name}
            </Link>
          ))}
        </div>
      </div>

      {/* Description + Good to Know + FAQ */}
      <div className="mt-10 space-y-10">
        <section>
          <h2 className="text-2xl font-bold text-textPrimary mb-4">Shrink File Size Without Losing Quality</h2>
          <p className="text-textMuted text-base leading-relaxed">
            Shrink a photo down without watching the quality fall apart. Most images lose 60-80% of their file size
            with barely any visible difference, and a quality slider plus side-by-side preview let you see exactly
            what you're trading off before you commit to a download.
          </p>
        </section>

        {/* Good to know */}
        <section>
          <h3 className="text-lg font-bold text-textPrimary mb-4">Good to Know</h3>
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-3 bg-surface border border-border rounded-xl p-6">
            {goodToKnow.map((item, index) => (
              <div key={index} className="flex items-start gap-3">
                <item.icon className="w-4 h-4 text-primary mt-0.5 shrink-0" />
                <span className="text-sm text-textMuted">{item.text}</span>
              </div>
            ))}
          </div>
        </section>

        {/* FAQ */}
        <section>
          <h3 className="text-lg font-bold text-textPrimary mb-4">Frequently Asked Questions</h3>
          <Accordion type="single" collapsible className="space-y-3" data-testid="faq-accordion-compressor">
            <AccordionItem value="faq-1" className="border border-border rounded-lg px-5 bg-surface">
              <AccordionTrigger className="text-left font-medium text-textPrimary hover:text-primary text-sm">
                What quality setting should I use?
              </AccordionTrigger>
              <AccordionContent className="text-textMuted text-sm leading-relaxed">
                Around 75-85% works well for most web use — a solid balance of size and clarity. Go up to 90-95% for
                print or anything that needs to hold up close. For thumbnails or quick previews, 50-70% is usually
                plenty.
              </AccordionContent>
            </AccordionItem>

            <AccordionItem value="faq-2" className="border border-border rounded-lg px-5 bg-surface">
              <AccordionTrigger className="text-left font-medium text-textPrimary hover:text-primary text-sm">
                Which output format should I pick?
              </AccordionTrigger>
              <AccordionContent className="text-textMuted text-sm leading-relaxed">
                JPEG suits photos and busy images best. PNG is the right call for graphics, transparency, or sharp
                edges. WebP usually compresses smallest, though a few older browsers may not display it.
              </AccordionContent>
            </AccordionItem>

            <AccordionItem value="faq-3" className="border border-border rounded-lg px-5 bg-surface">
              <AccordionTrigger className="text-left font-medium text-textPrimary hover:text-primary text-sm">
                How much smaller will my file actually get?
              </AccordionTrigger>
              <AccordionContent className="text-textMuted text-sm leading-relaxed">
                Most images shrink by 60-80%, depending on the original file and the quality level you pick. Photos
                tend to compress more than screenshots or flat-color graphics.
              </AccordionContent>
            </AccordionItem>
          </Accordion>
        </section>
      </div>
    </div>
  );
}