"use client";

import { useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { useParams, useRouter } from "next/navigation";
import { useAuth } from "@/context/AuthContext";
import { useApi } from "@/lib/api";
import Image from "next/image";

type BuildDto = {
  uuid: string;
  title: string;
  description?: string | null;
  isPublic?: boolean | null;
  createdAt?: string | null;
  updatedAt?: string | null;
  items?: Array<{
    slot: string;
    productId: number;
    productName?: string | null;
    productBrand?: string | null;
    bestPrice?: number | string | null; // backend may serialize BigDecimal as string
  }>;
  photos?: BuildPhotoDto[];
};

type BuildPhotoDto = {
  uuid: string;
  url: string;
  caption?: string | null;
  sortOrder?: number | null;
  createdAt?: string | null;
};

type LocalPreview = {
  id: string;
  file: File;
  url: string; // object URL
};

function fmt(d?: string | null) {
  if (!d) return "—";
  const dt = new Date(d);
  return Number.isNaN(dt.getTime()) ? d : dt.toLocaleString();
}

export default function VaultBuildEditPage() {
  const { uuid } = useParams<{ uuid: string }>();
  const router = useRouter();
  const api = useApi();
  const { token, loading: authLoading } = useAuth();

  const [build, setBuild] = useState<BuildDto | null>(null);
  const [form, setForm] = useState({
    title: "",
    description: "",
    isPublic: false,
  });

  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [savedMsg, setSavedMsg] = useState<string | null>(null);

  //  photo upload UI state
  const [previews, setPreviews] = useState<LocalPreview[]>([]);
  const [uploading, setUploading] = useState(false);

  // avoid object URL leaks
  useEffect(() => {
    return () => {
      previews.forEach((p) => URL.revokeObjectURL(p.url));
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const authed = !!token;

  // Load build once auth is ready + token exists
  useEffect(() => {
    if (!uuid) return;
    if (authLoading) return;

    if (!authed) {
      setError("Please log in to edit builds.");
      return;
    }

    let cancelled = false;

    (async () => {
      try {
        setError(null);
        const res = await api.get(
          `/api/v1/builds/me/${encodeURIComponent(uuid)}`
        );

        if (!res.ok) {
          const txt = await res.text().catch(() => "");
          throw new Error(txt || `Failed to load build (${res.status})`);
        }

        const data = (await res.json()) as BuildDto;

        if (cancelled) return;
        setBuild(data);
        setForm({
          title: data.title ?? "",
          description: data.description ?? "",
          isPublic: Boolean(data.isPublic),
        });
      } catch (e: any) {
        if (!cancelled) setError(e?.message ?? "Failed to load build");
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [uuid, authLoading, authed, api]);

  const dirty = useMemo(() => {
    if (!build) return false;
    return (
      form.title !== (build.title ?? "") ||
      form.description !== (build.description ?? "") ||
      form.isPublic !== Boolean(build.isPublic)
    );
  }, [build, form]);

  async function onSave() {
    if (!uuid) return;
    setBusy(true);
    setSavedMsg(null);
    setError(null);

    try {
      const payload = {
        title: form.title.trim() || "Untitled Build",
        description: form.description.trim() || null,
        isPublic: form.isPublic,
      };

      const res = await api.put(
        `/api/v1/builds/me/${encodeURIComponent(uuid)}`,
        payload
      );

      if (!res.ok) {
        const txt = await res.text().catch(() => "");
        throw new Error(txt || `Save failed (${res.status})`);
      }

      const updated = (await res.json()) as BuildDto;
      setBuild(updated);
      setForm({
        title: updated.title ?? "",
        description: updated.description ?? "",
        isPublic: Boolean(updated.isPublic),
      });
      setSavedMsg("Saved.");
      setTimeout(() => setSavedMsg(null), 2000);
    } catch (e: any) {
      setError(e?.message ?? "Save failed");
    } finally {
      setBusy(false);
    }
  }

  function isImage(file: File) {
    return file.type.startsWith("image/");
  }

  async function fileToUpload(file: File, buildUuid: string) {
    // 1) ask backend for presigned upload URL
    const res = await api.post(
      `/api/v1/builds/me/${encodeURIComponent(buildUuid)}/photos/upload-url`,
      {
        fileName: file.name,
        contentType: file.type,
      }
    );

    if (!res.ok) {
      throw new Error(await res.text().catch(() => "Failed to get upload URL"));
    }

    const { uploadUrl, publicUrl } = await res.json();

    // 2) upload directly to storage
    const put = await fetch(uploadUrl, {
      method: "PUT",
      headers: { "Content-Type": file.type },
      body: file,
    });

    if (!put.ok) throw new Error("Upload failed");

    // 3) confirm + create photo record
    const create = await api.post(
      `/api/v1/builds/me/${encodeURIComponent(buildUuid)}/photos`,
      {
        url: publicUrl,
        caption: null,
        sortOrder: 0,
      }
    );

    if (!create.ok) {
      throw new Error(await create.text().catch(() => "Failed to save photo"));
    }

    return (await create.json()) as BuildPhotoDto;
  }

  async function onDelete() {
    if (!uuid) return;

    const ok = window.confirm("Delete this build?\n\nThis cannot be undone.");
    if (!ok) return;

    setBusy(true);
    setError(null);

    try {
      const res = await api.del(
        `/api/v1/builds/me/${encodeURIComponent(uuid)}`
      );

      if (!res.ok) {
        const txt = await res.text().catch(() => "");
        throw new Error(txt || `Delete failed (${res.status})`);
      }

      router.replace("/vault");
      router.refresh();
    } catch (e: any) {
      setError(e?.message ?? "Delete failed");
    } finally {
      setBusy(false);
    }
  }

  return (
    <main className="mx-auto max-w-3xl p-6">
      <div className="mb-4 flex items-center justify-between gap-3">
        <div>
          <h1 className="text-lg font-semibold">Edit Build</h1>
          <div className="mt-1 text-xs text-zinc-500">
            UUID: <span className="font-mono">{uuid}</span>
          </div>
        </div>

        <div className="flex items-center gap-2">
          <Link
            href="/vault"
            className="rounded-md border border-white/10 bg-white/5 px-3 py-1.5 text-xs hover:bg-white/10"
          >
            ← Vault
          </Link>

          <button
            className="rounded-md bg-amber-400 px-3 py-1.5 text-xs font-semibold text-black hover:bg-amber-300 disabled:opacity-50"
            disabled={!uuid}
            onClick={() =>
              router.push(`/builder?load=${encodeURIComponent(uuid)}`)
            }
            title="Open this build in the builder to swap parts"
          >
            Open in Builder
          </button>
        </div>
      </div>

      {authLoading && <div className="text-sm text-zinc-400">Loading…</div>}

      {!authLoading && error && (
        <pre className="mb-4 whitespace-pre-wrap rounded-md border border-red-500/30 bg-red-500/10 p-3 text-xs text-red-200">
          {error}
        </pre>
      )}

      {!authLoading && build && (
        <div className="space-y-4">
          {/* meta */}
          <div className="rounded-xl border border-white/10 bg-white/5 p-4">
            <div className="flex flex-wrap items-center justify-between gap-2">
              <div className="text-xs text-zinc-400">
                Created: {fmt(build.createdAt)} • Updated:{" "}
                {fmt(build.updatedAt)}
              </div>

              <span
                className={`rounded-full border px-2 py-0.5 text-[11px] ${
                  form.isPublic
                    ? "border-emerald-500/30 bg-emerald-500/10 text-emerald-200"
                    : "border-white/10 bg-white/5 text-white/70"
                }`}
              >
                {form.isPublic ? "Published" : "Draft"}
              </span>
            </div>
          </div>

          {/* parts */}
          <div className="rounded-xl border border-white/10 bg-white/5 p-4">
            <div className="mb-3 flex items-center justify-between">
              <div className="text-sm font-semibold">Parts in this build</div>
              <div className="text-xs text-zinc-400">
                {build.items?.length ? `${build.items.length} items` : "—"}
              </div>
            </div>

            {!build.items?.length ? (
              <div className="text-sm opacity-70">No parts saved yet.</div>
            ) : (
              <div className="overflow-hidden rounded-lg border border-white/10 bg-black/20">
                {/* header */}
                <div className="grid grid-cols-12 gap-3 border-b border-white/10 px-3 py-2 text-[11px] font-semibold uppercase tracking-wider text-zinc-400">
                  <div className="col-span-5">Product</div>
                  <div className="col-span-4">Component (Role)</div>
                  <div className="col-span-2">Brand</div>
                  <div className="col-span-1 text-right">Price</div>
                </div>

                {/* rows */}
                {build.items
                  .slice()
                  .sort((a, b) => a.slot.localeCompare(b.slot))
                  .map((it, idx) => {
                    const price =
                      typeof it.bestPrice === "number"
                        ? it.bestPrice
                        : it.bestPrice
                        ? Number(it.bestPrice)
                        : null;

                    return (
                      <div
                        key={`${it.slot}-${it.productId}-${idx}`}
                        className="grid grid-cols-12 gap-2 border-b border-white/5 px-3 py-2 text-sm last:border-b-0"
                      >
                        {/* Product */}
                        <div className="col-span-5 min-w-0">
                          <div className="truncate text-zinc-100">
                            {it.productName ?? `Product #${it.productId}`}
                          </div>
                          <div className="text-xs text-zinc-500">
                            ID:{" "}
                            <span className="font-mono">{it.productId}</span>
                          </div>
                        </div>

                        {/* Component (Role) */}
                        <div className="col-span-4 truncate text-zinc-200">
                          {it.slot}
                        </div>

                        {/* Brand */}
                        <div className="col-span-2 truncate text-zinc-300">
                          {it.productBrand ?? "—"}
                        </div>

                        {/* Price */}
                        <div className="col-span-1 text-right font-semibold text-zinc-100">
                          {price != null && !Number.isNaN(price)
                            ? `$${price.toFixed(2)}`
                            : "—"}
                        </div>
                      </div>
                    );
                  })}
              </div>
            )}
          </div>

          {/* form */}
          <div className="rounded-xl border border-white/10 bg-white/5 p-4">
            <label className="block text-xs font-medium text-zinc-300">
              Title
            </label>
            <input
              value={form.title}
              onChange={(e) =>
                setForm((f) => ({ ...f, title: e.target.value }))
              }
              className="mt-2 w-full rounded-md border border-white/10 bg-black/30 px-3 py-2 text-sm outline-none focus:border-amber-400/50"
              placeholder="e.g. Suppressed MK2"
              maxLength={120}
            />

            <label className="mt-4 block text-xs font-medium text-zinc-300">
              Notes / Description
            </label>
            <textarea
              value={form.description}
              onChange={(e) =>
                setForm((f) => ({ ...f, description: e.target.value }))
              }
              className="mt-2 min-h-[120px] w-full rounded-md border border-white/10 bg-black/30 px-3 py-2 text-sm outline-none focus:border-amber-400/50"
              placeholder="Why this build? Goals, suppressor setup, ammo, intended use, etc."
              maxLength={2000}
            />

            <div className="mt-4 flex items-center justify-between gap-3">
              <label className="flex items-center gap-2 text-sm">
                <input
                  type="checkbox"
                  checked={form.isPublic}
                  onChange={(e) =>
                    setForm((f) => ({ ...f, isPublic: e.target.checked }))
                  }
                />
                <span className="text-zinc-200">Publish to community</span>
              </label>

              <div className="flex items-center gap-2">
                {savedMsg && (
                  <span className="text-xs text-emerald-300">{savedMsg}</span>
                )}

                <button
                  onClick={onSave}
                  disabled={busy || !dirty}
                  className="rounded-md bg-white px-3 py-1.5 text-xs font-semibold text-black hover:bg-zinc-200 disabled:opacity-50"
                >
                  {busy ? "Working…" : dirty ? "Save" : "Saved"}
                </button>
              </div>
            </div>
          </div>

          {/* Build Photos */}
          <div className="mt-8 rounded-xl border border-white/10 bg-white/5 p-4">
            <div className="flex items-center justify-between gap-3">
              <div>
                <div className="text-sm font-semibold">Build Photos</div>
                <div className="text-xs opacity-70">
                  Select photos, remove any you don’t want, then upload.
                </div>
              </div>

              <div className="flex items-center gap-2">
                {/* Select (no upload) */}
                <label
                  className={`cursor-pointer rounded-md border border-white/10 bg-white/5 px-3 py-2 text-xs hover:bg-white/10 ${
                    uploading ? "opacity-60 pointer-events-none" : ""
                  }`}
                  title={uploading ? "Uploading…" : "Select photos"}
                >
                  Select Photos
                  <input
                    type="file"
                    accept="image/*"
                    multiple
                    className="hidden"
                    onChange={(e) => {
                      const files = Array.from(e.target.files ?? []).filter(
                        isImage
                      );
                      if (!files.length) return;

                      const local: LocalPreview[] = files.map((f) => ({
                        id:
                          typeof crypto !== "undefined" &&
                          "randomUUID" in crypto
                            ? crypto.randomUUID()
                            : `${Date.now()}-${Math.random()}`,
                        file: f,
                        url: URL.createObjectURL(f),
                      }));

                      setPreviews((prev) => [...local, ...prev]);
                      e.target.value = ""; // reset input so re-selecting same file works
                    }}
                  />
                </label>

                {/* Upload (real upload) */}
                <button
                  type="button"
                  disabled={uploading || previews.length === 0 || !build?.uuid}
                  className="rounded-md bg-amber-400 px-3 py-2 text-xs font-semibold text-black hover:bg-amber-300 disabled:opacity-50"
                  onClick={async () => {
                    if (!build?.uuid || previews.length === 0) return;

                    setError(null);
                    setUploading(true);

                    // snapshot so user can keep selecting more while current batch uploads
                    const batch = [...previews];

                    try {
                      for (const p of batch) {
                        // if user removed it before we got to it, skip
                        const stillThere = previews.some((x) => x.id === p.id);
                        if (!stillThere) continue;

                        const created = await fileToUpload(p.file, build.uuid);

                        setBuild((prev) =>
                          prev
                            ? {
                                ...prev,
                                photos: [created, ...(prev.photos ?? [])],
                              }
                            : prev
                        );

                        // remove preview after success
                        setPreviews((prev) => {
                          const hit = prev.find((x) => x.id === p.id);
                          if (hit) URL.revokeObjectURL(hit.url);
                          return prev.filter((x) => x.id !== p.id);
                        });
                      }
                    } catch (err: any) {
                      setError(err?.message ?? "Photo upload failed");
                    } finally {
                      setUploading(false);
                    }
                  }}
                >
                  {uploading
                    ? "Uploading…"
                    : `Upload${previews.length ? ` (${previews.length})` : ""}`}
                </button>
              </div>
            </div>

            {/* Gallery */}
            <div className="mt-4 grid grid-cols-2 gap-3 sm:grid-cols-3">
              {/* Local previews (pending upload) */}
              {previews.map((p) => (
                <div
                  key={p.id}
                  className="relative overflow-hidden rounded-lg border border-white/10 bg-black/20"
                >
                  {/* remove X */}
                  <button
                    type="button"
                    aria-label="Remove"
                    className="absolute right-2 top-2 rounded-full bg-black/60 px-2 py-1 text-xs text-white hover:bg-black/80"
                    onClick={() => {
                      setPreviews((prev) => {
                        const hit = prev.find((x) => x.id === p.id);
                        if (hit) URL.revokeObjectURL(hit.url);
                        return prev.filter((x) => x.id !== p.id);
                      });
                    }}
                    disabled={uploading}
                    title={
                      uploading
                        ? "Wait for upload to finish"
                        : "Remove from upload list"
                    }
                  >
                    ✕
                  </button>

                  <Image
                    src={p.url}
                    alt="Pending upload"
                    className="h-32 w-full object-cover"
                  />
                  <div className="p-2 text-xs opacity-80">
                    {uploading ? "Uploading…" : "Pending upload"}
                  </div>
                </div>
              ))}

              {/* Uploaded photos */}
              {(build?.photos ?? []).map((p) => (
                <div
                  key={p.uuid}
                  className="overflow-hidden rounded-lg border border-white/10 bg-black/20"
                >
                  <Image
                    src={p.url}
                    alt={p.caption ?? "Build photo"}
                    className="h-32 w-full object-cover"
                  />
                  <div className="p-2 text-xs opacity-80 line-clamp-2">
                    {p.caption ?? "—"}
                  </div>
                </div>
              ))}

              {previews.length === 0 && (build?.photos?.length ?? 0) === 0 && (
                <div className="col-span-full text-xs opacity-70">
                  No photos yet. Select a few and upload when ready.
                </div>
              )}
            </div>
          </div>

          {/* danger zone */}
          <div className="rounded-xl border border-red-500/20 bg-red-500/5 p-4">
            <div className="text-sm font-semibold text-red-200">
              Danger zone
            </div>
            <div className="mt-1 text-xs text-red-200/70">
              Deleting a build is permanent.
            </div>

            <button
              onClick={onDelete}
              disabled={busy}
              className="mt-3 rounded-md border border-red-500/30 bg-red-500/10 px-3 py-1.5 text-xs font-semibold text-red-100 hover:bg-red-500/15 disabled:opacity-50"
            >
              Delete build
            </button>
          </div>
        </div>
      )}
    </main>
  );
}
