"use client";

import { STATUS_MAP } from "@/config/constants";
import Image from "next/image";
import Link from "next/link";
import { useEffect, useMemo, useState, type CSSProperties } from "react";

type SortMethod = "updated" | "dist" | "alpha";
type Variant = "home" | "catalog";

type CourseStatus = {
  status?: string;
  name?: string;
};

type Facility = {
  id: number;
  slug: string;
  name: string;
  city?: string | null;
  county?: string | null;
  banetype?: string | null;
  image_url?: string | null;
  phone?: string | null;
  website_url?: string | null;
  golfbox_booking_url?: string | null;
  golfbox_tournament_url?: string | null;
  weather_url?: string | null;
  lat?: number | null;
  lng?: number | null;
  golfamore?: boolean | null;
  nsg_url?: string | null;
  vtg_pris?: number | null;
  vtg_lenke?: string | null;
  vtg_beskrivelse?: string | null;
  footnote?: string | null;
  footnote_updated_at?: string | null;
  status_updated_at?: string | null;
  amenities?: unknown;
  golfamore_data?: unknown;
  nsg_data?: unknown;
  vtg_datoer?: unknown;
  course_statuses?: unknown;
};

type FacilitySearchProps = {
  initialFacilities: Facility[];
  variant?: Variant;
  eyebrow?: string;
  title?: string;
  intro?: string;
};

type SpecialFlags = {
  hasGolfamore: boolean;
  hasNSG: boolean;
  hasSimulator: boolean;
  hasDrivingRange: boolean;
  hasVtg: boolean;
};

const AREA_GROUPS: Record<string, string[]> = {
  "nord-norge": ["finnmark", "troms", "nordland"],
  "midt-norge": ["trondelag", "nord-trondelag", "sor-trondelag"],
  vestlandet: ["more-og-romsdal", "sogn-og-fjordane", "hordaland", "rogaland", "vestland"],
  sorlandet: ["vest-agder", "aust-agder", "agder"],
  ostlandet: ["telemark", "vestfold", "ostfold", "buskerud", "hedmark", "oppland", "innlandet", "viken", "akershus", "oslo"],
  "oslo-og-akershus": ["akershus", "oslo", "viken"],
};

const HIERARCHICAL_AREA_OPTIONS = [
  { value: "", label: "Hele Norge" },
  { value: "region:nord-norge", label: "Nord-Norge" },
  { value: "county:finnmark", label: "\u00A0\u00A0\u00A0Finnmark" },
  { value: "county:troms", label: "\u00A0\u00A0\u00A0Troms" },
  { value: "county:nordland", label: "\u00A0\u00A0\u00A0Nordland" },
  { value: "region:midt-norge", label: "Midt-Norge" },
  { value: "county:nord-trondelag", label: "\u00A0\u00A0\u00A0Nord-Trøndelag" },
  { value: "county:sor-trondelag", label: "\u00A0\u00A0\u00A0Sør-Trøndelag" },
  { value: "county:trondelag", label: "\u00A0\u00A0\u00A0Trøndelag" },
  { value: "region:vestlandet", label: "Vestlandet" },
  { value: "county:more-og-romsdal", label: "\u00A0\u00A0\u00A0Møre og Romsdal" },
  { value: "county:sogn-og-fjordane", label: "\u00A0\u00A0\u00A0Sogn og Fjordane" },
  { value: "county:hordaland", label: "\u00A0\u00A0\u00A0Hordaland" },
  { value: "county:rogaland", label: "\u00A0\u00A0\u00A0Rogaland" },
  { value: "county:vestland", label: "\u00A0\u00A0\u00A0Vestland" },
  { value: "region:sorlandet", label: "Sørlandet" },
  { value: "county:vest-agder", label: "\u00A0\u00A0\u00A0Vest-Agder" },
  { value: "county:aust-agder", label: "\u00A0\u00A0\u00A0Aust-Agder" },
  { value: "county:agder", label: "\u00A0\u00A0\u00A0Agder" },
  { value: "region:ostlandet", label: "Østlandet" },
  { value: "county:telemark", label: "\u00A0\u00A0\u00A0Telemark" },
  { value: "county:vestfold", label: "\u00A0\u00A0\u00A0Vestfold" },
  { value: "county:ostfold", label: "\u00A0\u00A0\u00A0Østfold" },
  { value: "county:buskerud", label: "\u00A0\u00A0\u00A0Buskerud" },
  { value: "county:hedmark", label: "\u00A0\u00A0\u00A0Hedmark" },
  { value: "county:oppland", label: "\u00A0\u00A0\u00A0Oppland" },
  { value: "region:oslo-og-akershus", label: "\u00A0\u00A0\u00A0Oslo og Akershus" },
  { value: "county:akershus", label: "\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0Akershus" },
  { value: "county:oslo", label: "\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0Oslo" },
  { value: "county:innlandet", label: "\u00A0\u00A0\u00A0Innlandet" },
  { value: "county:viken", label: "\u00A0\u00A0\u00A0Viken" },
];

