import { useState, useRef, useCallback, useEffect } from "react";
import { AlertTriangle, CheckCircle, Loader2 } from "lucide-react";
import { cn } from "../lib/utils";
import { get } from "../lib/api";
import {
  type Draft,
  type EffectDraft,
  type FullItem,
  defaultDraft,
  draftFromItem,
  makeEffect,
} from "./components/ItemStudioTypes";
import {
  buildBasePayload,
  submitEditItem,
  submitCreateItem,
} from "./components/ItemStudioSubmit";
import {
  IdentitySection,
  ClassificationSection,
  EconomySection,
  ArtworkSection,
  EffectsSection,
} from "./components/ItemStudioForm";
import { ItemPreviewCard } from "./components/ItemPreviewCard";

// ===== Main Export =====

export function ItemStudio({
  onSuccess,
  editItemId,
}: {
  onSuccess: () => void;
  editItemId?: number;
}) {
  const [draft, setDraft] = useState<Draft>(defaultDraft());
  const [imageMode, setImageMode] = useState<"upload" | "url">("upload");
  const [imageFile, setImageFile] = useState<File | null>(null);
  const [imagePreview, setImagePreview] = useState<string | null>(null);
  const [iconUrlInput, setIconUrlInput] = useState("");
  const [imageUrlInput, setImageUrlInput] = useState("");
  const [dragOver, setDragOver] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState(false);
  const [validationErrors, setValidationErrors] = useState<
    Record<string, string>
  >({});
  const [loadingItem, setLoadingItem] = useState(false);

  const initialEditStateRef = useRef<{
    draft: Draft;
    iconUrlInput: string;
    imageUrlInput: string;
  } | null>(null);

  const fileInputRef = useRef<HTMLInputElement>(null);

  const update = useCallback((fields: Partial<Draft>) => {
    setDraft((d) => ({ ...d, ...fields }));
  }, []);

  useEffect(() => {
    if (!editItemId) {
      initialEditStateRef.current = null;
      setDraft(defaultDraft());
      setImageMode("upload");
      setIconUrlInput("");
      setImageUrlInput("");
      setImageFile(null);
      setImagePreview(null);
      setValidationErrors({});
      setError(null);
      return;
    }

    let cancelled = false;
    setLoadingItem(true);
    setError(null);

    get<FullItem>(`/api/items/${editItemId}`)
      .then(async (item) => {
        if (cancelled) return;
        const newDraft = draftFromItem(item);

        // Resolve item names for ITEM-type loot pool entries
        const itemIdsToResolve = new Set<number>();
        for (const eff of newDraft.effects) {
          if (eff.kind === "LOOTBOX") {
            for (const entry of eff.pool) {
              if (entry.type === "ITEM" && entry.itemId) {
                itemIdsToResolve.add(Number(entry.itemId));
              }
            }
          }
        }

        if (itemIdsToResolve.size > 0) {
          const resolved = await Promise.all(
            [...itemIdsToResolve].map((id) =>
              get<{ id: number; name: string; rarity: string }>(`/api/items/${id}`).catch(() => null)
            )
          );
          const itemMap = new Map(
            resolved.filter(Boolean).map((i) => [i!.id, i!])
          );

          for (const eff of newDraft.effects) {
            if (eff.kind === "LOOTBOX") {
              for (const entry of eff.pool) {
                const info = itemMap.get(Number(entry.itemId));
                if (info) {
                  entry.selectedItemName = info.name;
                  entry.selectedItemRarity = info.rarity;
                }
              }
            }
          }
        }

        if (cancelled) return;
        const newIconUrl = item.iconUrl ?? "";
        const newImageUrl = item.imageUrl ?? "";
        setDraft(newDraft);
        setImageMode("url");
        setIconUrlInput(newIconUrl);
        setImageUrlInput(newImageUrl);
        setImageFile(null);
        setImagePreview(null);
        setValidationErrors({});
        setError(null);
        initialEditStateRef.current = {
          draft: newDraft,
          iconUrlInput: newIconUrl,
          imageUrlInput: newImageUrl,
        };
      })
      .catch((e) => {
        if (cancelled) return;
        setError(e instanceof Error ? e.message : "Failed to load item");
      })
      .finally(() => {
        if (!cancelled) setLoadingItem(false);
      });

    return () => {
      cancelled = true;
    };
  }, [editItemId]);

  const handleImageFile = useCallback(
    (file: File) => {
      if (imagePreview) URL.revokeObjectURL(imagePreview);
      setImageFile(file);
      setImagePreview(URL.createObjectURL(file));
    },
    [imagePreview]
  );

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    setDragOver(false);
    const file = e.dataTransfer.files[0];
    if (file && file.type.startsWith("image/")) handleImageFile(file);
  };

  const clearImage = useCallback(() => {
    if (imagePreview) URL.revokeObjectURL(imagePreview);
    setImageFile(null);
    setImagePreview(null);
    if (fileInputRef.current) fileInputRef.current.value = "";
  }, [imagePreview]);

  const addEffect = () => {
    update({ effects: [...draft.effects, makeEffect("ADD_XP")] });
  };

  const updateEffect = (i: number, updated: EffectDraft) => {
    const effects = [...draft.effects];
    effects[i] = updated;
    update({ effects });
  };

  const removeEffect = (i: number) => {
    update({ effects: draft.effects.filter((_, idx) => idx !== i) });
  };

  const validate = (): boolean => {
    const errs: Record<string, string> = {};
    if (!draft.name.trim()) errs.name = "Name is required";
    if (imageMode === "upload" && !imageFile && !editItemId)
      errs.image = "Please upload an image";
    if (imageMode === "url" && !iconUrlInput.trim())
      errs.iconUrl = "Icon URL is required";
    if (imageMode === "url" && !imageUrlInput.trim())
      errs.imageUrl = "Image URL is required";
    setValidationErrors(errs);
    return Object.keys(errs).length === 0;
  };

  const handleSubmit = async () => {
    if (!validate()) return;
    setSubmitting(true);
    setError(null);

    try {
      const basePayload = buildBasePayload(draft);

      if (editItemId) {
        await submitEditItem({
          editItemId,
          basePayload,
          imageMode,
          iconUrlInput,
          imageUrlInput,
          imageFile,
        });

        setSuccess(true);
        setTimeout(() => {
          setSuccess(false);
          onSuccess();
        }, 1200);
      } else {
        await submitCreateItem({
          basePayload,
          imageMode,
          iconUrlInput,
          imageUrlInput,
          imageFile,
        });

        setSuccess(true);
        setTimeout(() => {
          setDraft(defaultDraft());
          clearImage();
          setIconUrlInput("");
          setImageUrlInput("");
          setValidationErrors({});
          setSuccess(false);
          onSuccess();
        }, 1200);
      }
    } catch (e) {
      setError(
        e instanceof Error
          ? e.message
          : editItemId
          ? "Failed to save item"
          : "Failed to create item"
      );
    } finally {
      setSubmitting(false);
    }
  };

  const handleReset = () => {
    if (editItemId && initialEditStateRef.current) {
      const s = initialEditStateRef.current;
      setDraft(s.draft);
      setImageMode("url");
      setIconUrlInput(s.iconUrlInput);
      setImageUrlInput(s.imageUrlInput);
    } else {
      setDraft(defaultDraft());
      setImageMode("upload");
      setIconUrlInput("");
      setImageUrlInput("");
    }
    clearImage();
    setValidationErrors({});
    setError(null);
  };

  const previewImageSrc =
    imageMode === "upload" ? imagePreview : iconUrlInput || null;

  if (loadingItem) {
    return (
      <div className="flex items-center justify-center py-20 gap-3 text-text-tertiary">
        <Loader2 className="w-5 h-5 animate-spin" />
        <span className="text-sm">Loading item{"\u2026"}</span>
      </div>
    );
  }

  return (
    <div className="grid grid-cols-[1fr_300px] gap-6 items-start pb-8">
      {/* -- Left: Form -- */}
      <div className="space-y-4">
        {editItemId && (
          <div className="flex items-center gap-2 text-xs text-text-tertiary">
            <span>Editing item #{editItemId}</span>
          </div>
        )}

        <IdentitySection
          draft={draft}
          update={update}
          validationErrors={validationErrors}
        />
        <ClassificationSection draft={draft} update={update} />
        <EconomySection draft={draft} update={update} />
        <ArtworkSection
          imageMode={imageMode}
          setImageMode={setImageMode}
          imageFile={imageFile}
          imagePreview={imagePreview}
          iconUrlInput={iconUrlInput}
          setIconUrlInput={setIconUrlInput}
          imageUrlInput={imageUrlInput}
          setImageUrlInput={setImageUrlInput}
          dragOver={dragOver}
          setDragOver={setDragOver}
          handleDrop={handleDrop}
          clearImage={clearImage}
          handleImageFile={handleImageFile}
          fileInputRef={fileInputRef}
          validationErrors={validationErrors}
        />
        <EffectsSection
          draft={draft}
          update={update}
          updateEffect={updateEffect}
          removeEffect={removeEffect}
          addEffect={addEffect}
        />

        {/* Error */}
        {error && (
          <div className="flex items-start gap-3 p-4 bg-destructive/10 border border-destructive/30 rounded-lg">
            <AlertTriangle className="w-5 h-5 text-destructive shrink-0 mt-0.5" />
            <p className="text-sm text-destructive">{error}</p>
          </div>
        )}

        {/* Actions */}
        <div className="flex items-center justify-between pt-2">
          <button
            onClick={handleReset}
            disabled={submitting}
            className={cn(
              "px-4 py-2 rounded-lg border border-border text-sm text-text-tertiary",
              "hover:text-foreground hover:border-primary/40 transition-colors",
              "disabled:opacity-50 disabled:cursor-not-allowed"
            )}
          >
            Reset
          </button>
          <button
            onClick={handleSubmit}
            disabled={submitting || success}
            className={cn(
              "px-6 py-2 rounded-lg text-sm font-semibold transition-all flex items-center gap-2",
              success
                ? "bg-success text-white"
                : "bg-primary hover:bg-primary/90 text-white",
              "disabled:opacity-70 disabled:cursor-not-allowed"
            )}
          >
            {submitting && <Loader2 className="w-4 h-4 animate-spin" />}
            {success ? (
              <>
                <CheckCircle className="w-4 h-4" />
                {editItemId ? "Saved!" : "Created!"}
              </>
            ) : submitting ? (
              editItemId ? "Saving..." : "Creating..."
            ) : (
              editItemId ? "Save Changes" : "Create Item"
            )}
          </button>
        </div>
      </div>

      {/* -- Right: Live Preview -- */}
      <div className="sticky top-6 space-y-3">
        <p className="text-xs font-semibold text-text-tertiary uppercase tracking-wider">
          Live Preview
        </p>
        <ItemPreviewCard draft={draft} previewImageSrc={previewImageSrc} />
        <p className="text-xs text-text-tertiary text-center opacity-60">
          Updates as you type
        </p>
      </div>
    </div>
  );
}
