import { Link, useNavigate } from "@tanstack/react-router";
import { useQuery } from "@tanstack/react-query";
import { useServerFn } from "@tanstack/react-start";
import { useCallback, useEffect, useRef, useState, type FormEvent, type ReactNode } from "react";
import { playShellUrl } from "@/lib/embed/ad-guard";
import { AdSlot } from "@/components/ad-slot";
import { GamePlayer } from "@/components/game-player";
import { useSite } from "@/components/site-context";
import {
  getCategoryBySlug,
  getGameBySlug,
  getGamesBySlugs,
  getHomePageData,
  listCategories,
  listGames,
} from "@/lib/games.functions";
import { HISTORY_KEY, MY_KEY, isInMy, pushHistory, readSlugs, toggleMy } from "@/lib/local-games";

type Game = {
  id: string;
  slug: string;
  title: string;
  description?: string | null;
  instructions?: string | null;
  thumb_url: string;
  embed_url?: string;
  is_featured?: boolean;
  categories?: { slug: string; name: string } | null;
};

type CategoryData = {
  category: { id: string; slug: string; name: string };
  games: Game[];
  total: number;
  hasMore: boolean;
};

const WELCOME =
  "Добро пожаловать на наш игровой портал! Здесь собраны лучшие HTML5-игры рунета: шутеры и бродилки, квесты и стратегии, симуляторы и аркады, головоломки и гонки. Выбирай категорию, запускай игру в браузере — без скачивания и регистрации!";

function useLocalSlugs(key: string) {
  const [slugs, setSlugs] = useState<string[]>([]);
  useEffect(() => {
    const sync = () => setSlugs(readSlugs(key));
    sync();
    window.addEventListener("local-games-changed", sync);
    return () => window.removeEventListener("local-games-changed", sync);
  }, [key]);
  return slugs;
}

function Thumb58({ g, categorySlug }: { g: Game; categorySlug: string }) {
  return (
    <Link
      to="/category/$slug"
      params={{ slug: categorySlug }}
      title={g.title}
      className="block shrink-0"
    >
      <img
        src={g.thumb_url}
        alt={g.title}
        width={58}
        height={58}
        loading="lazy"
        className="w-[58px] h-[58px] object-cover rounded-sm border border-border-soft hover:border-accent/60"
      />
    </Link>
  );
}

function Thumb({ g, size = "sm" }: { g: Game; size?: "sm" | "md" }) {
  const box = size === "md" ? "aspect-[4/3] rounded-lg" : "aspect-square rounded-md";
  return (
    <Link to="/game/$slug" params={{ slug: g.slug }} title={g.title} className="group block">
      <div className={`w-full ${box} overflow-hidden bg-surface border border-border-soft group-hover:border-accent/50`}>
        <img src={g.thumb_url} alt={g.title} loading="lazy" className="w-full h-full object-cover group-hover:scale-105 transition-transform" />
      </div>
      {size === "md" && <p className="text-[10px] sm:text-xs text-text-dim mt-1 line-clamp-2">{g.title}</p>}
    </Link>
  );
}

function Section({
  title,
  icon,
  categorySlug,
  children,
}: {
  title: string;
  icon?: string;
  categorySlug?: string;
  children: ReactNode;
}) {
  const heading = categorySlug ? (
    <Link
      to="/category/$slug"
      params={{ slug: categorySlug }}
      className="flex items-center gap-2 text-sm font-display text-text mb-2 border-b border-border-soft pb-1.5 hover:text-accent"
    >
      {icon && <span>{icon}</span>}
      {title}
    </Link>
  ) : (
    <h2 className="flex items-center gap-2 text-sm font-display text-text mb-2 border-b border-border-soft pb-1.5">
      {icon && <span>{icon}</span>}
      {title}
    </h2>
  );

  return (
    <section className="mb-5">
      {heading}
      {children}
    </section>
  );
}

