/**
 * Trouve-KA — contenu client de la page de résultats
 * Author: Simon-Pierre Boucher
 * Contact: contact@spboucher.ai
 */

"use client";

import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { useEffect, useState } from "react";
import { FilterPills, type SearchFilters } from "@/components/filter-pills";
import { GallerySkeleton, ImageGallery } from "@/components/image-gallery";
import { ResultItem } from "@/components/result-item";
import { SearchBar } from "@/components/search-bar";
import { Button } from "@/components/ui/button";
import { formatNumber } from "@/lib/format";
import type { SearchResponse } from "@/lib/types";

const PAGE_SIZE = 10;
const GALLERY_PAGE_SIZE = 24;

function buildSearchUrl(
  q: string,
  page: number,
  filters: SearchFilters,
): string {
  const params = new URLSearchParams({ q });
  if (page > 1) params.set("page", String(page));
  if (filters.category) params.set("category", filters.category);
  if (filters.language) params.set("language", filters.language);
  if (filters.quebecOnly) params.set("quebec_only", "true");
  if (filters.images) params.set("images", "true");
  return `/search?${params.toString()}`;
}

function ResultsSkeleton() {
  return (
    <div aria-hidden="true" className="divide-y divide-line">
      {Array.from({ length: 5 }, (_, i) => (
        <div
          key={i}
          className="flex animate-pulse items-start gap-4 py-6 sm:gap-6"
        >
          <div className="min-w-0 flex-1 space-y-2.5">
            <div className="h-3.5 w-1/3 rounded bg-[rgba(20,24,20,0.07)]" />
            <div className="h-5 w-2/3 rounded bg-line" />
            <div className="h-3.5 w-full rounded bg-[rgba(20,24,20,0.07)]" />
            <div className="h-3.5 w-5/6 rounded bg-[rgba(20,24,20,0.07)]" />
            <div className="flex gap-2 pt-0.5">
              <div className="h-[22px] w-[72px] rounded-[5px] bg-[rgba(20,24,20,0.07)]" />
              <div className="h-[22px] w-24 rounded-[5px] bg-[rgba(20,24,20,0.07)]" />
            </div>
          </div>
          {i % 2 === 0 ? (
            <div className="h-[76px] w-[76px] shrink-0 rounded-card bg-[rgba(20,24,20,0.07)] sm:h-[110px] sm:w-[110px]" />
          ) : null}
        </div>
      ))}
    </div>
  );
}

