"use client";

import { useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { useParams, useRouter, useSearchParams } from "next/navigation";

import type { BuilderSlotKey } from "@/types/builderSlots";
import { PART_ROLE_TO_CATEGORY, normalizePartRole } from "@/lib/catalogMappings";
import { trackAffiliateLinkClicked } from "@/lib/analytics";
import { ProductImage } from "@/components/parts/ProductImage";

/**
 * API Shapes
 * - OfferFromApi: what /api/v1/products/:id/offers returns
 * - GunbuilderProductFromApi: product detail contract (v1)
 */
type OfferFromApi = {
  id?: string | number;
  merchantName?: string | null;
  price?: number | null;
  originalPrice?: number | null;
  buyUrl?: string | null;
  buyShortUrl?: string | null;
  inStock?: boolean | null;
  lastUpdated?: string | null;
};

type GunbuilderProductFromApi = {
  id: number;
  name: string;
  brand: string;
  platform: string;
  partRole: string;
  price: number | null;
  caliber?: string | null;

  // Optional (legacy fallback label if product.offers is missing)
  merchantName?: string | null;

  imageUrl?: string | null;
  mainImageUrl?: string | null;

  buyUrl?: string | null;
  buyShortUrl?: string | null;
  inStock?: boolean | null;

  shortDescription?: string | null;
  description?: string | null;

  // (May be empty depending on endpoint; we now fetch offers separately)
  offers?: OfferFromApi[] | null;
};

type BuildState = Partial<Record<BuilderSlotKey, string>>;

const API_BASE_URL =
  process.env.NEXT_PUBLIC_API_BASE_URL ?? "";

const STORAGE_KEY = "gunbuilder-build-state";

const PLATFORMS = ["AR-15", "AR-10", "AR-9"] as const;

/**
 * Extract numeric id from slug like: "1217-radian-ar-15..."
 * This keeps URLs pretty while still letting us fetch by ID.
 */
function extractNumericId(productSlug: string): number | null {
  if (!productSlug) return null;
  const first = productSlug.split("-")[0];
  const n = Number(first);
  return Number.isFinite(n) && n > 0 ? n : null;
}

function formatPrice(price: number | null | undefined): string {
  if (price == null) return "—";
  return `$${price.toFixed(2)}`;
}

/**
 * Derive a friendly merchant label.
 * Priority:
 * 1) offer.merchantName (best)
 * 2) hostname from offer.buyUrl (fallback)
 * 3) "Retailer"
 */
function getHostFromUrl(url?: string | null): string | null {
  if (!url) return null;
  try {
    const u = new URL(url);
    return u.host.replace(/^www\./, "");
  } catch {
    return null;
  }
}

function toTitleCase(s: string): string {
  return s
    .replace(/[-_]+/g, " ")
    .replace(/\b\w/g, (c) => c.toUpperCase());
}

function merchantLabel(offer: OfferFromApi): string {
  const name = offer.merchantName?.trim();
  if (name) return name;

  const host = getHostFromUrl(offer.buyUrl);
  if (host) return toTitleCase(host.split(".")[0]);

  return "Retailer";
}

/**
 * Sort offers:
 * 1) lowest price first
 * 2) in-stock before out-of-stock
 * 3) merchant label tiebreaker
 */
function sortOffers(offers: OfferFromApi[]): OfferFromApi[] {
  return [...offers].sort((a, b) => {
    const ap = a.price ?? Number.POSITIVE_INFINITY;
    const bp = b.price ?? Number.POSITIVE_INFINITY;
    if (ap !== bp) return ap - bp;

    // in-stock first (false sorts later)
    const aStock = a.inStock === false ? 1 : 0;
    const bStock = b.inStock === false ? 1 : 0;
    if (aStock !== bStock) return aStock - bStock;

    return merchantLabel(a).localeCompare(merchantLabel(b));
  });
}

export default function ProductDetailsPage() {
  const params = useParams();
  const router = useRouter();
  const searchParams = useSearchParams();

  // Route params
  const platformParam = String(params.platform ?? "");
  const partRoleParam = String(params.partRole ?? "");
  const productSlug = String(params.productSlug ?? "");

  // Platform comes from path segment (fallback to ?platform just in case)
  const platform =
    platformParam || (searchParams.get("platform") as string) || "AR-15";

  const normalizedRole = useMemo(
    () => normalizePartRole(partRoleParam),
    [partRoleParam]
  );

  /**
   * categoryId drives builder state selection/removal
   * (based on partRole -> category mapping).
   */
  const categoryId = useMemo(() => {
    return (
      PART_ROLE_TO_CATEGORY[partRoleParam] ??
      PART_ROLE_TO_CATEGORY[normalizedRole] ??
      null
    );
  }, [partRoleParam, normalizedRole]);

  const numericId = useMemo(() => extractNumericId(productSlug), [productSlug]);

  // Read-only build state (builder page owns writes)
  const [build, setBuild] = useState<BuildState>(() => {
    if (typeof window === "undefined") return {};
    try {
      const stored = window.localStorage.getItem(STORAGE_KEY);
      return stored ? (JSON.parse(stored) as BuildState) : {};
    } catch {
      return {};
    }
  });

  // Keep build in sync if user changes build elsewhere
  useEffect(() => {
    if (typeof window === "undefined") return;
    const onStorage = (e: StorageEvent) => {
      if (e.key !== STORAGE_KEY) return;
      try {
        const stored = window.localStorage.getItem(STORAGE_KEY);
        setBuild(stored ? (JSON.parse(stored) as BuildState) : {});
      } catch {
        // ignore
      }
    };
    window.addEventListener("storage", onStorage);
    return () => window.removeEventListener("storage", onStorage);
  }, []);

  const selectedPartIdForCategory = categoryId ? build?.[categoryId] : undefined;
  const isSelected =
    !!categoryId &&
    selectedPartIdForCategory === (numericId ? String(numericId) : "");

  // Product fetch state
  const [product, setProduct] = useState<GunbuilderProductFromApi | null>(null);
  const [loading, setLoading] = useState<boolean>(true);
  const [error, setError] = useState<string | null>(null);

  // Offers fetch state (from /products/:id/offers)
  const [offersFromApi, setOffersFromApi] = useState<OfferFromApi[]>([]);
  const [offersLoading, setOffersLoading] = useState(false);

  // Image modal state
  const [isImageOpen, setIsImageOpen] = useState(false);

  /**
   * Route normalization:
   * If platform segment is missing/empty, rewrite to canonical /parts/p route.
   */
  useEffect(() => {
    if (platformParam) return;

    const qp = new URLSearchParams(searchParams.toString());
    qp.set("platform", platform || "AR-15");

    router.replace(
      `/parts/p/${encodeURIComponent(platform || "AR-15")}/${encodeURIComponent(
        partRoleParam
      )}/${encodeURIComponent(productSlug)}?${qp.toString()}`
    );
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [platformParam, platform, partRoleParam, productSlug, router, searchParams]);

  /**
   * Fetch product details from API:
   * GET /api/v1/products/:id
   */
  useEffect(() => {
    if (!numericId) {
      setError("Invalid product id.");
      setLoading(false);
      return;
    }

    const controller = new AbortController();

    async function fetchProduct() {
      try {
        setLoading(true);
        setError(null);

        const url = `/api/catalog/products/${numericId}`;
        const res = await fetch(url, {
          signal: controller.signal,
          credentials: 'include',
        });

        if (!res.ok) {
          throw new Error(`Failed to load product (${res.status})`);
        }

        const data: GunbuilderProductFromApi = await res.json();
        console.log('[DEBUG] Product from API:', {
          id: data.id,
          name: data.name,
          buyUrl: data.buyUrl,
          buyShortUrl: data.buyShortUrl
        });
        setProduct(data);
      } catch (err: any) {
        if (err?.name === "AbortError") return;
        setError(err?.message ?? "Failed to load product");
      } finally {
        setLoading(false);
      }
    }

    fetchProduct();
    return () => controller.abort();
  }, [numericId]);

  /**
   * Fetch offers (rich offer data)
   * GET /api/v1/products/:id/offers
   */
  useEffect(() => {
    if (!numericId) return;

    const controller = new AbortController();

    async function fetchOffers() {
      try {
        setOffersLoading(true);

        const url = `/api/catalog/products/${numericId}/offers`;
        const res = await fetch(url, {
          signal: controller.signal,
          credentials: 'include',
        });

        if (!res.ok) {
          throw new Error(`Failed to load offers (${res.status})`);
        }

        const data: OfferFromApi[] = await res.json();
        console.log('[DEBUG] Offers from API:', data);
        setOffersFromApi(Array.isArray(data) ? data : []);
      } catch (err: any) {
        if (err?.name === "AbortError") return;
        // offers failing shouldn't kill the page
        setOffersFromApi([]);
      } finally {
        setOffersLoading(false);
      }
    }

    fetchOffers();
    return () => controller.abort();
  }, [numericId]);

  /**
   * Builder selection toggle:
   * - If selected -> remove from build
   * - Else -> add to build
   */
  const handleTogglePart = () => {
    if (!numericId) return;

    if (!categoryId) {
      alert(
        `No CategoryId mapping found for partRole "${partRoleParam}". Add it in catalogMappings.`
      );
      return;
    }

    const qp = new URLSearchParams();
    qp.set("platform", platform || "AR-15");

    if (isSelected) {
      qp.set("remove", String(categoryId));
      router.push(`/builder?${qp.toString()}`);
      return;
    }

    qp.set("select", `${categoryId}:${numericId}`);
    router.push(`/builder?${qp.toString()}`);
  };

  const imageUrl = product?.imageUrl ?? product?.mainImageUrl ?? null;

  /**
   * Offers normalization:
   * - Prefer offers endpoint data
   * - Fallback to legacy single-offer derived from product if needed
   */
  const offers = useMemo(() => {
    if (offersFromApi.length > 0) {
      console.log('[DEBUG] Using offers from API, first offer:', offersFromApi[0]);
      const fallbackShortUrl = product?.buyShortUrl ?? null;
      const normalized = offersFromApi.map((offer) => ({
        ...offer,
        buyShortUrl: offer.buyShortUrl || fallbackShortUrl,
      }));
      return sortOffers(normalized);
    }

    if (product?.buyUrl || product?.buyShortUrl) {
      console.log('[DEBUG] Using fallback from product, buyShortUrl:', product.buyShortUrl, 'buyUrl:', product.buyUrl);
      return sortOffers([
        {
          merchantName: product.merchantName ?? "Retailer",
          price: product.price,
          buyUrl: product.buyShortUrl || product.buyUrl,
          inStock: product.inStock ?? true,
        },
      ]);
    }

    return [];
  }, [offersFromApi, product]);

  /**
   * Best offer (sorted offers[0])
   */
  const bestOffer = offers[0] ?? null;

  /**
   * Helper: identify the best offer row
   */
  const isBestOffer = (offer: OfferFromApi) =>
    !!bestOffer &&
    offer.id != null &&
    bestOffer.id != null &&
    String(offer.id) === String(bestOffer.id);

    useEffect(() => {
      console.log("OFFERS", offers);
      console.log("BEST", bestOffer);
    }, [offers, bestOffer]);

  // Use best offer for “truth” when available
  const stockValue = bestOffer?.inStock ?? product?.inStock ?? null;
  const currentPrice = bestOffer?.price ?? product?.price ?? null;

  if (!categoryId) {
    return (
      <main className="min-h-screen bg-black text-zinc-50">
        <div className="mx-auto max-w-6xl px-4 py-6 lg:py-10">
          <div className="text-center">
            <h1 className="text-2xl font-semibold text-zinc-50 mb-4">
              Unknown Part Role
            </h1>
            <p className="text-sm text-zinc-400 mb-6">
              No mapping found for{" "}
              <span className="text-zinc-200">{partRoleParam}</span>. Add it to{" "}
              <span className="text-zinc-200">catalogMappings</span>.
            </p>
            <Link
              href={`/parts/p/${encodeURIComponent(
                platform
              )}/${encodeURIComponent(partRoleParam)}`}
              className="text-amber-300 hover:text-amber-200 underline"
            >
              Back to Parts List
            </Link>
          </div>
        </div>
      </main>
    );
  }

  return (
    <main className="min-h-screen bg-black text-zinc-50">
      <div className="mx-auto max-w-6xl px-4 py-6 lg:py-10">
        {/* Breadcrumbs */}
        <header className="mb-6">
          <div className="flex flex-wrap items-center gap-2 text-xs text-zinc-500">
            <Link
              href={{
                pathname: "/builder",
                query: platform ? { platform } : {},
              }}
              className="hover:text-zinc-300"
            >
              Builder
            </Link>
            <span className="text-zinc-700">/</span>
            <Link
              href={`/parts/p/${encodeURIComponent(
                platform
              )}/${encodeURIComponent(partRoleParam)}`}
              className="hover:text-zinc-300"
            >
              Parts
            </Link>
            <span className="text-zinc-700">/</span>
            <span className="text-zinc-300">Details</span>
          </div>

          <div className="mt-4 flex items-start justify-between gap-4">
            <div>
              <p className="text-xs font-semibold tracking-[0.2em] uppercase text-zinc-500">
                BATTL BUILDERS
              </p>
              <h1 className="mt-1 text-2xl md:text-3xl font-semibold tracking-tight">
                Product <span className="text-amber-300">Details</span>
              </h1>
              <p className="mt-2 text-sm text-zinc-400 max-w-2xl">
                Offers, pricing placeholders, and builder actions — all on the
                canonical /parts/p route.
              </p>
            </div>
          </div>
        </header>

        {/* Body */}
        <section className="rounded-lg border border-zinc-800 bg-zinc-950/60 p-4 md:p-6">
          {loading ? (
            <p className="py-10 text-center text-sm text-zinc-500">
              Loading product…
            </p>
          ) : error ? (
            <p className="py-10 text-center text-sm text-red-400">
              {error} — check that the Ballistic API is running.
            </p>
          ) : !product ? (
            <p className="py-10 text-center text-sm text-zinc-500">
              Product not found.
            </p>
          ) : (
            <div className="grid gap-6 md:grid-cols-[280px_1fr]">
              {/* Left */}
              <div className="space-y-3">
                <div className="rounded-md border border-zinc-800 bg-zinc-950/80 p-3">
                  <div className="aspect-square w-full overflow-hidden rounded-md border border-zinc-800 bg-black">
                    {imageUrl ? (
                      <button
                        type="button"
                        onClick={() => setIsImageOpen(true)}
                        className="h-full w-full"
                        title="Click to enlarge"
                      >
                        <ProductImage
                          src={imageUrl}
                          alt={product.name}
                          className="h-full w-full object-contain p-2"
                        />
                      </button>
                    ) : (
                      <div className="flex h-full w-full items-center justify-center text-xs text-zinc-600">
                        No image
                      </div>
                    )}
                  </div>

                  <div className="mt-3 flex items-center justify-between">
                    <span className="text-[10px] uppercase tracking-[0.16em] text-zinc-500">
                      Stock
                    </span>
                    <span
                      className={`text-xs font-semibold ${
                        stockValue === false
                          ? "text-red-300"
                          : "text-emerald-300"
                      }`}
                    >
                      {stockValue === false ? "Out of stock" : "In stock"}
                    </span>
                  </div>

                  <div className="mt-3 flex gap-2">
                    <Link
                      href={`/parts/p/${encodeURIComponent(
                        platform
                      )}/${encodeURIComponent(partRoleParam)}`}
                      className="flex-1 rounded-md border border-zinc-700 bg-zinc-900/70 px-3 py-2 text-center text-xs font-medium text-zinc-300 transition-colors hover:border-zinc-600 hover:bg-zinc-800"
                    >
                      Back to List
                    </Link>

                    <button
                      type="button"
                      onClick={handleTogglePart}
                      className={`flex-1 rounded-md px-3 py-2 text-center text-xs font-semibold transition-colors ${
                        isSelected
                          ? "border border-zinc-600 bg-zinc-800 text-zinc-100 hover:bg-zinc-700"
                          : "bg-amber-400 text-black hover:bg-amber-300"
                      }`}
                    >
                      {isSelected ? "Remove" : "Add to Build"}
                    </button>
                  </div>
                </div>

                {/* Price history placeholder */}
                <div className="rounded-md border border-zinc-800 bg-zinc-950/80 p-3">
                  <div className="flex items-center justify-between">
                    <h3 className="text-xs font-semibold uppercase tracking-[0.16em] text-zinc-500">
                      Price History
                    </h3>
                    <span className="text-[10px] text-zinc-600">placeholder</span>
                  </div>
                  <div className="mt-2 h-28 rounded border border-zinc-800 bg-zinc-950 flex items-center justify-center text-xs text-zinc-600">
                    Pricing graph will go here
                  </div>
                  <p className="mt-2 text-[11px] text-zinc-500">
                    We’ll wire this to price snapshots once the offer model is
                    stable.
                  </p>
                </div>
              </div>

              {/* Right */}
              <div className="min-w-0 space-y-4">
                {/* Product meta */}
                <div className="rounded-md border border-zinc-800 bg-zinc-950/80 p-4">
                  <div className="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
                    <div className="min-w-0">
                      <p className="text-xs font-semibold tracking-[0.2em] uppercase text-zinc-500">
                        {product.brand}
                      </p>
                      <h2 className="mt-1 text-xl md:text-2xl font-semibold text-zinc-50">
                        {product.name}
                      </h2>

                      <div className="mt-2 flex flex-wrap gap-2 text-xs">
                        <span className="rounded border border-zinc-800 bg-zinc-900/60 px-2 py-1 text-zinc-300">
                          Platform:{" "}
                          <span className="font-semibold text-zinc-100">
                            {product.platform || platform}
                          </span>
                        </span>
                        {product.caliber && (
                          <span className="rounded border border-zinc-800 bg-zinc-900/60 px-2 py-1 text-zinc-300">
                            Caliber:{" "}
                            <span className="font-semibold text-zinc-100">
                              {product.caliber}
                            </span>
                          </span>
                        )}
                        <span className="rounded border border-zinc-800 bg-zinc-900/60 px-2 py-1 text-zinc-300">
                          Role:{" "}
                          <span className="font-semibold text-zinc-100">
                            {product.partRole || partRoleParam}
                          </span>
                        </span>
                        <span className="rounded border border-zinc-800 bg-zinc-900/60 px-2 py-1 text-zinc-300">
                          ID:{" "}
                          <span className="font-semibold text-zinc-100">
                            {product.id}
                          </span>
                        </span>
                      </div>
                    </div>

                    <div className="shrink-0 text-right">
                      <div className="text-[10px] uppercase tracking-[0.16em] text-zinc-500">
                        Current price
                      </div>
                      <div className="mt-1 text-2xl font-semibold text-amber-300">
                        {formatPrice(currentPrice)}
                      </div>
                    </div>
                  </div>

                  {(product.shortDescription || product.description) && (
                    <div className="mt-4 border-t border-zinc-800 pt-4">
                      {product.shortDescription ? (
                        <p className="text-sm text-zinc-300">
                          {product.shortDescription}
                        </p>
                      ) : null}
                      {product.description ? (
                        <p className="mt-2 whitespace-pre-wrap text-sm text-zinc-400">
                          {product.description}
                        </p>
                      ) : null}
                    </div>
                  )}
                </div>

                {/* Offers */}
                <div className="rounded-md border border-zinc-800 bg-zinc-950/80 p-4">
                  <div className="flex items-center justify-between">
                    <h3 className="text-xs font-semibold uppercase tracking-[0.16em] text-zinc-500">
                      Merchant Offers
                    </h3>
                    <span className="text-[10px] text-zinc-600">
                      {offersLoading
                        ? "loading…"
                        : offers.length
                        ? `${offers.length} offers`
                        : "no offers"}
                    </span>
                  </div>

                  {offers.length ? (
                    <div className="mt-3 overflow-x-auto rounded border border-zinc-800">
                      <table className="min-w-full text-sm">
                        <thead className="bg-zinc-900/60">
                          <tr className="text-xs uppercase tracking-[0.14em] text-zinc-500">
                            <th className="px-3 py-2 text-left">Merchant</th>
                            <th className="px-3 py-2 text-left">Stock</th>
                            <th className="px-3 py-2 text-right">Price</th>
                            <th className="px-3 py-2 text-right">Action</th>
                          </tr>
                        </thead>
                        <tbody className="divide-y divide-zinc-800">
                          {offers.map((o, idx) => (
                            <tr
                              key={String(o.id ?? idx)}
                              className={`hover:bg-zinc-900/40 ${
                                isBestOffer(o)
                                  ? "bg-amber-400/10 border-l-2 border-amber-400"
                                  : ""
                              }`}
                            >
                              <td className="px-3 py-2 text-zinc-200 flex items-center">
                                <span>{merchantLabel(o)}</span>

                                {isBestOffer(o) && (
                                  <span className="ml-2 inline-flex items-center rounded bg-amber-400 px-2 py-0.5 text-[10px] font-semibold text-black">
                                    BEST DEAL
                                  </span>
                                )}
                              </td>
                              <td className="px-3 py-2 text-xs">
                                {o.inStock === false ? (
                                  <span className="text-red-300">
                                    Out of stock
                                  </span>
                                ) : (
                                  <span className="text-emerald-300">
                                    In stock
                                  </span>
                                )}
                              </td>
                              <td className="px-3 py-2 text-right font-semibold text-amber-300">
                                {o.price != null ? `$${o.price.toFixed(2)}` : "—"}
                              </td>
                              <td className="px-3 py-2 text-right">
                                {(o.buyShortUrl || o.buyUrl) ? (
                                  <a
                                    href={o.buyShortUrl || o.buyUrl}
                                    target="_blank"
                                    rel="noreferrer"
                                    className="inline-flex items-center justify-center rounded-md bg-amber-400 px-3 py-1.5 text-xs font-semibold text-black hover:bg-amber-300"
                                    onClick={() => trackAffiliateLinkClicked(product?.name ?? "", merchantLabel(o))}
                                  >
                                    Buy
                                  </a>
                                ) : (
                                  <span className="text-xs text-zinc-600">—</span>
                                )}
                              </td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  ) : (
                    <p className="mt-3 text-sm text-zinc-500">
                      No offers attached yet. Once offers are available, this
                      becomes the “where to buy” table.
                    </p>
                  )}

                  {/* Best Offer CTA */}
                  {(bestOffer?.buyShortUrl || bestOffer?.buyUrl) ? (
                    <div className="mt-3 flex justify-end">
                      <a
                        href={bestOffer.buyShortUrl || bestOffer.buyUrl}
                        target="_blank"
                        rel="noreferrer"
                        className="rounded-md border border-zinc-700 bg-zinc-900/70 px-4 py-2 text-sm font-semibold text-zinc-200 hover:bg-zinc-800"
                        onClick={() => trackAffiliateLinkClicked(product?.name ?? "", merchantLabel(bestOffer))}
                      >
                        Buy from {merchantLabel(bestOffer)} →
                      </a>
                    </div>
                  ) : null}
                </div>

                {/* Footer tips */}
                <div className="flex flex-wrap gap-2 text-xs text-zinc-500">
                  {/* <span className="rounded border border-zinc-800 bg-zinc-950/60 px-2 py-1">
                    Tip: Add this part, then go back and compare alternates.
                  </span> */}
                  {/* <span className="rounded border border-zinc-800 bg-zinc-950/60 px-2 py-1">
                    Canonical route:{" "}
                    <span className="text-zinc-300">
                      /parts/p/{platform}/{partRoleParam}/{productSlug}
                    </span>
                  </span> */}
                </div>
              </div>
            </div>
          )}
        </section>

        {/* Image modal */}
        {isImageOpen && imageUrl ? (
          <div
            className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 p-4"
            onClick={() => setIsImageOpen(false)}
          >
            <div
              className="relative max-h-[90vh] max-w-[90vw]"
              onClick={(e) => e.stopPropagation()}
            >
              <button
                type="button"
                onClick={() => setIsImageOpen(false)}
                className="absolute -top-3 -right-3 rounded-full border border-zinc-700 bg-zinc-900 px-3 py-2 text-xs font-semibold text-zinc-200 hover:bg-zinc-800"
              >
                Close
              </button>

              <ProductImage
                src={imageUrl}
                alt={product?.name ?? "Product image"}
                className="max-h-[90vh] max-w-[90vw] rounded-lg border border-zinc-800 bg-black object-contain"
              />
            </div>
          </div>
        ) : null}
      </div>
    </main>
  );
}
