"use client";

import { useEffect, useMemo, useState } from "react";
import { Check, X, Wand2, RefreshCw } from "lucide-react";

type EnrichmentStatus = "PENDING_REVIEW" | "APPROVED" | "REJECTED" | "APPLIED";
type EnrichmentType = "CALIBER" | "CALIBER_GROUP";
type EnrichmentSource = "RULES" | "AI";

type QueueItem = {
  id: number;
  productId: number;
  productName?: string;
  productSlug?: string;
  mainImageUrl?: string;
  brandName?: string;
  enrichmentType: EnrichmentType;
  source: EnrichmentSource;
  status: EnrichmentStatus;
  attributes: Record<string, any>;
  confidence: number;
  rationale?: string;
  createdAt: string;

  // NEW: current value on products table (so we can prevent bad applies)
  productCaliber?: string | null;
  productCaliberGroup?: string | null;

};

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

function getAuthHeaders(): HeadersInit {
  if (typeof window === "undefined") return {};
  const token =
    localStorage.getItem("token") ||
    localStorage.getItem("jwt") ||
    localStorage.getItem("accessToken");

  return token ? { Authorization: `Bearer ${token}` } : {};
}

async function apiFetch(path: string, init?: RequestInit) {
  const res = await fetch(`${API_BASE}${path}`, {
    ...init,
    headers: {
      "Content-Type": "application/json",
      ...getAuthHeaders(),
      ...(init?.headers ?? {}),
    },
    // If you're using cookie auth instead of bearer, flip this on:
    // credentials: "include",
  });

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

  const ct = res.headers.get("content-type") ?? "";
  if (ct.includes("application/json")) return res.json();
  return res.text();
}

function hasProductCaliber(it: QueueItem) {
  const c = it.productCaliber;
  return typeof c === "string" && c.trim().length > 0;
}

function hasAlreadySet(it: QueueItem) {
    if (it.enrichmentType === "CALIBER") {
      return hasProductCaliber(it);
    }
    const g = it.productCaliberGroup;
    return typeof g === "string" && g.trim().length > 0;
  }
  
  // ✅ ADD THIS: text for the “Already set:” pill
  function alreadySetLabel(it: QueueItem) {
    return it.enrichmentType === "CALIBER" ? it.productCaliber : it.productCaliberGroup;
  }

