"use client";

import { useState, useRef, ChangeEvent, useEffect } from "react";
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Button } from "@/components/ui/button";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Upload, Download, X, Trash2 } from "lucide-react";
import { toast } from "sonner";
import { cn } from "@/lib/utils";
import { Switch } from "@/components/ui/switch";
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";

export function ImageConverter() {
  const [images, setImages] = useState<File[]>([]);
  const [previewUrls, setPreviewUrls] = useState<string[]>([]);
  const [filenames, setFilenames] = useState<string[]>([]);
  const [width, setWidth] = useState<number | string>("");
  const [height, setHeight] = useState<number | string>("");
  const [format, setFormat] = useState<"png" | "jpeg" | "webp">("png");
  
  const [prefix, setPrefix] = useState<string>("");
  const [suffix, setSuffix] = useState<string>("");
  const [useCounter, setUseCounter] = useState<boolean>(false);
  const [counterStart, setCounterStart] = useState<number>(1);
  const [counterDigits, setCounterDigits] = useState<number>(3);

  const [isConverting, setIsConverting] = useState(false);
  const [isDraggingOver, setIsDraggingOver] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    return () => {
      previewUrls.forEach((url) => URL.revokeObjectURL(url));
    };
  }, [previewUrls]);

  const handleFiles = (files: FileList | null) => {
    if (!files || files.length === 0) return;

    const imageFiles = Array.from(files).filter((file) =>
      file.type.startsWith("image/")
    );

    if (imageFiles.length === 0) {
      toast.error("No valid image files found.");
      return;
    }

    const newImages = [...images, ...imageFiles];
    const newPreviewUrls = [
      ...previewUrls,
      ...imageFiles.map((file) => URL.createObjectURL(file)),
    ];
    const newFilenames = [
      ...filenames,
      ...imageFiles.map((file) =>
        file.name.substring(0, file.name.lastIndexOf("."))
      ),
    ];

    setImages(newImages);
    setPreviewUrls(newPreviewUrls);
    setFilenames(newFilenames);

    toast.success(`${imageFiles.length} image(s) added.`);
  };

  const handleImageChange = (e: ChangeEvent<HTMLInputElement>) => {
    handleFiles(e.target.files);
    if (e.target) e.target.value = "";
  };

  const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    setIsDraggingOver(true);
  };

  const handleDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    setIsDraggingOver(false);
  };

  const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    setIsDraggingOver(false);
    handleFiles(e.dataTransfer.files);
  };

  const handleRemoveImage = (indexToRemove: number) => {
    URL.revokeObjectURL(previewUrls[indexToRemove]);
    const newImages = images.filter((_, i) => i !== indexToRemove);
    const newPreviewUrls = previewUrls.filter((_, i) => i !== indexToRemove);
    const newFilenames = filenames.filter((_, i) => i !== indexToRemove);

    setImages(newImages);
    setPreviewUrls(newPreviewUrls);
    setFilenames(newFilenames);
  };

  const handleClearAll = () => {
    previewUrls.forEach((url) => URL.revokeObjectURL(url));
    setImages([]);
    setPreviewUrls([]);
    setFilenames([]);
    toast.info("All images cleared.");
  };

  const handleFilenameChange = (index: number, newName: string) => {
    const newFilenames = [...filenames];
    newFilenames[index] = newName;
    setFilenames(newFilenames);
  };

  const generateFinalFilename = (index: number) => {
    if (useCounter) {
      const counter = (index + counterStart).toString().padStart(counterDigits, '0');
      return `${prefix}${counter}${suffix}`;
    }
    const baseName = filenames[index] || "filename";
    return `${prefix}${baseName}${suffix}`;
  };

  const handleConvertAndDownload = async () => {
    if (images.length === 0 || !width || !height) {
      toast.error("Please upload images and set dimensions.");
      return;
    }

    setIsConverting(true);
    toast.info(`Starting conversion for ${images.length} images...`);

    const conversionPromises = images.map((image, index) => {
      return new Promise<void>((resolve, reject) => {
        const previewUrl = previewUrls[index];
        const img = new Image();
        img.crossOrigin = "anonymous";
        img.src = previewUrl;

        img.onload = () => {
          const canvas = document.createElement("canvas");
          canvas.width = Number(width);
          canvas.height = Number(height);
          const ctx = canvas.getContext("2d");

          if (ctx) {
            ctx.drawImage(img, 0, 0, Number(width), Number(height));
            const dataUrl = canvas.toDataURL(`image/${format}`);
            const link = document.createElement("a");
            link.href = dataUrl;
            const finalFilename = generateFinalFilename(index);
            link.download = `${finalFilename}_${width}x${height}.${format}`;
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            resolve();
          } else {
            reject(new Error(`Could not process ${image.name}.`));
          }
        };
        img.onerror = () => {
          reject(new Error(`Failed to load ${image.name} for conversion.`));
        };
      });
    });

    try {
      await Promise.all(conversionPromises);
      toast.success(`Successfully exported all ${images.length} images!`);
    } catch (error) {
      if (error instanceof Error) {
        toast.error(error.message);
      } else {
        toast.error("An unknown error occurred during conversion.");
      }
    } finally {
      setIsConverting(false);
    }
  };

  const hasImages = images.length > 0;

  return (
    <div className="grid grid-cols-1 lg:grid-cols-3 gap-8 w-full">
      <div className="lg:col-span-1 flex flex-col">
        <Accordion type="single" collapsible defaultValue="image-settings" className="w-full space-y-8">
          <Card>
            <AccordionItem value="image-settings" className="border-none">
              <AccordionTrigger className="p-6 hover:no-underline">
                <div className="text-left">
                  <CardTitle>Image Settings</CardTitle>
                  <CardDescription className="mt-1">
                    Adjust resolution and format for all uploaded images.
                  </CardDescription>
                </div>
              </AccordionTrigger>
              <AccordionContent className="px-6 pb-6">
                <div className="space-y-6">
                  <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
                    <div className="space-y-2">
                      <Label htmlFor="width">Width (px)</Label>
                      <Input id="width" type="number" placeholder="e.g., 1920" value={width} onChange={(e) => setWidth(e.target.value)} />
                    </div>
                    <div className="space-y-2">
                      <Label htmlFor="height">Height (px)</Label>
                      <Input id="height" type="number" placeholder="e.g., 1080" value={height} onChange={(e) => setHeight(e.target.value)} />
                    </div>
                  </div>
                  <div className="space-y-2">
                    <Label htmlFor="format">Format</Label>
                    <Select value={format} onValueChange={(value: "png" | "jpeg" | "webp") => setFormat(value)}>
                      <SelectTrigger id="format"><SelectValue placeholder="Select format" /></SelectTrigger>
                      <SelectContent>
                        <SelectItem value="png">PNG</SelectItem>
                        <SelectItem value="jpeg">JPEG</SelectItem>
                        <SelectItem value="webp">WEBP</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>
                </div>
                <CardFooter className="px-0 pt-6 pb-0 flex justify-between">
                  <Button variant="outline" onClick={() => fileInputRef.current?.click()}><Upload className="mr-2 h-4 w-4" />Upload</Button>
                  <Button onClick={handleConvertAndDownload} disabled={!hasImages || !width || !height || isConverting}>
                    <Download className="mr-2 h-4 w-4" />
                    {isConverting ? "Converting..." : `Download All (${images.length})`}
                  </Button>
                </CardFooter>
              </AccordionContent>
            </AccordionItem>
          </Card>

          <Card>
            <AccordionItem value="filename-settings" className="border-none">
              <AccordionTrigger className="p-6 hover:no-underline">
                <div className="text-left">
                  <CardTitle>Filename Settings</CardTitle>
                  <CardDescription className="mt-1">Customize the output filenames.</CardDescription>
                </div>
              </AccordionTrigger>
              <AccordionContent className="px-6 pb-6">
                <div className="space-y-6">
                  <div className="space-y-2">
                    <Label htmlFor="prefix">Prefix</Label>
                    <Input id="prefix" placeholder="e.g., travel-" value={prefix} onChange={(e) => setPrefix(e.target.value)} />
                  </div>
                  <div className="space-y-2">
                    <Label htmlFor="suffix">Suffix</Label>
                    <Input id="suffix" placeholder="e.g., -edit" value={suffix} onChange={(e) => setSuffix(e.target.value)} />
                  </div>
                  <div className="flex items-center space-x-2 pt-2">
                    <Switch id="use-counter" checked={useCounter} onCheckedChange={setUseCounter} />
                    <Label htmlFor="use-counter">Add sequential number</Label>
                  </div>
                  {useCounter && (
                    <div className="grid grid-cols-2 gap-4 pt-2">
                      <div className="space-y-2">
                        <Label htmlFor="counter-start">Start number</Label>
                        <Input
                          id="counter-start"
                          type="number"
                          value={counterStart}
                          onChange={(e) => setCounterStart(Math.max(0, Number(e.target.value)))}
                          min="0"
                        />
                      </div>
                      <div className="space-y-2">
                        <Label htmlFor="counter-digits">Padding digits</Label>
                        <Input
                          id="counter-digits"
                          type="number"
                          value={counterDigits}
                          onChange={(e) => setCounterDigits(Math.max(1, Number(e.target.value)))}
                          min="1"
                        />
                      </div>
                    </div>
                  )}
                </div>
              </AccordionContent>
            </AccordionItem>
          </Card>
        </Accordion>
      </div>

      <div className="lg:col-span-2 flex flex-col gap-8">
        <div
          className={cn(
            "w-full aspect-video rounded-lg border-2 border-dashed flex items-center justify-center relative transition-colors p-1 cursor-pointer",
            isDraggingOver ? "border-primary bg-accent" : "border-input"
          )}
          onDragOver={handleDragOver}
          onDragLeave={handleDragLeave}
          onDrop={handleDrop}
          onClick={() => fileInputRef.current?.click()}
        >
          <div className="flex flex-col items-center justify-center text-center text-muted-foreground">
            <Upload className="w-10 h-10 mb-4" />
            <p className="text-lg font-semibold">Click to upload or drag and drop</p>
            <p className="text-sm">Select files from your computer</p>
          </div>
          <Input type="file" ref={fileInputRef} onChange={handleImageChange} className="hidden" accept="image/*" multiple />
        </div>

        {hasImages && (
          <Card>
            <CardHeader>
              <div className="flex justify-between items-center">
                <CardTitle>Uploaded Images</CardTitle>
                <Button variant="ghost" size="sm" onClick={handleClearAll}><Trash2 className="mr-2 h-4 w-4" />Clear All</Button>
              </div>
            </CardHeader>
            <CardContent>
              <ScrollArea className="h-[400px] pr-4">
                <div className="space-y-4">
                  {previewUrls.map((url, index) => (
                    <div key={url} className="p-4 border rounded-lg flex items-center gap-4">
                      <img src={url} alt={`Preview ${index + 1}`} className="w-20 h-20 object-cover rounded-md shrink-0" />
                      <div className="flex-1 min-w-0">
                        <Label htmlFor={`filename-${index}`} className="text-xs text-muted-foreground">Base Name</Label>
                        <Input
                          id={`filename-${index}`}
                          value={filenames[index]}
                          onChange={(e) => handleFilenameChange(index, e.target.value)}
                          disabled={useCounter}
                          className="text-sm font-medium h-8 mt-1"
                        />
                        <p className="text-xs text-muted-foreground truncate mt-1" title={`${generateFinalFilename(index)}_${width || 'w'}x${height || 'h'}.${format}`}>
                          Final name: {generateFinalFilename(index)}.{format}
                        </p>
                      </div>
                      <Button variant="ghost" size="icon" className="shrink-0 text-gray-500 hover:text-destructive" onClick={() => handleRemoveImage(index)}>
                        <X className="h-4 w-4" />
                      </Button>
                    </div>
                  ))}
                </div>
              </ScrollArea>
            </CardContent>
          </Card>
        )}
      </div>
    </div>
  );
}