const STATUS_ORDER = [
  "aapen",
  "aapen_med_vintergreener",
  "stenger_snart",
  "aapner_snart",
  "ukjent",
  "stengt",
  "under_utvikling",
  "nedlagt",
];

const STATUS_CLASSES: Record<string, string> = {
  aapen: "bg-[#8BC34A] text-white",
  aapen_med_vintergreener: "bg-[#D2A63A] text-[#112015]",
  stenger_snart: "bg-[#FF5722] text-white",
  aapner_snart: "bg-sky-600 text-white",
  stengt: "bg-[#B6473D] text-white",
  under_utvikling: "bg-slate-600 text-white",
  nedlagt: "bg-[#112015] text-white",
  ukjent: "bg-[#D9DED5] text-[#112015]",
};

const normalizeText = (value: unknown) =>
  String(value ?? "")
    .toLowerCase()
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .replace(/[^a-z0-9]+/g, " ")
    .trim();

const normalizeStatus = (value: unknown) =>
  String(value ?? "")
    .toLowerCase()
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .replace(/\s+/g, "_")
    .replace(/[^a-z0-9_]+/g, "")
    .trim();

const slugify = (value: unknown) =>
  normalizeText(value)
    .replace(/\s+/g, "-")
    .replace(/^-+|-+$/g, "");

const parseJson = <T,>(value: unknown, fallback: T): T => {
  if (!value) return fallback;
  if (typeof value === "object") return value as T;
  try {
    return JSON.parse(String(value)) as T;
  } catch {
    return fallback;
  }
};

const getDistance = (lat1: number, lon1: number, lat2: number, lon2: number) => {
  try {
    const r = 6371;
    const dLat = ((lat2 - lat1) * Math.PI) / 180;
    const dLon = ((lon2 - lon1) * Math.PI) / 180;
    const a =
      Math.sin(dLat / 2) * Math.sin(dLat / 2) +
      Math.cos((lat1 * Math.PI) / 180) *
        Math.cos((lat2 * Math.PI) / 180) *
        Math.sin(dLon / 2) *
        Math.sin(dLon / 2);
    return r * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  } catch {
    return Number.POSITIVE_INFINITY;
  }
};

const hasTruthyAmenity = (value: unknown) => {
  const normalized = normalizeText(value);
  return Boolean(normalized) && !["nei", "no", "false", "0", "ingen"].includes(normalized);
};

const getFacilityRegions = (county: string) => {
  const countySlug = slugify(county);
  return Object.entries(AREA_GROUPS)
    .filter(([, counties]) => counties.includes(countySlug))
    .map(([region]) => region);
};

const getPrimaryStatus = (statuses: Array<{ status?: string }>) => {
  for (const candidate of STATUS_ORDER) {
    if (statuses.some((status) => normalizeStatus(status.status) === candidate)) {
      return candidate;
    }
  }
  return "ukjent";
};

const formatUpdatedDate = (value: string | null | undefined) => {
  if (!value) return "Ukjent";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return "Ukjent";
  return date.toLocaleDateString("nb-NO", {
    day: "2-digit",
    month: "short",
    year: "numeric",
  });
};

const getStatusLabel = (status: string) => STATUS_MAP[status] || "Ukjent";

