"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";

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;

  // 1) Prefer localStorage (your canonical token store)
  const ls = localStorage.getItem("ballistic_auth_token");
  if (ls && ls.trim().length > 0) return ls;

  // 2) Fallback to cookie (only works if NOT HttpOnly)
  const ck = getCookie("bb_access_token");
  if (ck && ck.trim().length > 0) return ck;

  return null;
}

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

  const lsUser = localStorage.getItem("ballistic_auth_user");
  if (lsUser) {
    try {
      const parsed = JSON.parse(lsUser);
      // adjust if your user object uses a different key
      return parsed?.role ?? parsed?.roles?.[0] ?? null;
    } catch {
      // ignore
    }
  }

  const ckRole = getCookie("bb_role");
  return ckRole ?? 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;
  }>
) {
  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 };
}

export default function AdminProductsPage() {
  // filters
  const [q, setQ] = useState("");
  const [platform, setPlatform] = useState("");
  const [partRole, setPartRole] = useState("");
  const [visibility, setVisibility] = useState<ProductVisibility | "">("");
  const [status, setStatus] = useState<ProductStatus | "">("");
  const [builderEligible, setBuilderEligible] = useState<"" | "true" | "false">(
    ""
  );
  const [adminLocked, setAdminLocked] = useState<"" | "true" | "false">("");

  // paging
  const [page, setPage] = useState(0);
  const [size, setSize] = useState(50);

  // 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());

  const queryParams = useMemo(() => {
    return {
      q,
      platform,
      partRole,
      visibility,
      status,
      builderEligible: builderEligible === "" ? null : builderEligible,
      adminLocked: adminLocked === "" ? null : adminLocked,
      page,
      size,
      sort: "updatedAt,desc",
    };
  }, [
    q,
    platform,
    partRole,
    visibility,
    status,
    builderEligible,
    adminLocked,
    page,
    size,
  ]);

  const refresh = async () => {
    setLoading(true);
    setErr(null);
    try {
      const res = await fetchAdminProducts(queryParams);
      setData(res);
      // clear selection on refresh so you don’t accidentally nuke new stuff
      setSelected(new Set());
    } catch (e: any) {
      setErr(e?.message ?? "Failed to load.");
    } finally {
      setLoading(false);
    }
  };

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

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

  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 selectedIds = Array.from(selected);

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

    // no confirmations per your “keep moving” vibe, but you can add one later
    setLoading(true);
    setErr(null);

    try {
      const res = await bulkUpdate(selectedIds, set);
      // eslint-disable-next-line no-console
      console.log("Bulk updated:", res.updatedCount);
      await refresh();
    } catch (e: any) {
      setErr(e?.message ?? "Bulk update failed.");
      setLoading(false);
    }
  };

  return (
    <div className="mx-auto max-w-7xl px-4 py-10">
      <div className="mb-6 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>

      {/* Filters */}
      <div className="mb-4 grid grid-cols-1 gap-3 md:grid-cols-6">
        <input
          value={q}
          onChange={(e) => setQ(e.target.value)}
          placeholder="Search (name, slug, mpn, upc)…"
          className="md:col-span-2 rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
        />

        <input
          value={platform}
          onChange={(e) => setPlatform(e.target.value)}
          placeholder="Platform (AR-15)…"
          className="rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
        />

        <input
          value={partRole}
          onChange={(e) => setPartRole(e.target.value)}
          placeholder="Part role (barrel)…"
          className="rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
        />

        <select
          value={visibility}
          onChange={(e) => setVisibility(e.target.value as any)}
          className="rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
        >
          <option value="">Visibility (any)</option>
          <option value="PUBLIC">PUBLIC</option>
          <option value="HIDDEN">HIDDEN</option>
        </select>

        <select
          value={status}
          onChange={(e) => setStatus(e.target.value as any)}
          className="rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
        >
          <option value="">Status (any)</option>
          <option value="ACTIVE">ACTIVE</option>
          <option value="DISABLED">DISABLED</option>
          <option value="ARCHIVED">ARCHIVED</option>
        </select>

        <div className="md:col-span-6 flex flex-wrap items-center gap-3">
          <select
            value={builderEligible}
            onChange={(e) => setBuilderEligible(e.target.value as any)}
            className="rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
          >
            <option value="">Builder eligible (any)</option>
            <option value="true">true</option>
            <option value="false">false</option>
          </select>

          <select
            value={adminLocked}
            onChange={(e) => setAdminLocked(e.target.value as any)}
            className="rounded-md border border-zinc-700 bg-black px-3 py-2 text-sm"
          >
            <option value="">Admin locked (any)</option>
            <option value="true">true</option>
            <option value="false">false</option>
          </select>

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

          <button
            className="rounded-md border border-zinc-700 px-3 py-2 text-sm hover:bg-zinc-900"
            onClick={() => {
              setQ("");
              setPlatform("");
              setPartRole("");
              setVisibility("");
              setStatus("");
              setBuilderEligible("");
              setAdminLocked("");
              setPage(0);
              refresh();
            }}
          >
            Clear
          </button>
        </div>
      </div>

      {/* Bulk actions */}
      <div className="mb-3 flex flex-wrap items-center justify-between gap-3">
        <div className="text-sm opacity-70">
          Selected:{" "}
          <span className="font-semibold opacity-100">
            {selectedIds.length}
          </span>
        </div>

        <div className="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 || selectedIds.length === 0}
            onClick={() =>
              runBulk({
                visibility: "HIDDEN",
                builderEligible: false,
                adminLocked: true,
                adminNote: "Hidden + removed from builder (bulk)",
              })
            }
          >
            Hide + Remove from Builder + 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 || selectedIds.length === 0}
            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 || selectedIds.length === 0}
            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 || selectedIds.length === 0}
            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 || selectedIds.length === 0}
            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 || selectedIds.length === 0}
            onClick={() => runBulk({ adminLocked: false })}
          >
            Unlock
          </button>
        </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>
  );
}