function WelcomePanel() {
  const site = useSite();
  return (
    <div className="flex gap-3 sm:gap-4 p-4 sm:p-5 bg-gradient-to-br from-surface to-bg min-h-[200px]">
      <div className="shrink-0 w-16 h-16 sm:w-20 sm:h-20 rounded-2xl bg-accent/15 border border-accent/30 flex items-center justify-center font-display text-lg sm:text-xl text-text leading-tight text-center">
        {site.logo_primary}
        <span className="text-accent">{site.logo_accent}</span>
      </div>
      <div className="min-w-0">
        <h1 className="text-base sm:text-lg font-display text-accent mb-2">Игры онлайн бесплатно</h1>
        <p className="text-[11px] sm:text-sm text-text-dim leading-relaxed">{WELCOME}</p>
      </div>
    </div>
  );
}

function CategoryPanel({ name, total }: { name: string; total: number }) {
  return (
    <div className="px-4 py-3 border-b border-border-soft flex items-center justify-between bg-surface">
      <h1 className="text-base sm:text-lg font-display text-accent">{name}</h1>
      <span className="text-[10px] font-bold uppercase tracking-widest text-text-muted">{total} игр</span>
    </div>
  );
}

function gameAspectStyle(width?: number, height?: number) {
  const w = width && width > 0 ? width : 16;
  const h = height && height > 0 ? height : 9;
  return { aspectRatio: `${w} / ${h}` } as const;
}

function GamePanel({
  game,
}: {
  game: Game & {
    embed_url: string;
    width?: number;
    height?: number;
    description?: string | null;
    instructions?: string | null;
  };
}) {
  const [playing, setPlaying] = useState(false);
  const [saved, setSaved] = useState(false);
  const playerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    pushHistory(game.slug);
    setSaved(isInMy(game.slug));
  }, [game.slug]);

  const toggleSave = useCallback(() => {
    setSaved(toggleMy(game.slug));
  }, [game.slug]);

  const share = useCallback(async () => {
    const url = `${window.location.origin}/game/${game.slug}`;
    if (navigator.share) {
      await navigator.share({ title: game.title, url });
    } else {
      await navigator.clipboard.writeText(url);
      alert("Ссылка скопирована");
    }
  }, [game.slug, game.title]);

  return (
    <div className="bg-surface border border-border-soft rounded-xl overflow-hidden shadow-sm">
      <div className="p-3 sm:p-4 space-y-3">
        <div className="flex gap-3 items-start">
          <img
            src={game.thumb_url}
            alt={game.title}
            width={64}
            height={64}
            className="w-16 h-16 shrink-0 object-cover rounded-lg border border-border-soft"
          />
          <div className="min-w-0">
            <h2 className="text-base sm:text-lg font-display text-text leading-tight">{game.title}</h2>
            {game.description && (
              <p className="text-[11px] text-text-dim mt-1 line-clamp-4 leading-relaxed">{game.description}</p>
            )}
          </div>
        </div>
        {game.instructions && (
          <div className="rounded-lg bg-bg border border-border-soft p-3">
            <h3 className="text-[10px] font-bold uppercase tracking-wider text-accent mb-1">Управление</h3>
            <p className="text-[11px] text-text-dim leading-relaxed whitespace-pre-line">{game.instructions}</p>
          </div>
        )}
        <div
          ref={playerRef}
          className="relative w-full bg-black rounded-lg overflow-hidden"
          style={gameAspectStyle(game.width, game.height)}
        >
          {playing ? (
            <GamePlayer
              embedUrl={game.embed_url}
              title={game.title}
              onFullscreen={() => {
                const el = playerRef.current;
                if (el?.requestFullscreen) {
                  void el.requestFullscreen();
                  return;
                }
                window.open(playShellUrl(game.embed_url), "_blank", "noopener,noreferrer");
              }}
            />
          ) : (
            <button
              type="button"
              onClick={() => setPlaying(true)}
              className="absolute inset-0 grid place-items-center bg-black/50 text-white font-bold uppercase text-sm hover:bg-black/30"
            >
              ▶ Играть
            </button>
          )}
        </div>
        <div className="flex flex-wrap gap-2 pt-1">
          <button
            type="button"
            onClick={toggleSave}
            className={`px-4 py-2 rounded-lg text-xs font-bold uppercase ${saved ? "bg-neon/15 text-neon" : "bg-accent text-white"}`}
          >
            {saved ? "★ В моих играх" : "+ В мои игры"}
          </button>
          <button type="button" onClick={share} className="px-4 py-2 rounded-lg bg-surface-elevated text-xs font-bold uppercase text-text">
            Поделиться
          </button>
        </div>
      </div>
    </div>
  );
}

