import React, { useEffect, useRef, useState } from "react";
import type { PickupPoint } from "../context/CheckoutContext";

const PPL_WIDGET_API_KEY =
  process.env.NEXT_PUBLIC_PPL_WIDGET_API_KEY ||
  "ak_87faa40f358e4d80830fea818c0238bf";

type PplWidgetElement = HTMLElement & {
  open?: () => void;
  configure?: (options: Record<string, unknown>) => void;
};

function loadScript(id: string, src: string) {
  return new Promise<void>((resolve, reject) => {
    const existing = document.getElementById(id) as HTMLScriptElement | null;
    if (existing?.dataset.loaded === "true") {
      resolve();
      return;
    }
    if (existing) {
      existing.addEventListener("load", () => resolve(), { once: true });
      existing.addEventListener("error", () => reject(new Error("PPL widget se nepodařilo načíst.")), { once: true });
      return;
    }
    const script = document.createElement("script");
    script.id = id;
    script.src = src;
    script.async = true;
    script.addEventListener(
      "load",
      () => {
        script.dataset.loaded = "true";
        resolve();
      },
      { once: true },
    );
    script.addEventListener(
      "error",
      () => reject(new Error("PPL widget se nepodařilo načíst.")),
      { once: true },
    );
    document.head.appendChild(script);
  });
}

export type NearbyPickupPoint = {
  id: string;
  name: string;
  address: string;
  street?: string;
  city?: string;
  zip?: string;
  isNonstop?: boolean;
  distanceKm?: number;
  latitude?: number;
  longitude?: number;
};

const CARRIER_TO_PROVIDER: Record<string, string> = {
  packeta: "packeta",
  ppl: "ppl",
  czech_post: "balikovna",
  gls: "gls",
  dpd: "dpd",
};

const PROVIDER_LOGOS: Record<string, string> = {
  packeta: "/images/dopravci/packeta.png",
  ppl: "/images/dopravci/ppl2.png",
  balikovna: "/images/dopravci/balikovna.png",
  gls: "/images/dopravci/gls.png",
  dpd: "/images/dopravci/dpd.png",
};

function toCheckoutPoint(point: NearbyPickupPoint): PickupPoint {
  return {
    id: point.id,
    name: point.name,
    city: point.city || "",
    street: point.street || point.address,
    zip: point.zip || "",
    country: "CZ",
    pickupPointType: point.isNonstop ? "box" : "pickup",
    place: point.name,
    code: point.id,
    latitude: point.latitude,
    longitude: point.longitude,
  };
}