const buildMapUrl = (lat?: number | null, lng?: number | null) => {
  if (typeof lat !== "number" || typeof lng !== "number") return null;
  return `https://www.google.com/maps/search/?api=1&query=${lat},${lng}`;
};

const getAreaLabel = (value: string, countyOptions: Array<{ slug: string; label: string }>) => {
  if (!value) return "Hele Norge";
  const builtIn = HIERARCHICAL_AREA_OPTIONS.find((option) => option.value === value);
  if (builtIn) return builtIn.label.trim();
  if (value.startsWith("county:")) {
    return countyOptions.find((option) => option.slug === value.replace("county:", ""))?.label || "Valgt fylke";
  }
  return "Valgt område";
};

const matchesHoleFilter = (holeValue: string, filterValue: string) => {
  const normalizedHole = normalizeText(holeValue);
  if (!filterValue) return true;
  if (filterValue === "18-plus") return normalizedHole.includes("18");
  if (filterValue === "18") return normalizedHole === "18";
  if (filterValue === "9") return normalizedHole === "9" || normalizedHole === "9 9";
  if (filterValue === "6-12") return normalizedHole === "6" || normalizedHole === "12";
  if (filterValue === "under-utvikling") return normalizedHole.includes("utvikling");
  return true;
};

const matchesSpecialFilter = (specialFilter: string, flags: SpecialFlags) => {
  if (!specialFilter) return true;
  if (specialFilter === "golfamore") return flags.hasGolfamore;
  if (specialFilter === "nsg") return flags.hasNSG;
  if (specialFilter === "simulator") return flags.hasSimulator;
  if (specialFilter === "drivingrange") return flags.hasDrivingRange;
  if (specialFilter === "vtg") return flags.hasVtg;
  return true;
};

const getSearchShellClasses = (variant: Variant) =>
  variant === "home"
    ? "rounded-[2rem] bg-[#39443B] px-4 py-5 text-white shadow-2xl sm:px-6 sm:py-7"
    : "surface-card rounded-[2rem] px-4 py-5 text-[#112015] sm:px-6 sm:py-7";

const noteClampStyle: CSSProperties = {
  display: "-webkit-box",
  WebkitBoxOrient: "vertical",
  WebkitLineClamp: 3,
  overflow: "hidden",
};

const actionIconClassName =
  "flex h-12 w-12 items-center justify-center rounded-[1.1rem] bg-white text-[#112015] shadow-sm transition hover:bg-[#FF5722] hover:text-white";

const cardActionShellClassName =
  "flex flex-wrap gap-2 rounded-[1.35rem] bg-[#25312A] p-2 text-[#112015]";

