"use client";

import { useEffect, useMemo, useState } from "react";

type ProductVisibility = "PUBLIC" | "HIDDEN";
type ProductStatus = "ACTIVE" | "DISABLED" | "ARCHIVED";

type AdminProductRow = {
  id: number;
  uuid: string;
  name: string;
  slug: string;
  platform: string | null;
  partRole: string | null;
  brandName: string | null;
  importStatus: string | null;

  visibility: ProductVisibility;
  status: ProductStatus;
  builderEligible: boolean;
  adminLocked: boolean;

  adminNote: string | null;
  mainImageUrl: string | null;

  createdAt: string | null;
  updatedAt: string | null;
};

type PageResponse<T> = {
  content: T[];
  totalElements: number;
  totalPages: number;
  number: number;
  size: number;
};

const API_BASE =
  process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";

// -----------------------------
// Auth helpers (kept as-is)
// -----------------------------
function getCookie(name: string): string | null {
  if (typeof document === "undefined") return null;
  const match = document.cookie.match(
    new RegExp(
      "(^| )" + name.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") + "=([^;]+)"
    )
  );
  return match ? decodeURIComponent(match[2]) : null;
}

function getToken(): string | null {
  if (typeof window === "undefined") return null;

  const ls = localStorage.getItem("ballistic_auth_token");
  if (ls && ls.trim().length > 0) return ls;

  const ck = getCookie("bb_access_token");
  if (ck && ck.trim().length > 0) return ck;

  return null;
}

function qs(params: Record<string, any>) {
  const sp = new URLSearchParams();
  Object.entries(params).forEach(([k, v]) => {
    if (v === undefined || v === null || v === "") return;
    sp.set(k, String(v));
  });
  return sp.toString();
}

async function fetchAdminProducts(params: Record<string, any>) {
  const token = getToken();

  const res = await fetch(`${API_BASE}/api/v1/admin/products?${qs(params)}`, {
    method: "GET",
    credentials: "include",
    headers: {
      Accept: "application/json",
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
    },
    cache: "no-store",
  });

  if (!res.ok) {
    const txt = await res.text();
    throw new Error(`Failed to load admin products (${res.status}): ${txt}`);
  }

  return (await res.json()) as PageResponse<AdminProductRow>;
}

async function bulkUpdate(
  productIds: number[],
  set: Partial<{
    visibility: ProductVisibility;
    status: ProductStatus;
    builderEligible: boolean;
    adminLocked: boolean;
    adminNote: string;
    platform: string;
    platformLocked: boolean;
  }>
) {
  const token = getToken();

  const res = await fetch(`${API_BASE}/api/v1/admin/products/bulk`, {
    method: "PATCH",
    credentials: "include",
    headers: {
      "Content-Type": "application/json",
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
    },
    body: JSON.stringify({ productIds, ...set }),
  });

  if (!res.ok) {
    const txt = await res.text();
    throw new Error(`Bulk update failed (${res.status}): ${txt}`);
  }

  return (await res.json()) as {
    updatedCount: number;
    skippedLockedCount: number;
  };
}

// -----------------------------
// UI types
// -----------------------------
type AdminFilters = {
  q: string;
  platform: string; // platform KEY
  partRole: string;
  visibility: ProductVisibility | "";
  status: ProductStatus | "";
  builderEligible: "" | "true" | "false";
  adminLocked: "" | "true" | "false";
};

type PlatformDto = {
  id: number;
  key: string;
  label: string;
  is_active: boolean;
};

async function fetchPlatforms() {
  const res = await fetch(`${API_BASE}/api/platforms`, {
    method: "GET",
    headers: { Accept: "application/json" },
    cache: "no-store",
  });

  if (!res.ok) {
    const txt = await res.text();
    throw new Error(`Failed to load platforms (${res.status}): ${txt}`);
  }

  const all = (await res.json()) as PlatformDto[];
  return all.filter((p) => p.is_active);
}

// Replace with an API later if you want.
// For now: derive from the current page results + known “common” roles.
function buildRoleOptions(rows: AdminProductRow[]) {
  const set = new Set<string>();
  rows.forEach((r) => {
    if (r.partRole) set.add(r.partRole);
  });
  return ["", ...Array.from(set).sort((a, b) => a.localeCompare(b))];
}

// -----------------------------
// Small UI helpers
// -----------------------------
function Field({
  label,
  children,
  widthClass,
}: {
  label: string;
  children: React.ReactNode;
  widthClass?: string;
}) {
  return (
    <div className={widthClass ?? "w-[180px]"}>
      <div className="mb-1 text-[11px] uppercase tracking-[0.16em] text-zinc-500">
        {label}
      </div>
      {children}
    </div>
  );
}