function ListPanel({ title, games, empty }: { title: string; games: Game[]; empty: string }) {
  return (
    <div className="rounded-xl border border-border-soft overflow-hidden bg-surface shadow-sm">
      <div className="px-4 py-3 border-b border-border-soft flex items-center justify-between">
        <h1 className="text-base font-display text-accent">{title}</h1>
        <span className="text-[10px] font-bold uppercase tracking-widest text-text-muted">{games.length} игр</span>
      </div>
      {games.length === 0 ? (
        <p className="p-8 text-center text-sm text-text-dim">{empty}</p>
      ) : (
        <div className="p-3 grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 gap-2">
          {games.map((g) => (
            <Thumb key={g.id} g={g} size="md" />
          ))}
        </div>
      )}
    </div>
  );
}

export function PortalPage({
  activeSlug,
  activeCategorySlug,
  searchQuery,
  listPanel,
}: {
  activeSlug?: string;
  activeCategorySlug?: string;
  searchQuery?: string;
  listPanel?: "my" | "history";
}) {
  const site = useSite();
  const navigate = useNavigate();
  const fetchHome = useServerFn(getHomePageData);
  const fetchGame = useServerFn(getGameBySlug);
  const fetchCategory = useServerFn(getCategoryBySlug);
  const fetchCats = useServerFn(listCategories);
  const fetchSearch = useServerFn(listGames);
  const fetchBySlugs = useServerFn(getGamesBySlugs);
  const [bestMore, setBestMore] = useState(25);
  const [catMore, setCatMore] = useState(80);
  const [searchMore, setSearchMore] = useState(48);
  const [searchInput, setSearchInput] = useState(searchQuery ?? "");

  const mySlugs = useLocalSlugs(MY_KEY);
  const historySlugs = useLocalSlugs(HISTORY_KEY);
  const listSlugs = listPanel === "my" ? mySlugs : listPanel === "history" ? historySlugs : [];

  useEffect(() => setSearchInput(searchQuery ?? ""), [searchQuery]);
  useEffect(() => setCatMore(80), [activeCategorySlug]);
  useEffect(() => setSearchMore(48), [searchQuery]);

  const { data: home } = useQuery({
    queryKey: ["home-data"],
    queryFn: () => fetchHome(),
    staleTime: 60_000,
  });
  const { data: cats = [] } = useQuery({ queryKey: ["categories"], queryFn: () => fetchCats() });
  const { data: active } = useQuery({
    queryKey: ["game", activeSlug],
    queryFn: () => fetchGame({ data: { slug: activeSlug! } }),
    enabled: !!activeSlug,
  });
  const { data: catData, isLoading: catLoading } = useQuery<CategoryData>({
    queryKey: ["category", activeCategorySlug, catMore],
    queryFn: async () => {
      const r = await fetchCategory({ data: { slug: activeCategorySlug!, limit: catMore } });
      if (!r) throw new Error("Категория не найдена");
      return r;
    },
    enabled: !!activeCategorySlug && !activeSlug,
  });
  const { data: searchData } = useQuery({
    queryKey: ["search", searchQuery, searchMore],
    queryFn: () => fetchSearch({ data: { q: searchQuery!, limit: searchMore } }),
    enabled: !!searchQuery && !activeSlug && !listPanel && !activeCategorySlug,
  });
  const { data: listGamesData } = useQuery({
    queryKey: ["list-panel", listPanel, listSlugs],
    queryFn: () => fetchBySlugs({ data: { slugs: listSlugs } }),
    enabled: !!listPanel && listSlugs.length > 0,
  });

  const onSearch = (e: FormEvent) => {
    e.preventDefault();
    const q = searchInput.trim();
    if (q) navigate({ to: "/search", search: { q } });
    else navigate({ to: "/" });
  };

  const gameOpen = !!(activeSlug && active?.game);
  const categoryOpen = !!(activeCategorySlug && !gameOpen && !searchQuery && !listPanel);
  const searchOpen = !!(searchQuery && !gameOpen && !listPanel && !activeCategorySlug);
  const listOpen = !!listPanel && !gameOpen;
  const best = home?.best.slice(0, bestMore) ?? [];
  const catGames = (catData?.games ?? []) as Game[];
  const searchGames = (searchData?.items ?? []) as Game[];
  const panelGames = (listGamesData ?? []) as Game[];

  return (
    <div className="min-h-screen bg-bg text-text">
      <header className="sticky top-0 z-50 bg-surface border-b border-border-soft shadow-sm">
        <div className="max-w-[1400px] mx-auto px-2 sm:px-4 py-2 flex items-center gap-2 sm:gap-3">
          <Link to="/" className="font-display text-lg sm:text-xl text-text shrink-0">
            {site.logo_primary}
            <span className="text-accent">{site.logo_accent}</span>
          </Link>
          <form onSubmit={onSearch} className="flex-1 max-w-md mx-auto hidden sm:block">
            <input
              value={searchInput}
              onChange={(e) => setSearchInput(e.target.value)}
              placeholder="Поиск игр..."
              className="w-full px-4 py-2 rounded-full bg-bg border border-border-soft text-sm text-text placeholder:text-text-muted focus:border-accent outline-none"
            />
          </form>
          <div className="ml-auto flex items-center gap-1.5 shrink-0">
            <Link
              to="/my"
              className={`px-2.5 py-1.5 rounded-lg text-[10px] font-bold uppercase whitespace-nowrap ${listPanel === "my" ? "bg-accent text-white" : "bg-bg border border-border-soft text-text"}`}
            >
              ★ Мои
            </Link>
            <Link
              to="/history"
              className={`px-2.5 py-1.5 rounded-lg text-[10px] font-bold uppercase whitespace-nowrap ${listPanel === "history" ? "bg-accent text-white" : "bg-bg border border-border-soft text-text"}`}
            >
              История
            </Link>
            <span className="hidden md:inline text-xs font-bold text-accent pl-1">{home?.total ?? site.gameCount}</span>
          </div>
        </div>
        <form onSubmit={onSearch} className="sm:hidden max-w-[1400px] mx-auto px-2 pb-2">
          <input
            value={searchInput}
            onChange={(e) => setSearchInput(e.target.value)}
            placeholder="Поиск игр..."
            className="w-full px-4 py-2 rounded-full bg-bg border border-border-soft text-sm text-text placeholder:text-text-muted focus:border-accent outline-none"
          />
        </form>
        <div className="max-w-[1400px] mx-auto px-2 sm:px-4 pb-2 flex gap-1.5 overflow-x-auto no-scrollbar">
          <Link
            to="/"
            className={`px-3 py-1 rounded-full text-[10px] font-bold uppercase whitespace-nowrap ${!activeCategorySlug && !gameOpen && !searchOpen && !listOpen ? "bg-accent text-white" : "bg-bg border border-border-soft text-text"}`}
          >
            Все
          </Link>
          {cats.map((c) => (
            <Link
              key={c.id}
              to="/category/$slug"
              params={{ slug: c.slug }}
              className={`px-3 py-1 rounded-full text-[10px] font-bold uppercase whitespace-nowrap ${activeCategorySlug === c.slug ? "bg-accent text-white" : "bg-bg border border-border-soft text-text"}`}
            >
              {c.name}
            </Link>
          ))}
        </div>
      </header>

      <div className="max-w-[1400px] mx-auto px-2 sm:px-4 py-4">
        {home && (
          <div className="flex flex-wrap lg:flex-nowrap items-start gap-2 xl:gap-3 mb-4 p-2 rounded-xl border border-border-soft bg-surface max-w-full overflow-x-auto shadow-sm">
            <div className="shrink-0">
              <Link to="/category/$slug" params={{ slug: "girls" }} className="text-xs font-display text-text mb-1 flex items-center gap-1 hover:text-accent">
                <span>👧</span> Для девочек
              </Link>
              <div className="grid grid-cols-4 sm:grid-cols-6 lg:grid-cols-[repeat(8,58px)] auto-rows-[58px] gap-1">
                {home.girls.slice(0, 32).map((g) => (
                  <Thumb58 key={g.id} g={g} categorySlug="girls" />
                ))}
              </div>
            </div>
            <div className="shrink-0">
              <Link to="/category/$slug" params={{ slug: "action" }} className="text-xs font-display text-text mb-1 flex items-center gap-1 hover:text-accent">
                <span>👦</span> Для мальчиков
              </Link>
              <div className="grid grid-cols-4 sm:grid-cols-5 lg:grid-cols-[repeat(7,58px)] auto-rows-[58px] gap-1">
                {home.boys.slice(0, 28).map((g) => (
                  <Thumb58 key={g.id} g={g} categorySlug={g.categories?.slug ?? "action"} />
                ))}
              </div>
            </div>
            <AdSlot
              id="top-square"
              className="w-[330px] h-[244px] shrink-0 self-start mt-[22px] max-w-[min(330px,100%)]"
              label="Реклама"
            />
          </div>
        )}

        <div className="grid lg:grid-cols-[auto_minmax(0,1fr)] gap-2 lg:gap-3 mb-5">
          <aside className="w-full lg:w-max lg:max-w-[378px] shrink-0 space-y-3 order-2 lg:order-none">
            {home?.sideCategories.map((block) => (
              <Section key={block.slug} title={block.name} categorySlug={block.slug}>
                <div className="grid grid-cols-[repeat(6,58px)] gap-1">
                  {block.games.map((g) => (
                    <Thumb58 key={g.id} g={g} categorySlug={block.slug} />
                  ))}
                </div>
              </Section>
            ))}
          </aside>

          <div className="min-w-0 order-1 lg:order-none space-y-3">
            {gameOpen && active?.game ? (
              <>
                <GamePanel game={active.game as Game & { embed_url: string }} />
                <div className="grid grid-cols-3 gap-2">
                  <AdSlot id="g-ad-1" className="aspect-square min-h-[110px] sm:min-h-[130px]" label="Реклама" />
                  <AdSlot id="g-ad-2" className="aspect-square min-h-[110px] sm:min-h-[130px]" label="Реклама" />
                  <AdSlot id="g-ad-3" className="aspect-square min-h-[110px] sm:min-h-[130px]" label="Реклама" />
                </div>
                {active.related && active.related.length > 0 && (
                  <section>
                    <h3 className="text-xs font-display text-text mb-2 border-b border-border-soft pb-1">Похожие игры</h3>
                    <div className="grid grid-cols-[repeat(6,58px)] sm:grid-cols-[repeat(8,58px)] md:grid-cols-[repeat(10,58px)] gap-1">
                      {active.related.map((g) => (
                        <Link key={g.id} to="/game/$slug" params={{ slug: g.slug }} title={g.title} className="block shrink-0">
                          <img src={g.thumb_url} alt={g.title} width={58} height={58} loading="lazy" className="w-[58px] h-[58px] object-cover rounded-sm border border-border-soft hover:border-accent/60" />
                        </Link>
                      ))}
                    </div>
                  </section>
                )}
              </>
            ) : categoryOpen ? (
              <div className="rounded-xl border border-border-soft overflow-hidden bg-surface shadow-sm">
                {catData ? (
                  <>
                    <CategoryPanel name={catData.category.name as string} total={catData.total} />
                    {catGames.length > 0 ? (
                      <div className="p-3">
                        <div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 gap-2">
                          {catGames.map((g) => (
                            <Thumb key={g.id} g={g} size="md" />
                          ))}
                        </div>
                        {catData.hasMore && (
                          <button
                            type="button"
                            onClick={() => setCatMore((n) => n + 40)}
                            className="mt-4 px-8 py-3 bg-accent text-white font-bold uppercase text-xs rounded-xl"
                          >
                            Загрузить ещё
                          </button>
                        )}
                      </div>
                    ) : (
                      <p className="p-8 text-center text-sm text-text-dim">В этой категории пока нет игр</p>
                    )}
                  </>
                ) : catLoading ? (
                  <div className="p-5 min-h-[120px] animate-pulse bg-surface" />
                ) : (
                  <p className="p-8 text-center text-sm text-text-dim">Категория не найдена</p>
                )}
              </div>
            ) : searchOpen ? (
              <div className="rounded-xl border border-border-soft overflow-hidden bg-surface shadow-sm">
                <div className="px-4 py-3 border-b border-border-soft flex items-center justify-between">
                  <h1 className="text-base font-display text-accent">Поиск: {searchQuery}</h1>
                  <span className="text-[10px] font-bold uppercase tracking-widest text-text-muted">
                    {searchData?.total ?? 0} игр
                  </span>
                </div>
                {searchGames.length > 0 ? (
                  <div className="p-3">
                    <div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 gap-2">
                      {searchGames.map((g) => (
                        <Thumb key={g.id} g={g} size="md" />
                      ))}
                    </div>
                    {searchData?.hasMore && (
                      <button
                        type="button"
                        onClick={() => setSearchMore((n) => n + 48)}
                        className="mt-4 px-8 py-3 bg-accent text-white font-bold uppercase text-xs rounded-xl"
                      >
                        Загрузить ещё
                      </button>
                    )}
                  </div>
                ) : (
                  <p className="p-8 text-center text-sm text-text-dim">Ничего не найдено</p>
                )}
              </div>
            ) : listOpen ? (
              <ListPanel
                title={listPanel === "my" ? "Мои игры" : "История"}
                games={panelGames}
                empty={listPanel === "my" ? "Добавляйте игры кнопкой «В мои игры»" : "Здесь появятся недавно открытые игры"}
              />
            ) : (
              <>
                <div className="rounded-xl border border-border-soft overflow-hidden shadow-sm">
                  <WelcomePanel />
                </div>
                {home && (
                  <Section title="Каталог">
                    <div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-5 xl:grid-cols-6 gap-2">
                      {home.catalog.map((g) => (
                        <Thumb key={g.id} g={g} size="md" />
                      ))}
                    </div>
                  </Section>
                )}
              </>
            )}
          </div>
        </div>

        {!gameOpen && home && (
          <Section title="Лучшие игры" icon="⭐">
            <div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 gap-2">
              {best.map((g) => (
                <Thumb key={g.id} g={g} size="md" />
              ))}
            </div>
            {bestMore < home.best.length && (
              <button
                type="button"
                onClick={() => setBestMore((n) => n + 25)}
                className="mt-4 px-8 py-3 bg-accent text-white font-bold uppercase text-xs rounded-xl"
              >
                Загрузить ещё
              </button>
            )}
          </Section>
        )}
      </div>

      <footer className="border-t border-border-soft bg-surface py-5 text-center text-xs text-text-muted">
        © {new Date().getFullYear()} {site.name}
      </footer>
    </div>
  );
}