export default function FacilitySearch({
  initialFacilities,
  variant = "catalog",
  eyebrow = "Golfbaner",
  title = "Alle golfbaner samlet på ett sted",
  intro = "Bruk område, banestatus og fasiliteter for å snevre inn oversikten. Her får katalogen være arbeidsflate, ikke hero.",
}: FacilitySearchProps) {
  const [searchQuery, setSearchQuery] = useState("");
  const [areaFilter, setAreaFilter] = useState("");
  const [statusFilter, setStatusFilter] = useState("");
  const [holeFilter, setHoleFilter] = useState("");
  const [specialFilter, setSpecialFilter] = useState("");
  const [sortMethod, setSortMethod] = useState<SortMethod>("updated");
  const [userLocation, setUserLocation] = useState<{ lat: number; lng: number } | null>(null);

  useEffect(() => {
    if (!("geolocation" in navigator)) return;

    navigator.geolocation.getCurrentPosition(
      (position) => {
        setUserLocation({ lat: position.coords.latitude, lng: position.coords.longitude });
        setSortMethod((current) => (current === "updated" ? "dist" : current));
      },
      () => undefined,
      {
        enableHighAccuracy: false,
        timeout: 8000,
        maximumAge: 1000 * 60 * 30,
      }
    );
  }, []);

  const countyOptions = useMemo(() => {
    const unique = new Map<string, string>();

    for (const facility of Array.isArray(initialFacilities) ? initialFacilities : []) {
      const label = String(facility?.county || "").trim();
      const slug = slugify(label);
      if (label && slug && !unique.has(slug)) unique.set(slug, label);
    }

    return Array.from(unique.entries())
      .map(([slug, label]) => ({ slug, label }))
      .sort((a, b) => a.label.localeCompare(b.label, "nb"));
  }, [initialFacilities]);

  const areaOptions = useMemo(() => {
    const seen = new Set<string>();
    const options = HIERARCHICAL_AREA_OPTIONS.filter((option) => {
      if (seen.has(option.value)) return false;
      seen.add(option.value);
      return true;
    });

    for (const county of countyOptions) {
      const countyValue = `county:${county.slug}`;
      if (!seen.has(countyValue)) {
        options.push({ value: countyValue, label: county.label });
        seen.add(countyValue);
      }
    }

    return options;
  }, [countyOptions]);

  const processedFacilities = useMemo(() => {
    if (!Array.isArray(initialFacilities)) return [];

    const stopWords = new Set(["i", "pa", "for", "med", "av", "og", "de", "den", "det", "bane", "baner"]);

    return initialFacilities
      .map((facility) => {
        const amenities = parseJson<Record<string, unknown>>(facility.amenities, {});
        const golfamoreData = parseJson<Record<string, unknown>>(facility.golfamore_data, {});
        const nsgData = parseJson<Record<string, unknown>>(facility.nsg_data, {});
        const vtgDates = parseJson<unknown[]>(facility.vtg_datoer, []);
        const rawStatuses = parseJson<CourseStatus[]>(facility.course_statuses, []);
        const statuses =
          Array.isArray(rawStatuses) && rawStatuses.length > 0
            ? rawStatuses
            : [{ status: "ukjent", name: "Hovedbane" }];

        const countySlug = slugify(facility.county || "");
        const regions = getFacilityRegions(facility.county || "");
        const holeValue = String(amenities.antall_hull || "").trim();
        const primaryStatus = getPrimaryStatus(statuses);
        const normalizedStatuses = statuses.map((status) => normalizeStatus(status.status));
        const hasGolfamore = facility.golfamore === true || Object.keys(golfamoreData).length > 0;
        const hasNSG = Boolean(facility.nsg_url) || Object.keys(nsgData).length > 0;
        const hasSimulator = hasTruthyAmenity(amenities.simulator);
        const hasDrivingRange = hasTruthyAmenity(amenities.drivingrange);
        const hasVtg =
          Boolean(facility.vtg_pris) ||
          Boolean(facility.vtg_lenke) ||
          Boolean(facility.vtg_beskrivelse) ||
          (Array.isArray(vtgDates) && vtgDates.length > 0);

        const updatedTsRaw = facility.status_updated_at ? new Date(facility.status_updated_at).getTime() : 0;
        const lastUpdatedTs = Number.isFinite(updatedTsRaw) ? updatedTsRaw : 0;
        const distance =
          userLocation && facility.lat && facility.lng
            ? getDistance(userLocation.lat, userLocation.lng, facility.lat, facility.lng)
            : Number.POSITIVE_INFINITY;

        let searchBlob = [
          facility.name,
          facility.city,
          facility.county,
          facility.banetype,
          holeValue,
          ...statuses.map((status) => status.name),
          ...regions,
        ]
          .map((value) => normalizeText(value))
          .join(" ");

        if (hasGolfamore) searchBlob += " golfamore";
        if (hasNSG) searchBlob += " nsg seniorgolf";
        if (hasSimulator) searchBlob += " simulator";
        if (hasDrivingRange) searchBlob += " drivingrange range";
        if (hasVtg) searchBlob += " vtg veien til golf nybegynnerkurs";
        if (normalizedStatuses.includes("aapen")) searchBlob += " apen apne";
        if (normalizedStatuses.includes("stengt")) searchBlob += " stengt";
        if (normalizedStatuses.includes("aapen_med_vintergreener")) searchBlob += " vinter vintergreener";

        const words = normalizeText(searchQuery)
          .split(/\s+/)
          .filter((word) => word && !stopWords.has(word));

        const selectedArea = areaFilter.replace(/^(region:|county:)/, "");
        const matchesSearch = words.every((word) => searchBlob.includes(word));
        const matchesArea =
          !areaFilter ||
          (areaFilter.startsWith("region:") &&
            (regions.includes(selectedArea) ||
              (AREA_GROUPS[selectedArea] ? AREA_GROUPS[selectedArea].includes(countySlug) : false))) ||
          (areaFilter.startsWith("county:") && countySlug === selectedArea);
        const matchesStatus = !statusFilter || normalizedStatuses.includes(statusFilter);
        const matchesHoles = matchesHoleFilter(holeValue, holeFilter);
        const matchesSpecial = matchesSpecialFilter(specialFilter, {
          hasGolfamore,
          hasNSG,
          hasSimulator,
          hasDrivingRange,
          hasVtg,
        });

        return {
          ...facility,
          holeValue,
          primaryStatus,
          hasGolfamore,
          hasNSG,
          hasVtg,
          distance,
          lastUpdatedTs,
          matchesSearch,
          matchesArea,
          matchesStatus,
          matchesHoles,
          matchesSpecial,
        };
      })
      .filter(
        (facility) =>
          facility.matchesSearch &&
          facility.matchesArea &&
          facility.matchesStatus &&
          facility.matchesHoles &&
          facility.matchesSpecial
      )
      .sort((a, b) => {
        if (sortMethod === "dist") {
          if (a.distance !== b.distance) return a.distance - b.distance;
          return a.name.localeCompare(b.name, "nb");
        }
        if (sortMethod === "updated") {
          if (a.lastUpdatedTs !== b.lastUpdatedTs) return b.lastUpdatedTs - a.lastUpdatedTs;
          return a.name.localeCompare(b.name, "nb");
        }
        return a.name.localeCompare(b.name, "nb");
      });
  }, [areaFilter, holeFilter, initialFacilities, searchQuery, sortMethod, specialFilter, statusFilter, userLocation]);

  const filtersCount = [areaFilter, statusFilter, holeFilter, specialFilter, searchQuery.trim()].filter(Boolean).length;
  const summaryText = `${processedFacilities.length} baner • ${getAreaLabel(areaFilter, countyOptions)}${
    filtersCount > 0 ? ` • ${filtersCount} aktive filtre` : ""
  }`;
  const labelClassName = variant === "home" ? "text-white/70" : "text-[#617063]";

  return (
    <section className="mx-auto max-w-[1400px] px-4 py-6 sm:px-6 sm:py-8 lg:px-8 lg:py-10">
      {variant === "catalog" && (
        <div className="mb-8 max-w-4xl">
          <p className="mb-3 text-[11px] font-extrabold uppercase tracking-[0.3em] text-[#6FA786]">{eyebrow}</p>
          <h1 className="section-title text-4xl text-[#112015] sm:text-5xl lg:text-6xl">{title}</h1>
          <p className="mt-4 max-w-3xl text-base leading-8 text-[#617063]">{intro}</p>
        </div>
      )}

      <div className={getSearchShellClasses(variant)}>
        <div className="mb-5">
          <h2 className="section-title text-3xl sm:text-4xl">
            {variant === "home" ? "Søk golfbaner" : "Filtrer oversikten"}
          </h2>
        </div>

        <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
          <FieldSelect label="Område" value={areaFilter} onChange={setAreaFilter} labelClassName={labelClassName}>
            {areaOptions.map((option) => (
              <option key={option.value || "all"} value={option.value}>
                {option.label}
              </option>
            ))}
          </FieldSelect>

          <FieldSelect label="Banestatus" value={statusFilter} onChange={setStatusFilter} labelClassName={labelClassName}>
            <option value="">Alle statuser</option>
            <option value="aapen">Åpne baner</option>
            <option value="aapen_med_vintergreener">Vintergreener</option>
            <option value="stenger_snart">Stenger snart</option>
            <option value="aapner_snart">Åpner snart</option>
            <option value="stengt">Stengt</option>
            <option value="ukjent">Ukjent status</option>
          </FieldSelect>

          <FieldSelect label="Antall hull" value={holeFilter} onChange={setHoleFilter} labelClassName={labelClassName}>
            <option value="">Alle anlegg</option>
            <option value="18-plus">18 hull eller mer</option>
            <option value="18">Nøyaktig 18 hull</option>
            <option value="9">9 hull</option>
            <option value="6-12">6 eller 12 hull</option>
            <option value="under-utvikling">Under utvikling</option>
          </FieldSelect>

          <FieldSelect label="Ekstra" value={specialFilter} onChange={setSpecialFilter} labelClassName={labelClassName}>
            <option value="">Ingen tillegg</option>
            <option value="golfamore">Golfamore</option>
            <option value="nsg">Seniorgolf / NSG</option>
            <option value="simulator">Simulator</option>
            <option value="drivingrange">Drivingrange</option>
            <option value="vtg">Tilbyr VTG</option>
          </FieldSelect>
        </div>

        <div className="mt-3 grid gap-3 lg:grid-cols-[minmax(0,1fr)_220px_auto]">
          <FieldInput
            label="Søk"
            value={searchQuery}
            placeholder='For eksempel "åpne baner i Oslo"'
            onChange={setSearchQuery}
            labelClassName={labelClassName}
          />

          <FieldSelect
            label="Sortering"
            value={sortMethod}
            onChange={(value) => setSortMethod(value as SortMethod)}
            labelClassName={labelClassName}
          >
            <option value="updated">Sist oppdatert</option>
            <option value="alpha">Alfabetisk</option>
            <option value="dist">Nærmest deg</option>
          </FieldSelect>

          <button
            type="button"
            onClick={() => {
              setSearchQuery("");
              setAreaFilter("");
              setStatusFilter("");
              setHoleFilter("");
              setSpecialFilter("");
              setSortMethod(userLocation ? "dist" : "updated");
            }}
            className={`mt-[1.72rem] h-[52px] rounded-2xl px-5 text-[11px] font-extrabold uppercase tracking-[0.2em] transition ${
              variant === "home" ? "bg-[#FF5722] text-white hover:bg-[#C94F2D]" : "bg-[#25312A] text-white hover:bg-[#39443B]"
            }`}
          >
            Nullstill
          </button>
        </div>

        <div
          className={`mt-4 rounded-[1.2rem] px-4 py-3 text-sm font-bold ${
            variant === "home" ? "bg-white/10 text-white/90" : "bg-[#F3F6EE] text-[#617063]"
          }`}
        >
          <span>{summaryText}</span>
          <span className={`ml-2 ${variant === "home" ? "text-white/65" : "text-[#839184]"}`}>
            {sortMethod === "dist" && userLocation
              ? "Sortert etter avstand fra deg."
              : sortMethod === "updated"
                ? "Sortert etter sist oppdatert."
                : "Sortert alfabetisk."}
          </span>
        </div>
      </div>

      {processedFacilities.length === 0 ? (
        <div className="surface-card mt-6 rounded-[2rem] px-6 py-12 text-center">
          <p className="text-lg font-extrabold text-[#112015]">Ingen baner matcher filtrene akkurat nå.</p>
          <p className="mt-2 text-sm text-[#617063]">Prøv å nullstille filtrene eller velg et større område.</p>
        </div>
      ) : (
        <div className="mt-6 grid grid-cols-1 gap-5 md:grid-cols-2 2xl:grid-cols-3">
          {processedFacilities.map((facility) => (
            <article
              key={facility.id}
              className="surface-card group overflow-hidden rounded-[2rem] transition hover:-translate-y-1 hover:shadow-xl"
            >
              <Link href={`/golfbaner/${facility.slug}`} className="block">
              <div className="relative h-56 overflow-hidden bg-[#D9DED5] sm:h-60">
                <Image
                  src={facility.image_url || "/Toppbilde-standard.jpg"}
                  alt={facility.name}
                  fill
                  sizes="(max-width: 768px) 100vw, (max-width: 1536px) 50vw, 33vw"
                  className="object-cover transition duration-700 group-hover:scale-105"
                />
                <div className="absolute inset-0 bg-gradient-to-t from-[#25312A]/65 via-[#25312A]/10 to-transparent" />

                <div className="absolute left-4 top-4 flex max-w-[calc(100%-2rem)] flex-wrap gap-2">
                  <span
                    className={`rounded-full px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.15em] ${
                      STATUS_CLASSES[facility.primaryStatus] || STATUS_CLASSES.ukjent
                    }`}
                  >
                    {getStatusLabel(facility.primaryStatus)}
                  </span>
                  {facility.hasGolfamore && (
                    <span className="rounded-full bg-[#FF5722] px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.15em] text-white">
                      Golfamore
                    </span>
                  )}
                  {facility.hasNSG && (
                    <span className="rounded-full bg-[#2D6CB5] px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.15em] text-white">
                      NSG
                    </span>
                  )}
                </div>

                <div className="absolute bottom-4 left-4 right-4">
                  <p className="text-[10px] font-extrabold uppercase tracking-[0.22em] text-white/75">
                    {facility.city} • {facility.county}
                  </p>
                  <h3 className="mt-2 text-3xl text-white">{facility.name}</h3>
                </div>
              </div>

              </Link>

              <div className="space-y-5 p-5">
                <div className="flex flex-wrap gap-2">
                  <span className="rounded-full bg-[#EEF5E4] px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.15em] text-[#112015]">
                    {facility.holeValue || "--"} hull
                  </span>
                  <span className="rounded-full bg-[#F4F5F1] px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.15em] text-[#617063]">
                    {facility.banetype || "Banetype ukjent"}
                  </span>
                  {facility.hasVtg && (
                    <span className="rounded-full bg-[#FFF0E9] px-3 py-1.5 text-[10px] font-extrabold uppercase tracking-[0.15em] text-[#C94F2D]">
                      VTG
                    </span>
                  )}
                </div>

                {facility.footnote && (
                  <div className="rounded-[1.35rem] border border-[#FFD9CC] bg-[#FFF7F3] px-4 py-3">
                    <p className="text-[10px] font-extrabold uppercase tracking-[0.18em] text-[#9A6A5E]">
                      {formatUpdatedDate(facility.footnote_updated_at || facility.status_updated_at)}
                    </p>
                    <p className="mt-2 text-[15px] italic leading-7 text-[#7B3D2C]" style={noteClampStyle}>
                      {facility.footnote}
                    </p>
                  </div>
                )}

                <div className="grid grid-cols-2 gap-3 rounded-[1.35rem] bg-[#F7F8F3] p-4">
                  <div>
                    <p className="text-[10px] font-extrabold uppercase tracking-[0.18em] text-[#839184]">Oppdatert</p>
                    <p className="mt-1 text-sm font-bold text-[#112015]">{formatUpdatedDate(facility.status_updated_at)}</p>
                  </div>
                  <div>
                    <p className="text-[10px] font-extrabold uppercase tracking-[0.18em] text-[#839184]">Sortering</p>
                    <p className="mt-1 text-sm font-bold text-[#112015]">
                      {sortMethod === "dist" && Number.isFinite(facility.distance)
                        ? `${Math.round(facility.distance)} km unna`
                        : sortMethod === "updated"
                          ? "Nyeste status"
                          : "Alfabetisk"}
                    </p>
                  </div>
                </div>

                <div className={cardActionShellClassName}>
                  {facility.website_url && (
                    <a href={facility.website_url} target="_blank" rel="noreferrer" className={actionIconClassName} aria-label={`Besøk nettsiden til ${facility.name}`}>
                      <ActionIcon type="web" />
                    </a>
                  )}
                  {facility.golfbox_booking_url && (
                    <a href={facility.golfbox_booking_url} target="_blank" rel="noreferrer" className={actionIconClassName} aria-label={`Book starttid hos ${facility.name}`}>
                      <ActionIcon type="booking" />
                    </a>
                  )}
                  {facility.golfbox_tournament_url && (
                    <a href={facility.golfbox_tournament_url} target="_blank" rel="noreferrer" className={actionIconClassName} aria-label={`Se turneringer hos ${facility.name}`}>
                      <ActionIcon type="trophy" />
                    </a>
                  )}
                  {buildMapUrl(facility.lat, facility.lng) && (
                    <a href={buildMapUrl(facility.lat, facility.lng) || "#"} target="_blank" rel="noreferrer" className={actionIconClassName} aria-label={`Åpne kart for ${facility.name}`}>
                      <ActionIcon type="pin" />
                    </a>
                  )}
                  {facility.weather_url && (
                    <a href={facility.weather_url} target="_blank" rel="noreferrer" className={actionIconClassName} aria-label={`Se været for ${facility.name}`}>
                      <ActionIcon type="weather" />
                    </a>
                  )}
                </div>

                <div className="flex items-center justify-between gap-3 text-sm font-bold text-[#112015]">
                  <span className="truncate text-[#617063]">{facility.phone ? facility.phone : facility.city || "Se detaljer"}</span>
                  <Link href={`/golfbaner/${facility.slug}`} className="shrink-0 text-[#FF5722] transition hover:text-[#C94F2D]">
                    Se anlegg →
                  </Link>
                </div>
              </div>
            </article>
          ))}
        </div>
      )}
    </section>
  );
}

