import { useState, useCallback, useEffect } from "react";
import type { ToolUiProps } from "../../core/plugins/plugin-types";
import type { ImageOptimizerOptions } from "./index";
import { Button } from "../../components/ui/Button";
import { Card } from "../../components/ui/Card";
import { Dropzone } from "../../components/ui/Dropzone";
import { Slider } from "../../components/ui/Slider";
import { Select } from "../../components/ui/Select";
import { useToolExecution } from "../../components/tool/useToolExecution";

const IMAGE_FORMATS = ["image/jpeg", "image/webp", "image/png"] as const;
type ImageFormat = (typeof IMAGE_FORMATS)[number];

function isImageFormat(value: string): value is ImageFormat {
  return IMAGE_FORMATS.includes(value as ImageFormat);
}

export default function ImageOptimizerUi({
  plugin,
}: ToolUiProps<ImageOptimizerOptions>) {
  const [files, setFiles] = useState<File[]>([]);
  const [previewUrls, setPreviewUrls] = useState<string[]>([]);

  const [quality, setQuality] = useState(80);
  const [format, setFormat] = useState<
    "image/jpeg" | "image/webp" | "image/png"
  >("image/webp");
  const { run, result, isExecuting, error, reset } = useToolExecution(plugin);

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

  const handleFilesDrop = useCallback((nextFiles: File[]) => {
    setFiles(nextFiles);
    setPreviewUrls(nextFiles.map((file) => URL.createObjectURL(file)));
    reset();
  }, [reset]);

  const handleRun = useCallback(async () => {
    if (files.length === 0) return;

    await run({ files }, { quality, format });
  }, [files, format, quality, run]);

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
        e.preventDefault();
        if (!isExecuting && files.length > 0) {
          handleRun();
        }
      }
    };
    window.addEventListener("keydown", handleKeyDown);
    return () => {
      window.removeEventListener("keydown", handleKeyDown);
    };
  }, [handleRun, isExecuting, files]);

  const downloadBlob = useCallback((blob: Blob, filename: string) => {
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }, []);

  return (
    <div className="p-[18px] md:p-[28px] max-w-5xl mx-auto">
      <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
        <div className="lg:col-span-2 space-y-6">
          <Card title="Upload Images">
            <Dropzone
              accept="image/jpeg,image/png,image/webp"
              multiple
              maxSizeMb={20}
              onFilesDrop={handleFilesDrop}
            />

            {previewUrls.length > 0 && (
              <div className="mt-6">
                <h4 className="text-sm font-medium text-gray-700 mb-3">
                  Previews:
                </h4>
                <div className="grid grid-cols-2 sm:grid-cols-3 gap-4">
                  {previewUrls.map((url, i) => (
                    <div
                      key={i}
                      className="relative aspect-square rounded-lg overflow-hidden border border-gray-200"
                    >
                      <img
                        src={url}
                        alt="Preview"
                        className="object-cover w-full h-full"
                      />
                    </div>
                  ))}
                </div>
              </div>
            )}
          </Card>

          {error && (
            <Card className="border-red-200">
              <div className="text-sm text-red-700">{error}</div>
            </Card>
          )}

          {result && result.type === "files" && (
            <Card
              title="Optimized Results"
              className="border-green-200 shadow-md"
            >
              {result.files.length > 1 && (
                <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-4 pb-4 border-b border-gray-100">
                  <span className="text-sm text-gray-500 font-medium">
                    Successfully optimized {result.files.length} images
                  </span>
                  <Button
                    variant="primary"
                    onClick={() => {
                      result.files.forEach((file) => {
                        downloadBlob(file.blob, file.name);
                      });
                    }}
                    className="w-full sm:w-auto shrink-0"
                  >
                    Download All ({result.files.length})
                  </Button>
                </div>
              )}

              <ul className="divide-y divide-gray-200 border border-gray-200 rounded-lg">
                {result.files.map((file, i) => {
                  const savedBytes =
                    (file.sizeBefore || 0) - (file.sizeAfter || 0);
                  const savedPercentage = file.sizeBefore
                    ? (savedBytes / file.sizeBefore) * 100
                    : 0;

                  return (
                    <li
                      key={i}
                      className="p-4 flex flex-col sm:flex-row sm:items-center justify-between gap-4 hover:bg-gray-50 transition-colors"
                    >
                      <div className="flex flex-col min-w-0 flex-1">
                        <span className="font-medium text-gray-900 truncate" title={file.name}>
                          {file.name}
                        </span>
                        <div className="text-sm text-gray-500 mt-1 flex flex-wrap items-center gap-2">
                          <span className="line-through">
                            {((file.sizeBefore || 0) / 1024).toFixed(1)} KB
                          </span>
                          <span className="text-green-600 font-medium">
                            {((file.sizeAfter || 0) / 1024).toFixed(1)} KB
                          </span>
                          <span className="text-xs bg-green-100 text-green-800 px-2 py-0.5 rounded-full">
                            -{savedPercentage.toFixed(0)}%
                          </span>
                        </div>
                      </div>
                      <Button
                        variant="secondary"
                        onClick={() => downloadBlob(file.blob, file.name)}
                        className="w-full sm:w-auto shrink-0 text-center"
                      >
                        Download
                      </Button>
                    </li>
                  );
                })}
              </ul>
            </Card>
          )}
        </div>

        <div className="space-y-6">
          <Card title="Settings">
            <div className="space-y-6">
              <Select
                label="Output Format"
                value={format}
                onChange={(e) => {
                  if (isImageFormat(e.target.value)) {
                    setFormat(e.target.value);
                  }
                }}
                options={[
                  { label: "WebP (Recommended)", value: "image/webp" },
                  { label: "JPEG", value: "image/jpeg" },
                  { label: "PNG", value: "image/png" },
                ]}
              />

              <Slider
                label="Quality"
                value={quality}
                onChange={(e) => setQuality(Number(e.target.value))}
                min={1}
                max={100}
              />

              <div className="pt-4 border-t border-gray-100">
                <Button
                  onClick={handleRun}
                  disabled={isExecuting || files.length === 0}
                  className="w-full"
                >
                  {isExecuting ? "Optimizing..." : "Optimize Images"}
                </Button>
              </div>
            </div>
          </Card>
        </div>
      </div>
    </div>
  );
}
