"use client";

import { useEffect, useRef, useState, type DragEvent } from "react";
import Drawer from "../common/Drawer";
import { ChevronDownIcon, CloseXIcon, UploadIcon } from "../dashboard/icons";
import { getImageUrl, handleImageError } from "@/lib/imageUrl";
import type { ProductDraft } from "@/types/product";

export type { ProductDraft };

export type CategoryOption = {
  id: string;
  name: string;
};

const emptyDraft: ProductDraft = {
  categoryId: "",
  category: "",
  title: "",
  description: "",
  manufacturer: "",
  modelNumber: "",
  price: "",
  currency: "AUD",
  stockUnit: "",
  negotiable: true,
  accessoriesIncluded: "",
  optionalAccessories: "",
  detailedNotes: "",
  images: [],
};

const MAX_IMAGES = 5;
// Keep in sync with LISTING_TITLE_MAX / LISTING_DESCRIPTION_MAX in the API
const TITLE_MAX = 250;
const DESCRIPTION_MAX = 20000;

function Stepper({ step }: { step: 1 | 2 }) {
  return (
    <div className="flex items-center gap-3">
      <div className="flex items-center gap-2">
        <span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-[#1657D9] text-[12px] font-semibold text-white">
          {step === 1 ? (
            "1"
          ) : (
            <svg width="12" height="12" viewBox="0 0 20 20" fill="none" aria-hidden="true">
              <path d="m5 10 3.5 3.5L15 6.5" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          )}
        </span>
        <span className="text-[13px] font-medium text-[#1657D9]">
          Product Details
        </span>
      </div>
      <div className={`h-px w-10 ${step === 2 ? "bg-[#1657D9]" : "bg-[#D0D5DD]"}`} />
      <div className="flex items-center gap-2">
        <span
          className={`flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-[12px] font-semibold ${
            step === 2 ? "bg-[#1657D9] text-white" : "border border-[#D0D5DD] text-[#98A2B3]"
          }`}
        >
          2
        </span>
        <span className={`text-[13px] font-medium ${step === 2 ? "text-[#1657D9]" : "text-[#98A2B3]"}`}>
          Upload &amp; Post
        </span>
      </div>
    </div>
  );
}

function Field({
  label,
  extra,
  required,
  error,
  children,
}: {
  label: string;
  extra?: string;
  required?: boolean;
  error?: string;
  children: React.ReactNode;
}) {
  return (
    <div>
      <div className="mb-1.5 flex items-center justify-between">
        <label className="text-[13px] font-medium text-[#344054]">
          {label} {required && <span className="text-red-500">*</span>}
        </label>
        {extra && <span className="text-[11px] text-[#98A2B3]">{extra}</span>}
      </div>
      {children}
      {error && <p className="mt-1 text-[11px] text-red-500">{error}</p>}
    </div>
  );
}

const inputClass =
  "h-10 w-full rounded-lg border border-[#D0D5DD] px-3 text-[13px] text-[#101828] outline-none placeholder:text-[#98A2B3] focus:border-[#1657D9]";
const textareaClass =
  "w-full rounded-lg border border-[#D0D5DD] px-3 py-2.5 text-[13px] text-[#101828] outline-none placeholder:text-[#98A2B3] focus:border-[#1657D9]";

function Select({
  value,
  onChange,
  children,
}: {
  value: string;
  onChange: (value: string) => void;
  children: React.ReactNode;
}) {
  return (
    <div className="relative">
      <select
        value={value}
        onChange={(e) => onChange(e.target.value)}
        className={`${inputClass} appearance-none bg-white pr-9`}
      >
        {children}
      </select>
      <span className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-[#667085]">
        <ChevronDownIcon />
      </span>
    </div>
  );
}

export default function AddProductModal({
  open,
  onClose,
  categories = [],
  onSave,
  mode = "add",
  initialDraft,
  loading = false,
}: {
  open: boolean;
  onClose: () => void;
  categories?: Array<CategoryOption | string>;
  onSave: (draft: ProductDraft, files: File[]) => Promise<void> | void;
  mode?: "add" | "edit";
  initialDraft?: ProductDraft;
  loading?: boolean;
}) {
  const [step, setStep] = useState<1 | 2>(1);
  const [draft, setDraft] = useState<ProductDraft>(() => initialDraft ?? emptyDraft);
  const [existingImages, setExistingImages] = useState<string[]>([]);
  const [newFiles, setNewFiles] = useState<Array<{ file: File; previewUrl: string }>>([]);
  const [dragOver, setDragOver] = useState(false);
  const [errors, setErrors] = useState<Record<string, string>>({});
  const fileInputRef = useRef<HTMLInputElement | null>(null);

  // Sync draft and existing images whenever modal opens or initialDraft changes
  useEffect(() => {
    if (open) {
      setStep(1);
      setErrors({});
      const current = initialDraft ? { ...emptyDraft, ...initialDraft } : { ...emptyDraft };
      setDraft(current);
      setExistingImages(current.images || []);
      setNewFiles([]);
    }
  }, [open, initialDraft]);

  // Clean up object URLs on unmount or reset
  useEffect(() => {
    return () => {
      newFiles.forEach((nf) => URL.revokeObjectURL(nf.previewUrl));
    };
  }, [newFiles]);

  const set = <K extends keyof ProductDraft>(key: K, value: ProductDraft[K]) => {
    setDraft((prev) => ({ ...prev, [key]: value }));
    if (errors[key]) {
      setErrors((prev) => {
        const next = { ...prev };
        delete next[key];
        return next;
      });
    }
  };

  const handleClose = () => {
    setStep(1);
    setErrors({});
    newFiles.forEach((nf) => URL.revokeObjectURL(nf.previewUrl));
    setNewFiles([]);
    onClose();
  };

  const totalImageCount = existingImages.length + newFiles.length;

  const addFiles = (files: FileList | null) => {
    if (!files) return;
    const remainingSlots = Math.max(0, MAX_IMAGES - totalImageCount);
    if (remainingSlots <= 0) return;

    const filesToAdd = Array.from(files).slice(0, remainingSlots);
    const addedItems = filesToAdd.map((file) => ({
      file,
      previewUrl: URL.createObjectURL(file),
    }));

    setNewFiles((prev) => [...prev, ...addedItems]);
  };

  const handleDrop = (e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    setDragOver(false);
    addFiles(e.dataTransfer.files);
  };

  const removeExistingImage = (index: number) => {
    setExistingImages((prev) => prev.filter((_, i) => i !== index));
  };

  const removeNewFile = (index: number) => {
    setNewFiles((prev) => {
      const target = prev[index];
      if (target) {
        URL.revokeObjectURL(target.previewUrl);
      }
      return prev.filter((_, i) => i !== index);
    });
  };

  const validateStep1 = (): boolean => {
    const newErrors: Record<string, string> = {};
    if (!draft.title.trim()) {
      newErrors.title = "Product title is required.";
    } else if (draft.title.trim().length > TITLE_MAX) {
      // Older products may have a long title; it has to be shortened before saving
      newErrors.title = `Title must be ${TITLE_MAX} characters or fewer. Move the extra detail into the description.`;
    }
    if (!draft.description.trim()) {
      newErrors.description = "Product description is required.";
    }
    const cleanPrice = draft.price.replace(/[^0-9.]/g, "");
    if (!cleanPrice || isNaN(Number(cleanPrice)) || Number(cleanPrice) < 0) {
      newErrors.price = "A valid price is required.";
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleNextStep = () => {
    if (validateStep1()) {
      setStep(2);
    }
  };

  const handleSubmit = async () => {
    const finalDraft: ProductDraft = {
      ...draft,
      images: existingImages,
    };
    const filesToUpload = newFiles.map((nf) => nf.file);
    await onSave(finalDraft, filesToUpload);
  };

  // Normalize category options to { id, name }
  const normalizedCategories: CategoryOption[] = categories.map((c) =>
    typeof c === "string" ? { id: c, name: c } : c
  );

  return (
    <Drawer
      open={open}
      onClose={handleClose}
      title={mode === "edit" ? "Edit Product" : "Add new Product"}
      width="873px"
      footer={
        <div className="flex items-center justify-end gap-3">
          <button
            type="button"
            disabled={loading}
            onClick={step === 1 ? handleClose : () => setStep(1)}
            className="h-10 rounded-lg bg-[#F2F4F7] px-5 text-[13px] font-medium text-[#344054] transition-colors hover:bg-[#E4E7EC] disabled:opacity-50"
          >
            {step === 1 ? "Cancel" : "Back"}
          </button>
          <button
            type="button"
            disabled={loading}
            onClick={step === 1 ? handleNextStep : handleSubmit}
            className="flex h-10 items-center justify-center gap-2 rounded-lg bg-[#1657D9] px-5 text-[13px] font-medium text-white transition-colors hover:bg-[#1445B0] disabled:opacity-50"
          >
            {loading ? (
              <>
                <svg className="h-4 w-4 animate-spin text-white" viewBox="0 0 24 24" fill="none">
                  <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
                  <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
                </svg>
                <span>Saving...</span>
              </>
            ) : step === 1 ? (
              "Save & Next"
            ) : mode === "edit" ? (
              "Update Product"
            ) : (
              "Publish Product"
            )}
          </button>
        </div>
      }
    >
      <div className="-mx-5 -mt-4 mb-5 border-b border-[#E4E7EC] px-5 py-4">
        <Stepper step={step} />
      </div>

      <div>
        {step === 1 ? (
          <div className="flex flex-col gap-4">
            <h3 className="text-[14px] font-semibold text-[#101828]">Product Details</h3>

            <Field label="Category" extra="(Optional)">
              <Select
                value={draft.categoryId || ""}
                onChange={(val) => {
                  const match = normalizedCategories.find((c) => c.id === val);
                  set("categoryId", val);
                  set("category", match ? match.name : "");
                }}
              >
                <option value="">Select Category</option>
                {/* Editing a product whose category was inactivated later: keep showing it (it can't be picked again) */}
                {draft.categoryId && !normalizedCategories.some((c) => c.id === draft.categoryId) && (
                  <option value={draft.categoryId}>{draft.category || "Current category"} (inactive)</option>
                )}
                {normalizedCategories.map((c) => (
                  <option key={c.id} value={c.id}>
                    {c.name}
                  </option>
                ))}
              </Select>
            </Field>

            <Field
              label="Product Title"
              required
              extra={`${draft.title.length}/${TITLE_MAX}`}
              error={errors.title}
            >
              <input
                type="text"
                maxLength={TITLE_MAX}
                value={draft.title}
                onChange={(e) => set("title", e.target.value)}
                placeholder="e.g. Sony FX6 Cinema Camera Body"
                className={`${inputClass} ${errors.title ? "border-red-500" : ""}`}
              />
            </Field>

            <Field
              label="Product Description"
              required
              extra={`${draft.description.length}/${DESCRIPTION_MAX}`}
              error={errors.description}
            >
              <textarea
                rows={4}
                maxLength={DESCRIPTION_MAX}
                value={draft.description}
                onChange={(e) => set("description", e.target.value)}
                placeholder="Describe the product: what it is, key features, condition and what's in the box..."
                className={`${textareaClass} ${errors.description ? "border-red-500" : ""}`}
              />
            </Field>

            <div className="grid grid-cols-2 gap-3">
              <Field label="Manufacturer">
                <input
                  type="text"
                  value={draft.manufacturer}
                  onChange={(e) => set("manufacturer", e.target.value)}
                  placeholder="e.g. Sony"
                  className={inputClass}
                />
              </Field>
              <Field label="Model Number">
                <input
                  type="text"
                  value={draft.modelNumber}
                  onChange={(e) => set("modelNumber", e.target.value)}
                  placeholder="e.g. ILME-FX6V"
                  className={inputClass}
                />
              </Field>
            </div>

            <div className="grid grid-cols-3 gap-3">
              <Field label="Budget / Price" required error={errors.price}>
                <input
                  type="text"
                  value={draft.price}
                  onChange={(e) => set("price", e.target.value)}
                  placeholder="e.g. 8,999"
                  className={`${inputClass} ${errors.price ? "border-red-500" : ""}`}
                />
              </Field>
              <Field label="Currency">
                {/* Australian marketplace: AUD only (enforced by the API) */}
                <input
                  value="AUD"
                  readOnly
                  tabIndex={-1}
                  aria-label="Currency (Australian dollars only)"
                  className={`${inputClass} cursor-not-allowed bg-gray-50 text-gray-500`}
                />
              </Field>
              <Field label="Stock Unit" extra="(Optional)">
                <input
                  type="number"
                  min="0"
                  value={draft.stockUnit}
                  onChange={(e) => set("stockUnit", e.target.value)}
                  placeholder="e.g. 10"
                  className={inputClass}
                />
              </Field>
            </div>

            <div>
              <p className="mb-2 text-[13px] font-medium text-[#344054]">Is Price Negotiable?</p>
              <div className="flex items-center gap-6">
                <label className="flex cursor-pointer select-none items-center gap-2 text-[13px] text-[#344054]">
                  <input
                    type="radio"
                    name="negotiable"
                    checked={draft.negotiable}
                    onChange={() => set("negotiable", true)}
                    className="h-4 w-4 cursor-pointer accent-[#1657D9]"
                  />
                  Yes, open to reasonable offers
                </label>
                <label className="flex cursor-pointer select-none items-center gap-2 text-[13px] text-[#344054]">
                  <input
                    type="radio"
                    name="negotiable"
                    checked={!draft.negotiable}
                    onChange={() => set("negotiable", false)}
                    className="h-4 w-4 cursor-pointer accent-[#1657D9]"
                  />
                  No, firm price
                </label>
              </div>
            </div>

            <h3 className="mt-1 text-[14px] font-semibold text-[#101828]">Additional Information &amp; Notes</h3>

            <Field label="Accessories Included" extra="(Optional)">
              <textarea
                rows={2}
                value={draft.accessoriesIncluded}
                onChange={(e) => set("accessoriesIncluded", e.target.value)}
                placeholder="e.g. Top handle, grip remote, side bracket, LCD viewfinder..."
                className={textareaClass}
              />
            </Field>

            <Field label="Optional Accessories" extra="(Optional)">
              <textarea
                rows={2}
                value={draft.optionalAccessories}
                onChange={(e) => set("optionalAccessories", e.target.value)}
                placeholder="e.g. Extra batteries, external raw recorder, V-mount plate..."
                className={textareaClass}
              />
            </Field>

            <Field label="Detailed Notes / Specifications" extra="(Optional)">
              <textarea
                rows={3}
                value={draft.detailedNotes}
                onChange={(e) => set("detailedNotes", e.target.value)}
                placeholder="Write detailed specifications, warranty notes, packaging info..."
                className={textareaClass}
              />
            </Field>
          </div>
        ) : (
          <div className="flex flex-col gap-4">
            <div>
              <h3 className="text-[14px] font-semibold text-[#101828]">Upload Pictures</h3>
              <p className="mt-1 text-[12px] text-[#667085]">
                Upload up to {MAX_IMAGES} pictures ({totalImageCount}/{MAX_IMAGES} used).
              </p>
            </div>

            {totalImageCount < MAX_IMAGES && (
              <div
                onClick={() => fileInputRef.current?.click()}
                onDragOver={(e) => {
                  e.preventDefault();
                  setDragOver(true);
                }}
                onDragLeave={() => setDragOver(false)}
                onDrop={handleDrop}
                className={`flex cursor-pointer flex-col items-center justify-center gap-1.5 rounded-xl border-2 border-dashed px-6 py-10 text-center transition-colors ${
                  dragOver ? "border-[#1657D9] bg-[#F5F8FF]" : "border-[#B9D0FF] bg-[#F9FBFF]"
                }`}
              >
                <span className="text-[#1657D9]">
                  <UploadIcon />
                </span>
                <p className="text-[13px] font-semibold text-[#1657D9]">Click to upload or drag and drop</p>
                <p className="text-[11px] text-[#98A2B3]">
                  High-res PNG, JPG, or WebP up to 10MB each.
                </p>
                <input
                  ref={fileInputRef}
                  type="file"
                  accept="image/png,image/jpeg,image/webp"
                  multiple
                  className="hidden"
                  onChange={(e) => {
                    addFiles(e.target.files);
                    e.target.value = "";
                  }}
                />
              </div>
            )}

            {totalImageCount > 0 && (
              <div className="flex flex-wrap gap-3">
                {/* Existing Images */}
                {existingImages.map((src, index) => (
                  <div
                    key={`existing-${src}-${index}`}
                    className="group relative h-[84px] w-[84px] overflow-hidden rounded-lg border border-[#E4E7EC] bg-white shadow-sm"
                  >
                    {/* eslint-disable-next-line @next/next/no-img-element */}
                    <img
                      src={getImageUrl(src)}
                      alt={`Product image ${index + 1}`}
                      className="h-full w-full object-cover"
                      onError={handleImageError}
                    />
                    <button
                      type="button"
                      onClick={() => removeExistingImage(index)}
                      aria-label="Remove image"
                      className="absolute right-1 top-1 flex h-5 w-5 items-center justify-center rounded-full bg-black/60 text-white transition-opacity hover:bg-black/80"
                    >
                      <CloseXIcon className="h-2.5 w-2.5" />
                    </button>
                    <span className="absolute bottom-0 inset-x-0 bg-black/50 py-0.5 text-center text-[9px] text-white">
                      Existing
                    </span>
                  </div>
                ))}

                {/* New Files */}
                {newFiles.map((nf, index) => (
                  <div
                    key={`new-${nf.previewUrl}-${index}`}
                    className="group relative h-[84px] w-[84px] overflow-hidden rounded-lg border border-[#1657D9] bg-white shadow-sm"
                  >
                    {/* eslint-disable-next-line @next/next/no-img-element */}
                    <img
                      src={nf.previewUrl}
                      alt={`New image ${index + 1}`}
                      className="h-full w-full object-cover"
                    />
                    <button
                      type="button"
                      onClick={() => removeNewFile(index)}
                      aria-label="Remove image"
                      className="absolute right-1 top-1 flex h-5 w-5 items-center justify-center rounded-full bg-red-600 text-white transition-opacity hover:bg-red-700"
                    >
                      <CloseXIcon className="h-2.5 w-2.5" />
                    </button>
                    <span className="absolute bottom-0 inset-x-0 bg-[#1657D9]/80 py-0.5 text-center text-[9px] text-white">
                      New
                    </span>
                  </div>
                ))}
              </div>
            )}
          </div>
        )}
      </div>
    </Drawer>
  );
}