export default function PickupPointSuggestions({
  carrier,
  shippingType,
  street,
  city,
  zip,
  selectedPoint,
  onSelect,
  onOpenMap,
}: {
  carrier?: string;
  shippingType?: string;
  street?: string;
  city?: string;
  zip?: string;
  selectedPoint: PickupPoint | null;
  onSelect: (point: PickupPoint) => void;
  onOpenMap: () => void;
}) {
  const [suggestions, setSuggestions] = useState<NearbyPickupPoint[]>([]);
  const [loading, setLoading] = useState(false);
  const pplHostRef = useRef<HTMLDivElement>(null);
  const pplWidgetRef = useRef<PplWidgetElement | null>(null);
  const provider = carrier ? CARRIER_TO_PROVIDER[carrier] : "";
  const searchAddress = [street, zip, city].filter(Boolean).join(", ");
  const canSearch = Boolean(city?.trim() && zip?.trim() && street?.trim() && provider);

  useEffect(() => {
    if (!canSearch || !provider) {
      setSuggestions([]);
      setLoading(false);
      return;
    }

    const controller = new AbortController();
    const timer = window.setTimeout(() => {
      setLoading(true);
      const params = new URLSearchParams({
        provider,
        address: searchAddress,
        city: city!.trim(),
        postalCode: zip!.trim(),
        ...(shippingType ? { type: shippingType } : {}),
      });
      fetch(`/api/shipping/suggestions?${params}`, {
        signal: controller.signal,
        cache: "no-store",
      })
        .then((response) => (response.ok ? response.json() : Promise.reject()))
        .then((result: { points?: NearbyPickupPoint[] }) => {
          setSuggestions(Array.isArray(result.points) ? result.points : []);
        })
        .catch(() => {
          if (!controller.signal.aborted) setSuggestions([]);
        })
        .finally(() => {
          if (!controller.signal.aborted) setLoading(false);
        });
    }, 350);

    return () => {
      window.clearTimeout(timer);
      controller.abort();
    };
  }, [canSearch, provider, searchAddress, city, zip, shippingType]);

  useEffect(() => {
    if (carrier !== "ppl" || !pplHostRef.current) return;

    let active = true;
    const host = pplHostRef.current;

    loadScript(
      "ppl-access-point-widget-loader",
      "https://www.ppl.cz/accesspointwidget/loader.js",
    )
      .then(() => customElements.whenDefined("ppl-access-point-widget"))
      .then(() => {
        if (!active || !host) return;
        const widget = document.createElement(
          "ppl-access-point-widget",
        ) as PplWidgetElement;
        widget.setAttribute("id", "pplWidget");
        widget.setAttribute("api-key", PPL_WIDGET_API_KEY);
        widget.setAttribute(
          "config",
          JSON.stringify({
            viewMode: "modal",
            allowedCountries: ["CZ"],
            defaultCountry: "CZ",
            defaultLang: "cs",
            centeredToAddress: searchAddress || undefined,
          }),
        );
        widget.addEventListener(
          "ppl-accesspointwidget-select",
          ((event: CustomEvent) => {
            const point =
              event.detail && typeof event.detail === "object"
                ? (event.detail as Record<string, unknown>)
                : {};
            const address =
              point.address && typeof point.address === "object"
                ? (point.address as Record<string, unknown>)
                : {};
            const id = String(point.code || point.id || "").trim();
            if (!id) return;
            onSelect({
              id,
              name: String(point.name || point.title || id),
              city: String(address.city || ""),
              street: String(address.street || ""),
              zip: String(address.zipCode || address.postalCode || ""),
              country: "CZ",
              pickupPointType: String(point.accessPointType || "ParcelShop"),
              place: String(point.name || id),
              code: id,
              rawDetail: point,
            });
          }) as EventListener,
        );
        host.replaceChildren(widget);
        pplWidgetRef.current = widget;
      })
      .catch(() => {
        pplWidgetRef.current = null;
      });

    return () => {
      active = false;
      pplWidgetRef.current = null;
      host.replaceChildren();
    };
  }, [carrier, searchAddress, onSelect]);

  const handleOpenMap = () => {
    if (carrier === "ppl") {
      pplWidgetRef.current?.configure?.({
        centeredToAddress: searchAddress || undefined,
        defaultCountry: "CZ",
        allowedCountries: ["CZ"],
        defaultLang: "cs",
        viewMode: "modal",
      });
      if (pplWidgetRef.current?.open) {
        pplWidgetRef.current.open();
        return;
      }
    }
    onOpenMap();
  };

  if (!carrier) return null;

  const selectedIsSuggested = Boolean(
    selectedPoint &&
      suggestions.some((point) => String(point.id) === String(selectedPoint.id)),
  );

  return (
    <div className="mt-4 pt-4 border-t border-luxury-gold/20">
      <h3 className="text-base md:text-lg font-aptos font-black text-luxury-gold mb-3">
        Výdejní místa v okolí
      </h3>

      {canSearch ? (
        <p className="text-sm text-luxury-light/70 mb-4">
          Podle adresy <span className="text-luxury-gold font-bold">{searchAddress}</span>
        </p>
      ) : (
        <p className="text-sm text-luxury-light/70 mb-4">
          Vyplňte ulici, město a PSČ v kontaktních údajích, ať můžeme nabídnout
          nejbližší výdejní místa.
        </p>
      )}

      <div ref={pplHostRef} />
      <button
        type="button"
        onClick={handleOpenMap}
        className="mb-4 bg-luxury-gold text-luxury-dark px-6 py-3 rounded-sm font-black text-sm uppercase tracking-widest hover:bg-yellow-300 transition-all duration-300 active:scale-95 shadow-lg"
      >
        Vybrat z mapy
      </button>

      {loading && (
        <p className="text-sm text-luxury-light/60 mb-4">
          Hledám nejbližší možnosti…
        </p>
      )}

      {suggestions.length > 0 && (
        <div className="space-y-2 mb-4">
          {suggestions.map((point) => {
            const selected = String(selectedPoint?.id) === String(point.id);
            return (
              <button
                key={`${provider}-${point.id}`}
                type="button"
                onClick={() => onSelect(toCheckoutPoint(point))}
                className={`w-full text-left p-4 rounded-lg border-2 transition-all duration-300 ${
                  selected
                    ? "border-luxury-gold bg-luxury-dark/80 shadow-lg shadow-luxury-gold/20"
                    : "border-luxury-gold/20 hover:border-luxury-gold/50"
                }`}
              >
                <div className="flex items-start justify-between gap-3">
                  <div className="min-w-0">
                    <p className="font-bold text-luxury-light flex items-center gap-2 flex-wrap">
                      {point.name}
                      {point.isNonstop && (
                        <span className="inline-flex items-center rounded-full bg-green-500/15 px-2 py-0.5 text-[11px] font-black uppercase tracking-wide text-green-400">
                          24/7
                        </span>
                      )}
                    </p>
                    <p className="text-sm text-luxury-light/60 mt-1">
                      {point.address}
                    </p>
                  </div>
                  <div className="flex flex-col items-end gap-1 flex-shrink-0">
                    {typeof point.distanceKm === "number" && (
                      <span className="text-xs text-luxury-gold font-bold">
                        {point.distanceKm.toLocaleString("cs-CZ", {
                          maximumFractionDigits: 1,
                        })}{" "}
                        km
                      </span>
                    )}
                    {PROVIDER_LOGOS[provider] && (
                      <div className="w-10 h-10 bg-white rounded-md p-1">
                        <img
                          src={PROVIDER_LOGOS[provider]}
                          alt=""
                          className="w-full h-full object-contain"
                        />
                      </div>
                    )}
                  </div>
                </div>
              </button>
            );
          })}
        </div>
      )}

      {selectedPoint && !selectedIsSuggested && (
        <div className="p-4 md:p-6 bg-luxury-dark/50 rounded-lg border-2 border-luxury-gold">
          <p className="text-sm font-bold text-luxury-gold uppercase mb-2">
            Vybrané výdejní místo
          </p>
          <p className="font-bold text-luxury-light mb-1 flex items-center gap-2 flex-wrap">
            {selectedPoint.place || selectedPoint.name}
            {selectedPoint.pickupPointType === "box" && (
              <span className="inline-flex items-center rounded-full bg-green-500/15 px-2 py-0.5 text-[11px] font-black uppercase tracking-wide text-green-400">
                24/7
              </span>
            )}
          </p>
          <p className="text-sm text-luxury-light/60">
            {selectedPoint.street}, {selectedPoint.zip} {selectedPoint.city}
          </p>
        </div>
      )}

      {!loading && canSearch && suggestions.length === 0 && !selectedPoint && (
        <p className="text-sm text-luxury-light/60">
          Nic v okolí se nenašlo. Zkuste výběr z mapy.
        </p>
      )}
    </div>
  );
}