function ActionIcon({ type }: { type: "web" | "booking" | "trophy" | "pin" | "weather" }) {
  return (
    <svg
      className="h-5 w-5"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="2"
      strokeLinecap="round"
      strokeLinejoin="round"
      aria-hidden="true"
    >
      {type === "web" && (
        <>
          <circle cx="12" cy="12" r="10" />
          <line x1="2" y1="12" x2="22" y2="12" />
          <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" />
        </>
      )}
      {type === "booking" && (
        <>
          <path d="M3 10h18" />
          <path d="M7 15h.01" />
          <path d="M11 15h.01" />
          <path d="M15 15h.01" />
          <path d="M7 19h.01" />
          <path d="M11 19h.01" />
          <path d="M15 19h.01" />
          <path d="M17 21H7a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2z" />
          <path d="M16 3v4" />
          <path d="M8 3v4" />
        </>
      )}
      {type === "trophy" && (
        <>
          <path d="M6 9H4.5a2.5 2.5 0 0 1 0-5H6" />
          <path d="M18 9h1.5a2.5 2.5 0 0 0 0-5H18" />
          <path d="M4 22h16" />
          <path d="M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20.24 7 22" />
          <path d="M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20.24 17 22" />
          <path d="M18 2H6v7a6 6 0 0 0 12 0V2z" />
        </>
      )}
      {type === "pin" && (
        <>
          <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" />
          <circle cx="12" cy="10" r="3" />
        </>
      )}
      {type === "weather" && (
        <>
          <path d="M12 2v2" />
          <path d="m4.93 4.93 1.41 1.41" />
          <path d="M20 12h2" />
          <path d="m19.07 4.93-1.41 1.41" />
          <path d="M15.947 12.65a4 4 0 0 0-5.925-4.128" />
          <path d="M13 22H7a5 5 0 1 1 4.9-6H13a3 3 0 0 1 0 6Z" />
        </>
      )}
    </svg>
  );
}

function FieldSelect({
  label,
  value,
  onChange,
  labelClassName,
  children,
}: {
  label: string;
  value: string;
  onChange: (value: string) => void;
  labelClassName: string;
  children: React.ReactNode;
}) {
  return (
    <label className="block">
      <span className={`mb-2 block text-[10px] font-extrabold uppercase tracking-[0.22em] ${labelClassName}`}>{label}</span>
      <select value={value} onChange={(event) => onChange(event.target.value)} className="filter-field w-full px-4 py-3">
        {children}
      </select>
    </label>
  );
}

function FieldInput({
  label,
  value,
  placeholder,
  onChange,
  labelClassName,
}: {
  label: string;
  value: string;
  placeholder: string;
  onChange: (value: string) => void;
  labelClassName: string;
}) {
  return (
    <label className="block">
      <span className={`mb-2 block text-[10px] font-extrabold uppercase tracking-[0.22em] ${labelClassName}`}>{label}</span>
      <input
        value={value}
        placeholder={placeholder}
        onChange={(event) => onChange(event.target.value)}
        className="filter-field w-full px-4 py-3"
      />
    </label>
  );
}