function Chip({ text, onClear }: { text: string; onClear: () => void }) {
  return (
    <button
      type="button"
      onClick={onClear}
      className="rounded-full border border-zinc-800 bg-zinc-950 px-2 py-1 text-[11px] text-zinc-200 hover:bg-zinc-900"
      title="Clear filter"
    >
      {text} <span className="ml-1 text-zinc-500">×</span>
    </button>
  );
}

export default function AdminProductsPage() {
  // paging
  const [page, setPage] = useState(0);
  const [size, setSize] = useState(50);

  // dropdown data
  const [platformOptions, setPlatformOptions] = useState<PlatformDto[]>([]);

  // data
  const [data, setData] = useState<PageResponse<AdminProductRow> | null>(null);
  const [loading, setLoading] = useState(false);
  const [err, setErr] = useState<string | null>(null);

  // selection
  const [selected, setSelected] = useState<Set<number>>(new Set());

  // filters: draft vs applied (THIS is the big clarity win)
  const initialFilters: AdminFilters = {
    q: "",
    platform: "",
    partRole: "",
    visibility: "",
    status: "",
    builderEligible: "",
    adminLocked: "",
  };

  const [draft, setDraft] = useState<AdminFilters>(initialFilters);
  const [applied, setApplied] = useState<AdminFilters>(initialFilters);

  // bulk action UI state
  const [bulkPlatformKey, setBulkPlatformKey] = useState<string>("");
  const [bulkPlatformLock, setBulkPlatformLock] = useState(false);

  const queryParams = useMemo(() => {
    return {
      ...applied,
      builderEligible:
        applied.builderEligible === "" ? null : applied.builderEligible,
      adminLocked: applied.adminLocked === "" ? null : applied.adminLocked,
      page,
      size,
      sort: "updatedAt,desc",
    };
  }, [applied, page, size]);

  const refresh = async () => {
    setLoading(true);
    setErr(null);
    try {
      const res = await fetchAdminProducts(queryParams);
      setData(res);
      setSelected(new Set()); // prevent accidental “bulk” on new results
    } catch (e: any) {
      setErr(e?.message ?? "Failed to load.");
    } finally {
      setLoading(false);
    }
  };

  // auto-refresh only on paging (kept behavior)
  useEffect(() => {
    refresh();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [page, size]);

  // load platforms
  useEffect(() => {
    (async () => {
      try {
        const plats = await fetchPlatforms();
        plats.sort((a, b) => a.label.localeCompare(b.label));
        setPlatformOptions(plats);
      } catch (e: any) {
        console.warn(e?.message ?? "Failed to load platforms");
      }
    })();
  }, []);

  const content = data?.content ?? [];

  // derive role options from current page (good enough v1)
  const roleOptions = useMemo(() => buildRoleOptions(content), [content]);

  const selectedIds = Array.from(selected);

  const allOnPageSelected =
    content.length > 0 && content.every((r) => selected.has(r.id));

  const toggleAllOnPage = () => {
    const next = new Set(selected);
    if (allOnPageSelected) content.forEach((r) => next.delete(r.id));
    else content.forEach((r) => next.add(r.id));
    setSelected(next);
  };

  const toggleOne = (id: number) => {
    const next = new Set(selected);
    if (next.has(id)) next.delete(id);
    else next.add(id);
    setSelected(next);
  };

  const applyFilters = async () => {
    setPage(0);
    setApplied({ ...draft });
    // keep your “manual” refresh model:
    await refresh();
  };

  const clearFilters = async () => {
    setDraft(initialFilters);
    setApplied(initialFilters);
    setPage(0);
    await refresh();
  };

  const runBulk = async (set: Parameters<typeof bulkUpdate>[1]) => {
    if (selectedIds.length === 0) return;

    setLoading(true);
    setErr(null);

    try {
      const res = await bulkUpdate(selectedIds, set);
      console.log(
        `Updated ${res.updatedCount}` +
          (res.skippedLockedCount > 0
            ? ` • Skipped ${res.skippedLockedCount} (platform locked)`
            : "")
      );
      await refresh();

      if ("platform" in set) {
        setBulkPlatformKey("");
        setBulkPlatformLock(false);
      }
    } catch (e: any) {
      setErr(e?.message ?? "Bulk update failed.");
      setLoading(false);
    }
  };

  // active filter chips (optional but huge clarity)
  const chips = useMemo(() => {
    const out: { key: keyof AdminFilters; label: string }[] = [];
    if (applied.q) out.push({ key: "q", label: `Search: ${applied.q}` });
    if (applied.platform)
      out.push({ key: "platform", label: `Platform: ${applied.platform}` });
    if (applied.partRole)
      out.push({ key: "partRole", label: `Role: ${applied.partRole}` });
    if (applied.visibility)
      out.push({
        key: "visibility",
        label: `Visibility: ${applied.visibility}`,
      });
    if (applied.status)
      out.push({ key: "status", label: `Status: ${applied.status}` });
    if (applied.builderEligible)
      out.push({
        key: "builderEligible",
        label: `Builder: ${applied.builderEligible}`,
      });
    if (applied.adminLocked)
      out.push({ key: "adminLocked", label: `Locked: ${applied.adminLocked}` });
    return out;
  }, [applied]);

  const clearOne = async (key: keyof AdminFilters) => {
    const nextDraft = { ...draft, [key]: "" } as AdminFilters;
    const nextApplied = { ...applied, [key]: "" } as AdminFilters;
    setDraft(nextDraft);
    setApplied(nextApplied);
    setPage(0);
    await refresh();
  };

  return (
    <div className="mx-auto max-w-screen-2xl px-2 py-6">
      <div className="mb-4 flex items-start justify-between gap-4">
        <div>
          <h1 className="text-2xl font-semibold">Admin · Products</h1>
          <p className="text-sm opacity-70">
            Filter, select, and apply bulk actions. This is where bad imports
            come to die.
          </p>
        </div>

        <button
          className="rounded-md border border-zinc-700 px-3 py-2 text-sm hover:bg-zinc-900 disabled:opacity-50"
          onClick={() => refresh()}
          disabled={loading}
        >
          Refresh
        </button>
      </div>

      {/* ROW 1: FILTER BAR */}
      <div className="mb-3 rounded-md border border-zinc-800 bg-zinc-950/40 p-3">
        <div className="flex flex-wrap items-end gap-2">
          <Field label="Search" widthClass="min-w-[260px] flex-1">
            <input
              value={draft.q}
              onChange={(e) => setDraft((s) => ({ ...s, q: e.target.value }))}
              placeholder="name, slug, mpn, upc…"
              className="w-full rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
            />
          </Field>

          <Field label="Platform">
            <select
              value={draft.platform}
              onChange={(e) =>
                setDraft((s) => ({ ...s, platform: e.target.value }))
              }
              className="w-full rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
            >
              <option value="">Any</option>
              {platformOptions.map((p) => (
                <option key={p.key} value={p.key}>
                  {p.key}
                </option>
              ))}
            </select>
          </Field>

          <Field label="Role">
            <select
              value={draft.partRole}
              onChange={(e) =>
                setDraft((s) => ({ ...s, partRole: e.target.value }))
              }
              className="w-full rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
            >
              <option value="">Any</option>
              {roleOptions.map((r) => (
                <option key={r || "any"} value={r}>
                  {r || "Any"}
                </option>
              ))}
            </select>
          </Field>

          <Field label="Visibility">
            <select
              value={draft.visibility}
              onChange={(e) =>
                setDraft((s) => ({ ...s, visibility: e.target.value as any }))
              }
              className="w-full rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
            >
              <option value="">Any</option>
              <option value="PUBLIC">PUBLIC</option>
              <option value="HIDDEN">HIDDEN</option>
            </select>
          </Field>

          <Field label="Status">
            <select
              value={draft.status}
              onChange={(e) =>
                setDraft((s) => ({ ...s, status: e.target.value as any }))
              }
              className="w-full rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
            >
              <option value="">Any</option>
              <option value="ACTIVE">ACTIVE</option>
              <option value="DISABLED">DISABLED</option>
              <option value="ARCHIVED">ARCHIVED</option>
            </select>
          </Field>

          <Field label="Builder">
            <select
              value={draft.builderEligible}
              onChange={(e) =>
                setDraft((s) => ({
                  ...s,
                  builderEligible: e.target.value as any,
                }))
              }
              className="w-full rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
            >
              <option value="">Any</option>
              <option value="true">Eligible</option>
              <option value="false">Not eligible</option>
            </select>
          </Field>

          <Field label="Locked">
            <select
              value={draft.adminLocked}
              onChange={(e) =>
                setDraft((s) => ({ ...s, adminLocked: e.target.value as any }))
              }
              className="w-full rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
            >
              <option value="">Any</option>
              <option value="true">Locked</option>
              <option value="false">Unlocked</option>
            </select>
          </Field>

          <div className="ml-auto flex items-center gap-2">
            <button
              className="rounded-md bg-emerald-600 px-3 py-2 text-sm hover:bg-emerald-500 disabled:opacity-50"
              onClick={applyFilters}
              disabled={loading}
            >
              Apply
            </button>

            <button
              className="rounded-md border border-zinc-700 px-3 py-2 text-sm hover:bg-zinc-900"
              onClick={clearFilters}
              disabled={loading}
            >
              Clear
            </button>
          </div>
        </div>

        {chips.length > 0 && (
          <div className="mt-3 flex flex-wrap gap-2">
            {chips.map((c) => (
              <Chip
                key={c.key}
                text={c.label}
                onClear={() => void clearOne(c.key)}
              />
            ))}
          </div>
        )}
      </div>

      {/* ROW 2: BULK BAR (only when selection > 0) */}
      {selectedIds.length > 0 && (
        <div className="mb-3 rounded-md border border-zinc-800 bg-zinc-950/40 p-3">
          <div className="flex flex-wrap items-center gap-3">
            <div className="text-sm opacity-80">
              Selected:{" "}
              <span className="font-semibold">{selectedIds.length}</span>
            </div>

            <div className="h-4 w-px bg-zinc-800" />

            <div className="flex flex-wrap items-center gap-2">
              <select
                value={bulkPlatformKey}
                onChange={(e) => setBulkPlatformKey(e.target.value)}
                className="rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
              >
                <option value="">Set platform…</option>
                {platformOptions.map((p) => (
                  <option key={p.key} value={p.key}>
                    {p.label}
                  </option>
                ))}
              </select>

              <label className="flex items-center gap-2 text-xs opacity-80">
                <input
                  type="checkbox"
                  checked={bulkPlatformLock}
                  onChange={(e) => setBulkPlatformLock(e.target.checked)}
                />
                Lock platform
              </label>

              <button
                className="rounded-md border border-zinc-700 px-3 py-2 text-sm hover:bg-zinc-900 disabled:opacity-50"
                disabled={loading || bulkPlatformKey.length === 0}
                onClick={() =>
                  runBulk({
                    platform: bulkPlatformKey,
                    ...(bulkPlatformLock ? { platformLocked: true } : {}),
                  })
                }
              >
                Apply Platform
              </button>
            </div>

            <div className="ml-auto flex flex-wrap gap-2">
              <button
                className="rounded-md border border-zinc-700 px-3 py-2 text-sm hover:bg-zinc-900 disabled:opacity-50"
                disabled={loading}
                onClick={() =>
                  runBulk({
                    visibility: "HIDDEN",
                    builderEligible: false,
                    adminLocked: true,
                    adminNote: "Hidden + removed from builder (bulk)",
                  })
                }
              >
                Hide + Remove + Lock
              </button>

              <button
                className="rounded-md border border-zinc-700 px-3 py-2 text-sm hover:bg-zinc-900 disabled:opacity-50"
                disabled={loading}
                onClick={() => runBulk({ builderEligible: false })}
              >
                Remove from Builder
              </button>

              <button
                className="rounded-md border border-zinc-700 px-3 py-2 text-sm hover:bg-zinc-900 disabled:opacity-50"
                disabled={loading}
                onClick={() => runBulk({ visibility: "HIDDEN" })}
              >
                Hide
              </button>

              <button
                className="rounded-md border border-zinc-700 px-3 py-2 text-sm hover:bg-zinc-900 disabled:opacity-50"
                disabled={loading}
                onClick={() => runBulk({ status: "DISABLED" })}
              >
                Disable
              </button>

              <button
                className="rounded-md border border-zinc-700 px-3 py-2 text-sm hover:bg-zinc-900 disabled:opacity-50"
                disabled={loading}
                onClick={() => runBulk({ adminLocked: true })}
              >
                Lock
              </button>

              <button
                className="rounded-md border border-zinc-700 px-3 py-2 text-sm hover:bg-zinc-900 disabled:opacity-50"
                disabled={loading}
                onClick={() => runBulk({ adminLocked: false })}
              >
                Unlock
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Errors */}
      {err && (
        <div className="mb-3 rounded-md border border-red-800 bg-red-950/40 px-3 py-2 text-sm">
          {err}
        </div>
      )}

      {/* Table */}
      <div className="overflow-x-auto rounded-md border border-zinc-800">
        <table className="w-full text-sm">
          <thead className="bg-zinc-950">
            <tr className="text-left">
              <th className="w-10 px-3 py-2">
                <input
                  type="checkbox"
                  checked={allOnPageSelected}
                  onChange={toggleAllOnPage}
                />
              </th>
              <th className="px-3 py-2">Product</th>
              <th className="px-3 py-2">Brand</th>
              <th className="px-3 py-2">Platform</th>
              <th className="px-3 py-2">Role</th>
              <th className="px-3 py-2">Import</th>
              <th className="px-3 py-2">Flags</th>
              <th className="px-3 py-2">Updated</th>
            </tr>
          </thead>

          <tbody>
            {loading && (
              <tr>
                <td colSpan={8} className="px-3 py-6 text-center opacity-70">
                  Loading…
                </td>
              </tr>
            )}

            {!loading && content.length === 0 && (
              <tr>
                <td colSpan={8} className="px-3 py-6 text-center opacity-70">
                  No results.
                </td>
              </tr>
            )}

            {!loading &&
              content.map((row) => (
                <tr
                  key={row.id}
                  className="border-t border-zinc-900 hover:bg-zinc-950/40"
                >
                  <td className="px-3 py-2">
                    <input
                      type="checkbox"
                      checked={selected.has(row.id)}
                      onChange={() => toggleOne(row.id)}
                    />
                  </td>

                  <td className="px-3 py-2">
                    <div className="flex items-center gap-3">
                      {row.mainImageUrl ? (
                        // eslint-disable-next-line @next/next/no-img-element
                        <img
                          src={row.mainImageUrl}
                          alt=""
                          className="h-10 w-10 rounded object-cover border border-zinc-800"
                        />
                      ) : (
                        <div className="h-10 w-10 rounded border border-zinc-800 bg-zinc-950" />
                      )}

                      <div className="min-w-0">
                        <div className="truncate font-medium">{row.name}</div>
                        <div className="truncate text-xs opacity-60">
                          {row.slug} · #{row.id}
                        </div>
                        {row.adminNote ? (
                          <div className="truncate text-xs opacity-60">
                            📝 {row.adminNote}
                          </div>
                        ) : null}
                      </div>
                    </div>
                  </td>

                  <td className="px-3 py-2">{row.brandName ?? "—"}</td>
                  <td className="px-3 py-2">{row.platform ?? "—"}</td>
                  <td className="px-3 py-2">{row.partRole ?? "—"}</td>
                  <td className="px-3 py-2">{row.importStatus ?? "—"}</td>

                  <td className="px-3 py-2">
                    <div className="flex flex-wrap gap-1 text-xs">
                      {row.visibility === "HIDDEN" ? (
                        <span className="rounded border border-zinc-700 px-2 py-0.5">
                          HIDDEN
                        </span>
                      ) : null}
                      {row.status !== "ACTIVE" ? (
                        <span className="rounded border border-zinc-700 px-2 py-0.5">
                          {row.status}
                        </span>
                      ) : null}
                      {row.builderEligible === false ? (
                        <span className="rounded border border-zinc-700 px-2 py-0.5">
                          NO_BUILDER
                        </span>
                      ) : null}
                      {row.adminLocked ? (
                        <span className="rounded border border-zinc-700 px-2 py-0.5">
                          LOCKED
                        </span>
                      ) : null}
                    </div>
                  </td>

                  <td className="px-3 py-2 text-xs opacity-70">
                    {row.updatedAt ?? "—"}
                  </td>
                </tr>
              ))}
          </tbody>
        </table>
      </div>

      {/* Pagination */}
      <div className="mt-4 flex items-center justify-between gap-3">
        <div className="text-sm opacity-70">
          Page {(data?.number ?? 0) + 1} of {data?.totalPages ?? 1} •{" "}
          {data?.totalElements ?? 0} total
        </div>

        <div className="flex items-center gap-2">
          <select
            value={size}
            onChange={(e) => {
              setSize(Number(e.target.value));
              setPage(0);
            }}
            className="rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
          >
            {[25, 50, 100, 200].map((n) => (
              <option key={n} value={n}>
                {n}/page
              </option>
            ))}
          </select>

          <button
            className="rounded-md border border-zinc-700 px-3 py-2 text-sm hover:bg-zinc-900 disabled:opacity-50"
            disabled={loading || page <= 0}
            onClick={() => setPage((p) => Math.max(0, p - 1))}
          >
            Prev
          </button>

          <button
            className="rounded-md border border-zinc-700 px-3 py-2 text-sm hover:bg-zinc-900 disabled:opacity-50"
            disabled={loading || (data ? page >= data.totalPages - 1 : true)}
            onClick={() => setPage((p) => p + 1)}
          >
            Next
          </button>
        </div>
      </div>
    </div>
  );
}