export function SearchContent() {
  const router = useRouter();
  const searchParams = useSearchParams();

  const q = searchParams.get("q")?.trim() ?? "";
  const page = Math.max(1, Number.parseInt(searchParams.get("page") ?? "1", 10) || 1);
  const filters: SearchFilters = {
    category: searchParams.get("category") ?? undefined,
    language: searchParams.get("language") ?? undefined,
    quebecOnly: searchParams.get("quebec_only") === "true",
    images: searchParams.get("images") === "true",
  };
  const imagesMode = Boolean(filters.images);

  const [data, setData] = useState<SearchResponse | null>(null);
  const [loading, setLoading] = useState(Boolean(q));
  const [error, setError] = useState(false);

  useEffect(() => {
    if (!q) {
      setData(null);
      setLoading(false);
      return;
    }

    const controller = new AbortController();
    setLoading(true);
    setError(false);

    const gallery = searchParams.get("images") === "true";
    const params = new URLSearchParams({
      q,
      page: String(page),
      limit: String(gallery ? GALLERY_PAGE_SIZE : PAGE_SIZE),
    });
    const category = searchParams.get("category");
    const language = searchParams.get("language");
    if (category) params.set("category", category);
    if (language) params.set("language", language);
    if (searchParams.get("quebec_only") === "true") {
      params.set("quebec_only", "true");
    }
    if (gallery) params.set("images", "true");

    fetch(`/api/search?${params.toString()}`, { signal: controller.signal })
      .then((res) => {
        if (!res.ok) throw new Error(`Erreur ${res.status}`);
        return res.json() as Promise<SearchResponse>;
      })
      .then((json) => {
        setData(json);
        setLoading(false);
      })
      .catch((err: unknown) => {
        if (err instanceof DOMException && err.name === "AbortError") return;
        setError(true);
        setLoading(false);
      });

    return () => controller.abort();
  }, [q, page, searchParams]);

  function navigate(nextPage: number, nextFilters: SearchFilters) {
    router.push(buildSearchUrl(q, nextPage, nextFilters));
    window.scrollTo({ top: 0 });
  }

  const totalPages = data ? Math.max(1, Math.ceil(data.total / data.limit)) : 1;
  const hasPrevious = page > 1;
  const hasNext = data ? page < totalPages : false;

  return (
    <div className="flex-1">
      {/* Barre persistante sous l'en-tête global (h-14) : recherche + filtres. */}
      <div className="sticky top-14 z-30 border-b border-line bg-paper md:bg-[rgba(245,243,238,0.92)] md:backdrop-blur">
        <div className="mx-auto max-w-3xl px-4 pt-3">
          <SearchBar key={q} initialQuery={q} className="max-w-xl" />
          <div className="overflow-x-auto py-3">
            <FilterPills
              filters={filters}
              onChange={(next) => navigate(1, next)}
            />
          </div>
        </div>
      </div>

      <main id="contenu" className="mx-auto max-w-3xl px-4 py-6">
        {!q ? (
          <p className="py-12 text-center text-ink-2">
            Entrez une requête pour chercher le web québécois.
          </p>
        ) : loading ? (
          imagesMode ? <GallerySkeleton /> : <ResultsSkeleton />
        ) : error ? (
          <div className="py-12 text-center">
            <p className="font-display font-bold text-ink">
              Le moteur est momentanément injoignable.
            </p>
            <p className="mt-2 text-sm text-ink-2">
              Réessayez dans quelques instants ou consultez l'
              <Link
                href="/status"
                className="font-medium text-green underline-offset-2 hover:underline"
              >
                état du moteur
              </Link>
              .
            </p>
          </div>
        ) : data && data.results.length === 0 ? (
          <div className="rise py-14 text-center">
            <p className="klabel">0 résultat</p>
            <h2 className="mx-auto mt-4 max-w-xl text-3xl font-bold leading-tight tracking-[-0.03em] [overflow-wrap:anywhere] sm:text-4xl">
              Rien pour <span className="hl">«&nbsp;{q}&nbsp;»</span> — encore.
            </h2>
            <p className="mx-auto mt-5 max-w-md text-sm leading-relaxed text-ink-2">
              Vérifiez l'orthographe, essayez des termes plus généraux ou
              retirez un filtre. Le robot crawle le Québec en continu&nbsp;: ce
              qui manque aujourd'hui peut apparaître demain.
            </p>
            <Link href="/soumettre" className="btn btn-primary mt-8">
              Soumettre un site québécois
            </Link>
          </div>
        ) : data ? (
          <>
            <p aria-live="polite" className="klabel">
              <span className="mr-1 rounded-[4px] bg-lime px-1.5 py-0.5 text-[11px] text-ink">
                {formatNumber(data.total)}
              </span>{" "}
              {data.total === 1 ? "résultat" : "résultats"} (
              {formatNumber(data.took_ms)}&nbsp;ms)
            </p>
            {imagesMode ? (
              <div className="mt-4">
                <ImageGallery results={data.results} />
              </div>
            ) : (
              <div className="mt-2 divide-y divide-line">
                {data.results.map((result) => (
                  <ResultItem key={result.url} result={result} />
                ))}
              </div>
            )}
            {hasPrevious || hasNext ? (
              <nav
                aria-label="Pagination des résultats"
                className="mt-8 flex items-center justify-between border-t border-line pt-5"
              >
                <Button
                  variant="ghost"
                  size="sm"
                  disabled={!hasPrevious}
                  onClick={() => navigate(page - 1, filters)}
                >
                  ← Précédent
                </Button>
                <span className="gk-mono text-xs font-medium text-ink-2">
                  Page {formatNumber(page)} de {formatNumber(totalPages)}
                </span>
                <Button
                  variant="ghost"
                  size="sm"
                  disabled={!hasNext}
                  onClick={() => navigate(page + 1, filters)}
                >
                  Suivant →
                </Button>
              </nav>
            ) : null}
          </>
        ) : null}
      </main>
    </div>
  );
}
