"use client";

/**
 * AdBanner — displays an ad image (when configured) or an
 * unobtrusive placeholder for future monetization.
 *
 * Usage:
 *   <AdBanner slot="between-popular" />          ← auto-fetches from /api/ads/slot/…
 *   <AdBanner slot="between-popular" ad={data} /> ← uses pre-fetched data (SSR)
 *
 * Slot names:
 *  leaderboard-top      970×90  — between navbar and hero
 *  between-popular      728×90  — between Popular Cars and Electric Cars
 *  between-electric     728×90  — between Electric Cars and News
 *  between-news         728×90  — below Latest News
 *  sidebar-right        300×600 — sticky desktop sidebar
 *  article-inline       468×60  — every 3 paragraphs in articles
 */

import { useEffect, useRef, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { cn } from "@/lib/utils";
import { useLazySection } from "@/lib/hooks/useLazySection";
import { resolveUploadUrl } from "@/lib/uploadUrl";

export type AdSlotName =
  | "leaderboard-top"
  | "between-popular"
  | "between-electric"
  | "between-news"
  | "sidebar-right"
  | "article-inline";

interface Ad {
  id: string;
  slot: string;
  image?: string;
  targetUrl?: string;
  altText?: string;
  active?: boolean;
}

interface Props {
  slot: AdSlotName;
  /** Pre-fetched ad data (SSR). If omitted the component fetches on mount. */
  ad?: Ad | null;
  className?: string;
}

const SLOT_CONFIG: Record<AdSlotName, { w: number; h: number; label: string }> = {
  "leaderboard-top":  { w: 970, h: 90,  label: "Advertisement" },
  "between-popular":  { w: 728, h: 90,  label: "Advertisement" },
  "between-electric": { w: 728, h: 90,  label: "Advertisement" },
  "between-news":     { w: 728, h: 90,  label: "Advertisement" },
  "sidebar-right":    { w: 300, h: 600, label: "Advertisement" },
  "article-inline":   { w: 468, h: 60,  label: "Advertisement" },
};

const API_BASE =
  process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000";

/** Fire-and-forget ad analytics event — never throws. */
function trackAd(id: string, event: "view" | "click") {
  fetch(`${API_BASE}/api/ads/${id}/${event}`, { method: "POST" }).catch(() => {});
}

export default function AdBanner({ slot, ad: adProp, className }: Props) {
  const config = SLOT_CONFIG[slot];
  const [ad, setAd] = useState<Ad | null>(adProp ?? null);
  const [fetched, setFetched] = useState(adProp !== undefined);
  const viewFiredRef = useRef(false); // guard: fire view only once per mount

  // Only observe when we still need to auto-fetch — skip for leaderboard-top
  // (it's above the fold so always visible on mount)
  const isAboveFold = slot === "leaderboard-top";
  const { ref, isVisible } = useLazySection({ rootMargin: "400px", fallback: isAboveFold });

  // If caller pre-fetched the ad (SSR), fire view impression on mount
  useEffect(() => {
    if (adProp?.id && !viewFiredRef.current) {
      viewFiredRef.current = true;
      trackAd(adProp.id, "view");
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Auto-fetch only when no `ad` prop was supplied AND the slot is near viewport
  useEffect(() => {
    if (adProp !== undefined) return;          // caller already provided data
    if (!isVisible) return;                    // not in viewport yet — wait
    let cancelled = false;
    console.log("[AdBanner] fetching slot:", slot);
    fetch(`${API_BASE}/api/ads/slot/${slot}`)
      .then((r) => (r.ok ? r.json() : null))
      .then((json) => {
        if (!cancelled) {
          console.log("[AdBanner] response", json);
          console.log("[AdBanner] ad", json?.ad);
          const fetchedAd = json?.ad ?? null;
          setAd(fetchedAd);
          setFetched(true);
          // Fire view impression once when we confirm an ad is showing
          if (fetchedAd?.id && !viewFiredRef.current) {
            viewFiredRef.current = true;
            trackAd(fetchedAd.id, "view");
          }
        }
      })
      .catch((err) => {
        console.error("[AdBanner] fetch error for slot", slot, err);
        if (!cancelled) setFetched(true);
      });
    return () => { cancelled = true; };
  }, [slot, adProp, isVisible]);

  if (!config) return null;

  // Show nothing until we know whether there is an ad
  // (prevents layout shift from immediately rendering a placeholder)
  // Note: ref is still attached below so IntersectionObserver can fire
  if (!fetched && !isVisible) return <div ref={ref} aria-hidden="true" style={{ minHeight: 1 }} />;

  // ── Active ad with image ────────────────────────────────────────────────────
  if (ad?.image) {
    const img = (
      <div
        className={cn("relative overflow-hidden rounded-xl mx-auto", className)}
        style={{ maxWidth: config.w, aspectRatio: `${config.w}/${config.h}` }}
      >
        <Image
          src={resolveUploadUrl(ad.image)}
          alt={ad.altText || "Advertisement"}
          fill
          className="object-cover"
          sizes={`${config.w}px`}
        />
      </div>
    );

    return (
      // Block (not flex) wrapper — flex collapses a fill-image container to 0×0
      // because it has no in-flow content. Block layout lets the inner div use
      // width:auto (= fill parent), maxWidth constrains it, mx-auto centres it.
      <div className="py-3">
        {ad.targetUrl ? (
          <Link
            href={ad.targetUrl}
            target="_blank"
            rel="noopener noreferrer nofollow"
            className="block"
            aria-label="Advertisement"
            onClick={() => ad?.id && trackAd(ad.id, "click")}
          >
            {img}
          </Link>
        ) : (
          img
        )}
      </div>
    );
  }

  // ── Placeholder ────────────────────────────────────────────────────────────
  return (
    <div className={cn("py-3 flex justify-center", className)}>
      <div
        className="w-full rounded-xl border border-dashed border-gray-200 bg-gray-50/60 flex items-center justify-center"
        style={{ maxWidth: config.w, minHeight: Math.min(config.h, 90) }}
        aria-label="Advertisement placeholder"
        role="complementary"
      >
        <p className="text-[10px] font-semibold uppercase tracking-widest text-gray-300 select-none">
          {config.label} · {config.w}×{config.h}
        </p>
      </div>
    </div>
  );
}