export default function EnrichmentQueueClient() {
  const [type, setType] = useState<EnrichmentType>("CALIBER");
  const [status, setStatus] = useState<EnrichmentStatus>("PENDING_REVIEW");
  const [limit, setLimit] = useState<number>(50);

  const [items, setItems] = useState<QueueItem[]>([]);
  const [loading, setLoading] = useState(false);
  const [busyId, setBusyId] = useState<number | null>(null);
  const [error, setError] = useState<string | null>(null);

  // Bulk selection
  const [selected, setSelected] = useState<Record<number, boolean>>({});

  // “Fancy” per-row UI: treat an item as “locally approved/rejected” immediately
  // so the row swaps buttons without waiting for a reload.
  const [localStatus, setLocalStatus] = useState<
    Record<number, EnrichmentStatus>
  >({});

  const count = useMemo(() => items.length, [items]);

  const selectedIds = useMemo(
    () =>
      Object.entries(selected)
        .filter(([, v]) => v)
        .map(([k]) => Number(k)),
    [selected]
  );
  

  const allOnPageSelected = useMemo(() => {
    if (items.length === 0) return false;
    return items.every((it) => selected[it.id]);
  }, [items, selected]);

  function toggleAllOnPage() {
    const next = { ...selected };
    const nextValue = !allOnPageSelected;
    for (const it of items) next[it.id] = nextValue;
    setSelected(next);
  }

  function toggleOne(id: number) {
    setSelected((prev) => ({ ...prev, [id]: !prev[id] }));
  }

  function effectiveStatus(it: QueueItem): EnrichmentStatus {
    return localStatus[it.id] ?? it.status;
  }

  async function load() {
    setLoading(true);
    setError(null);
    try {
      const data = (await apiFetch(
        `/api/admin/enrichment/queue2?type=${encodeURIComponent(
          type
        )}&status=${encodeURIComponent(status)}&limit=${limit}`
      )) as QueueItem[];

      setItems(data ?? []);

      // Keep selection only for items still visible
      setSelected((prev) => {
        const keep = new Set((data ?? []).map((x) => x.id));
        const next: Record<number, boolean> = {};
        for (const [k, v] of Object.entries(prev)) {
          const id = Number(k);
          if (keep.has(id)) next[id] = v;
        }
        return next;
      });

      // Reset local status for items not in view
      setLocalStatus((prev) => {
        const keep = new Set((data ?? []).map((x) => x.id));
        const next: Record<number, EnrichmentStatus> = {};
        for (const [k, v] of Object.entries(prev)) {
          const id = Number(k);
          if (keep.has(id)) next[id] = v;
        }
        return next;
      });
    } catch (e: any) {
      setError(e?.message ?? "Failed to load queue");
    } finally {
      setLoading(false);
    }
  }

  async function runRules() {
    setLoading(true);
    setError(null);
    try {
      await apiFetch(
        `/api/admin/enrichment/run?type=${encodeURIComponent(type)}&limit=200`,
        { method: "POST" }
      );
      setStatus("PENDING_REVIEW");
      setTimeout(load, 50);
    } catch (e: any) {
      setError(e?.message ?? "Failed to run rules");
      setLoading(false);
    }
  }

  async function runAi() {
    setLoading(true);
    setError(null);
    try {
      await apiFetch(
        `/api/admin/enrichment/ai/run?type=${encodeURIComponent(type)}&limit=200`,
        { method: "POST" }
      );
      setStatus("PENDING_REVIEW");
      setTimeout(load, 50);
    } catch (e: any) {
      setError(e?.message ?? "Failed to run AI");
      setLoading(false);
    }
  }

  async function act(id: number, action: "approve" | "reject" | "apply") {
    setBusyId(id);
    setError(null);

    // Optimistic UI for approve/reject so the row instantly changes
    if (action === "approve")
      setLocalStatus((p) => ({ ...p, [id]: "APPROVED" }));
    if (action === "reject")
      setLocalStatus((p) => ({ ...p, [id]: "REJECTED" }));

    try {
      await apiFetch(`/api/admin/enrichment/${id}/${action}`, {
        method: "POST",
      });
      await load();
    } catch (e: any) {
      // rollback optimistic local status on error
      setLocalStatus((p) => {
        const next = { ...p };
        delete next[id];
        return next;
      });
      setError(e?.message ?? `Failed to ${action}`);
    } finally {
      setBusyId(null);
    }
  }

  async function bulk(action: "approve" | "reject" | "apply") {
    const ids = selectedIds;
    if (ids.length === 0) return;

    setLoading(true);
    setError(null);

    try {
      // Apply should only run for items that are APPROVED (effective status) AND product caliber is blank
      const byId = new Map(items.map((x) => [x.id, x]));
      const filtered =
        action === "apply"
          ? ids.filter((id) => {
              const it = byId.get(id);
              if (!it) return false;
              return (
                effectiveStatus(it) === "APPROVED" && !hasAlreadySet(it)
              );
            })
          : ids;

      for (const id of filtered) {
        // optimistic statuses for approve/reject in bulk
        if (action === "approve")
          setLocalStatus((p) => ({ ...p, [id]: "APPROVED" }));
        if (action === "reject")
          setLocalStatus((p) => ({ ...p, [id]: "REJECTED" }));

        await apiFetch(`/api/admin/enrichment/${id}/${action}`, {
          method: "POST",
        });
      }

      setSelected({});
      await load();
    } catch (e: any) {
      setError(e?.message ?? `Failed to bulk ${action}`);
      setLoading(false);
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    load();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [type, status, limit]);

  return (
    <div className="space-y-4">
      {/* Controls */}
      <div className="flex flex-col gap-3 rounded-md border border-zinc-800 bg-zinc-950/40 p-4">
        <div className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
          <div className="flex flex-wrap items-center gap-2">
            <div className="text-sm text-zinc-400">
              Showing <span className="text-zinc-200 font-medium">{count}</span>
            </div>

            <select
              className="h-9 rounded-md border border-zinc-800 bg-zinc-900 px-3 text-sm text-zinc-100"
              value={type}
              onChange={(e) => setType(e.target.value as EnrichmentType)}
            >
              <option value="CALIBER">CALIBER</option>
              <option value="CALIBER_GROUP">CALIBER_GROUP</option>
            </select>

            <select
              className="h-9 rounded-md border border-zinc-800 bg-zinc-900 px-3 text-sm text-zinc-100"
              value={status}
              onChange={(e) => {
                setSelected({});
                setLocalStatus({});
                setStatus(e.target.value as EnrichmentStatus);
              }}
            >
              <option value="PENDING_REVIEW">PENDING_REVIEW</option>
              <option value="APPROVED">APPROVED</option>
              <option value="REJECTED">REJECTED</option>
              <option value="APPLIED">APPLIED</option>
            </select>

            <select
              className="h-9 rounded-md border border-zinc-800 bg-zinc-900 px-3 text-sm text-zinc-100"
              value={limit}
              onChange={(e) => setLimit(parseInt(e.target.value, 10))}
            >
              <option value={25}>25</option>
              <option value={50}>50</option>
              <option value={100}>100</option>
              <option value={200}>200</option>
            </select>
          </div>

          <div className="flex items-center gap-2">
            <button
              type="button"
              onClick={load}
              className="inline-flex items-center gap-2 rounded-md border border-zinc-800 bg-zinc-900 px-3 py-2 text-sm text-zinc-100 hover:bg-zinc-800"
              disabled={loading}
            >
              <RefreshCw
                className={`h-4 w-4 ${loading ? "animate-spin" : ""}`}
              />
              Refresh
            </button>

            <button
              type="button"
              onClick={runRules}
              className="inline-flex items-center gap-2 rounded-md bg-amber-400 px-3 py-2 text-sm font-semibold text-black hover:bg-amber-300"
              disabled={loading}
              title="Run enrichment rules to create new suggestions"
            >
              <Wand2 className="h-4 w-4" />
              Run Rules
            </button>

            <button
              type="button"
              onClick={runAi}
              className="inline-flex items-center gap-2 rounded-md border border-zinc-800 bg-zinc-900 px-3 py-2 text-sm font-semibold text-zinc-100 hover:bg-zinc-800"
              disabled={loading}
              title="Run AI enrichment to create new suggestions"
            >
              <Wand2 className="h-4 w-4" />
              Run AI
            </button>
          </div>
        </div>

        {/* Bulk action bar */}
        {selectedIds.length > 0 ? (
          <div className="flex flex-wrap items-center justify-between gap-2 rounded-md border border-zinc-800 bg-zinc-950/40 p-3">
            <div className="text-sm text-zinc-300">
              Selected{" "}
              <span className="font-semibold">{selectedIds.length}</span>
              <span className="ml-2 text-xs text-zinc-500">
                (Apply only works on APPROVED + product caliber blank)
              </span>
            </div>

            <div className="flex items-center gap-2">
              <button
                type="button"
                onClick={() => bulk("approve")}
                className="rounded-md border border-zinc-800 bg-zinc-900 px-3 py-2 text-sm text-zinc-100 hover:bg-zinc-800"
                disabled={loading}
              >
                Approve Selected
              </button>

              <button
                type="button"
                onClick={() => bulk("reject")}
                className="rounded-md border border-zinc-800 bg-zinc-900 px-3 py-2 text-sm text-zinc-100 hover:bg-zinc-800"
                disabled={loading}
              >
                Reject Selected
              </button>

              <button
                type="button"
                onClick={() => bulk("apply")}
                className="rounded-md bg-amber-400 px-3 py-2 text-sm font-semibold text-black hover:bg-amber-300"
                disabled={loading}
                title="Applies only APPROVED rows where product caliber is blank"
              >
                Apply Selected
              </button>

              <button
                type="button"
                onClick={() => setSelected({})}
                className="rounded-md border border-zinc-800 bg-zinc-900 px-3 py-2 text-sm text-zinc-100 hover:bg-zinc-800"
                disabled={loading}
              >
                Clear
              </button>
            </div>
          </div>
        ) : null}
      </div>

      {error ? (
        <div className="rounded-md border border-red-900/50 bg-red-950/30 p-3 text-sm text-red-200">
          {error}
        </div>
      ) : null}

      {/* Table */}
      <div className="overflow-hidden rounded-md border border-zinc-800">
        <div className="grid grid-cols-[40px_minmax(0,1fr)_120px_140px_160px] gap-3 border-b border-zinc-800 bg-zinc-950 px-4 py-3 text-[0.7rem] uppercase tracking-[0.16em] text-zinc-500">
          <div className="flex items-center justify-center">
            <input
              type="checkbox"
              checked={allOnPageSelected}
              onChange={toggleAllOnPage}
              className="h-4 w-4 accent-amber-400"
              aria-label="Select all"
            />
          </div>
          <div>Product</div>
          <div className="text-right">Confidence</div>
          <div className="text-right">Suggested</div>
          <div className="text-right">Actions</div>
        </div>

        <div className="divide-y divide-zinc-800 bg-zinc-950/40">
          {items.length === 0 ? (
            <div className="p-6 text-sm text-zinc-400">No items found.</div>
          ) : (
            items.map((it) => {
              const suggested =
              it.enrichmentType === "CALIBER"
              ? it.attributes?.caliber
              : it.attributes?.caliberGroup;              const isBusy = busyId === it.id;
              const st = effectiveStatus(it);
              const alreadySet = hasAlreadySet(it);
              const alreadySetValue = alreadySetLabel(it);

              return (
                <div
                  key={it.id}
                  className="grid grid-cols-[40px_minmax(0,1fr)_120px_140px_160px] gap-3 px-4 py-3"
                >
                  <div className="flex items-center justify-center">
                    <input
                      type="checkbox"
                      checked={!!selected[it.id]}
                      onChange={() => toggleOne(it.id)}
                      className="h-4 w-4 accent-amber-400"
                      aria-label={`Select enrichment ${it.id}`}
                    />
                  </div>

                  <div className="min-w-0">
                    <div className="flex items-start gap-3">
                      {it.mainImageUrl ? (
                        // eslint-disable-next-line @next/next/no-img-element
                        <img
                          src={it.mainImageUrl}
                          alt=""
                          className="h-10 w-10 rounded border border-zinc-800 object-cover"
                        />
                      ) : (
                        <div className="h-10 w-10 rounded border border-zinc-800 bg-zinc-900" />
                      )}

                      <div className="min-w-0">
                        <a
                          href={`/admin/products/${it.productId}`}
                          className="text-sm font-semibold text-zinc-100 hover:underline line-clamp-2"
                        >
                          {it.productName ?? `Product #${it.productId}`}
                        </a>

                        <div className="mt-0.5 text-xs text-zinc-500">
                          {it.brandName ? `${it.brandName} • ` : ""}
                          {it.source} • {st}
                          {alreadySet ? (
                            <span className="ml-2 inline-flex items-center rounded-md border border-zinc-700 bg-zinc-900 px-2 py-0.5 text-[10px] font-semibold text-zinc-300">
                              Already set: {alreadySetValue}
                            </span>
                          ) : null}
                        </div>

                        {it.rationale ? (
                          <div className="mt-1 text-xs text-zinc-400 line-clamp-2">
                            {it.rationale}
                          </div>
                        ) : null}
                      </div>
                    </div>
                  </div>

                  <div className="text-right text-sm font-semibold text-zinc-200">
                    {(it.confidence ?? 0).toFixed(2)}
                  </div>

                  <div className="text-right text-sm text-amber-300">
                    {suggested ?? "—"}
                  </div>

                  <div className="flex justify-end gap-2">
                    {st === "PENDING_REVIEW" && (
                      <>
                        <button
                          type="button"
                          onClick={() => act(it.id, "approve")}
                          disabled={isBusy || alreadySet}
                          className="inline-flex h-8 w-8 items-center justify-center rounded-md border border-zinc-800 bg-zinc-900 text-zinc-100 hover:bg-zinc-800 disabled:opacity-50"
                          title={
                            alreadySet
                              ? "Product caliber already set"
                              : "Approve"
                          }
                          aria-label="Approve"
                        >
                          <Check className="h-4 w-4" />
                        </button>

                        <button
                          type="button"
                          onClick={() => act(it.id, "reject")}
                          disabled={isBusy}
                          className="inline-flex h-8 w-8 items-center justify-center rounded-md border border-zinc-800 bg-zinc-900 text-zinc-100 hover:bg-zinc-800 disabled:opacity-50"
                          title="Reject"
                          aria-label="Reject"
                        >
                          <X className="h-4 w-4" />
                        </button>
                      </>
                    )}

                    {st === "APPROVED" && (
                      <button
                        type="button"
                        onClick={() => act(it.id, "apply")}
                        disabled={isBusy || alreadySet}
                        className="inline-flex h-8 items-center justify-center rounded-md bg-amber-400 px-3 text-xs font-semibold text-black hover:bg-amber-300 disabled:opacity-50"
                        title={
                            alreadySet
                            ? `Already set on product: ${alreadySetValue}`
                            : "Apply (writes to product if blank)"
                        }
                      >
                        Apply
                      </button>
                    )}

                    {st === "APPLIED" && (
                      <span className="inline-flex h-8 items-center rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 text-xs font-semibold text-emerald-200">
                        Applied
                      </span>
                    )}

                    {st === "REJECTED" && (
                      <span className="inline-flex h-8 items-center rounded-md border border-red-500/30 bg-red-500/10 px-3 text-xs font-semibold text-red-200">
                        Rejected
                      </span>
                    )}
                  </div>
                </div>
              );
            })
          )}
        </div>
      </div>
    </div>
  );
}