"use client";

import { useState } from "react";
import Cropper, { type Area } from "react-easy-crop";
import { ImagePlus, Upload } from "lucide-react";
import { uploadBlogImage } from "@/lib/storage";
import { toStorageUrl } from "@/lib/storage-url";

function createImage(url: string) {
  return new Promise<HTMLImageElement>((resolve, reject) => {
    const image = new Image();
    image.addEventListener("load", () => resolve(image));
    image.addEventListener("error", reject);
    image.src = url;
  });
}

async function getCroppedWebp(imageSrc: string, crop: Area) {
  const image = await createImage(imageSrc);
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");

  if (!ctx) {
    throw new Error("Image cropper is not available");
  }

  canvas.width = 1200;
  canvas.height = 800;
  ctx.drawImage(image, crop.x, crop.y, crop.width, crop.height, 0, 0, canvas.width, canvas.height);

  return new Promise<Blob>((resolve, reject) => {
    canvas.toBlob(
      (blob) => {
        if (!blob) {
          reject(new Error("Could not create cropped image"));
          return;
        }

        resolve(blob);
      },
      "image/webp",
      0.9,
    );
  });
}

type BlogImageUploaderProps = {
  slug: string;
  title: string;
  currentImageUrl?: string;
  currentImageAlt?: string;
  onUploaded: (imageUrl: string) => void;
};

export function BlogImageUploader({
  slug,
  title,
  currentImageUrl,
  currentImageAlt,
  onUploaded,
}: BlogImageUploaderProps) {
  const [imageSrc, setImageSrc] = useState("");
  const [crop, setCrop] = useState({ x: 0, y: 0 });
  const [zoom, setZoom] = useState(1);
  const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area | null>(null);
  const [uploadStatus, setUploadStatus] = useState<"idle" | "uploading" | "done" | "error">("idle");
  const [uploadMessage, setUploadMessage] = useState("");

  function selectImage(file: File | undefined) {
    if (!file) {
      return;
    }

    setImageSrc(URL.createObjectURL(file));
    setUploadStatus("idle");
    setUploadMessage("");
  }

  async function cropAndUploadImage() {
    if (!imageSrc || !croppedAreaPixels || !slug) {
      setUploadStatus("error");
      setUploadMessage("Add a title or slug and select an image before uploading.");
      return;
    }

    setUploadStatus("uploading");
    setUploadMessage("");

    try {
      const croppedImage = await getCroppedWebp(imageSrc, croppedAreaPixels);
      const imageUrl = await uploadBlogImage(croppedImage, slug);

      onUploaded(imageUrl);
      setUploadStatus("done");
      setUploadMessage(`Uploaded as ridenrevive/blogs/${slug}.webp`);
    } catch (error) {
      setUploadStatus("error");
      setUploadMessage(
        error instanceof Error
          ? error.message
          : "Could not upload image. Check Firebase configuration.",
      );
    }
  }

  const label = "mb-1.5 block text-xs font-black uppercase tracking-[0.14em] text-muted-foreground";
  const previewImageUrl = toStorageUrl(currentImageUrl);

  return (
    <div className="rounded-lg border border-border bg-slate-50 p-4">
      <div className="mb-3 flex items-center gap-2 text-sm font-black text-foreground">
        <ImagePlus className="h-4 w-4 text-primary" />
        Image cropper 3:2
      </div>
      {previewImageUrl ? (
        <div className="mb-4 max-w-xs overflow-hidden rounded-md border border-border bg-white">
          <img
            src={previewImageUrl}
            alt={currentImageAlt || title || "Current blog image"}
            className="aspect-[3/2] w-full object-cover"
          />
          <p className="border-t border-border px-3 py-2 text-xs font-semibold text-muted-foreground">
            Current image
          </p>
        </div>
      ) : null}
      <div className="grid gap-4 lg:grid-cols-[1fr_220px]">
        <div className="relative h-72 overflow-hidden rounded-md bg-slate-950">
          {imageSrc ? (
            <Cropper
              image={imageSrc}
              crop={crop}
              zoom={zoom}
              aspect={3 / 2}
              onCropChange={setCrop}
              onZoomChange={setZoom}
              onCropComplete={(_croppedArea, croppedPixels) => setCroppedAreaPixels(croppedPixels)}
            />
          ) : (
            <div className="grid h-full place-items-center text-center text-sm font-semibold text-white/70">
              Select an image to crop at 3:2
            </div>
          )}
        </div>
        <div className="space-y-3">
          <input
            type="file"
            accept="image/*"
            onChange={(event) => selectImage(event.target.files?.[0])}
            className="block w-full text-sm font-semibold text-muted-foreground file:mr-3 file:rounded-md file:border-0 file:bg-primary file:px-3 file:py-2 file:text-sm file:font-black file:text-primary-foreground"
          />
          <div>
            <label className={label}>Zoom</label>
            <input
              type="range"
              min={1}
              max={3}
              step={0.1}
              value={zoom}
              onChange={(event) => setZoom(Number(event.target.value))}
              className="w-full"
            />
          </div>
          <p className="text-xs font-semibold text-muted-foreground">
            Image will be renamed to{" "}
            <span className="font-black text-foreground">
              ridenrevive/blogs/{slug || "blog-slug"}.webp
            </span>
          </p>
          <button
            type="button"
            onClick={cropAndUploadImage}
            disabled={uploadStatus === "uploading"}
            className="inline-flex h-10 w-full items-center justify-center gap-2 rounded-md bg-primary px-4 text-sm font-black text-primary-foreground transition hover:opacity-95 disabled:opacity-70"
          >
            <Upload className="h-4 w-4" />
            {uploadStatus === "uploading" ? "Uploading..." : "Upload cropped image"}
          </button>
          {uploadMessage ? (
            <p
              className={`text-xs font-bold ${
                uploadStatus === "error" ? "text-destructive" : "text-primary"
              }`}
            >
              {uploadMessage}
            </p>
          ) : null}
          {title ? (
            <p className="text-xs font-semibold text-muted-foreground">
              Alt text can use: {title} image
            </p>
          ) : null}
        </div>
      </div>
    </div>
  );
}
