"use client";

import { useTranslation } from "@/hooks/useTranslation";
import { GenreModel, PostModel, TagModel } from "@/models";
import { DefaultGenre } from "@/models/genre";
import { toCapitalize } from "@/utils/text";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useEffect, useMemo, useState } from "react";
import { Search, SlidersHorizontal, X } from "lucide-react";

import Loader from "../ui/Loader";
import Genres from "./components/Genres";
import NovelList from "./components/NovelList";
import SortOption from "./components/SortOption";
import PaginationGenre from "../ui/PaginationGenre";

interface NovelState {
  novels: PostModel[];
  genres: GenreModel[];
  tags: TagModel[];
  totalPages: number;
}

export default function NovelPage({ novels, genres, tags, totalPages }: NovelState) {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();

  const { t } = useTranslation();

  const urlGenre = searchParams.get("genre") || "";
  const urlTag = searchParams.get("tag") || "";
  const urlSort = searchParams.get("sort") || "all";
  const urlPage = Number(searchParams.get("page") || 1);

  const [selectedGenre, setSelectedGenre] = useState<GenreModel>(DefaultGenre);
  const [tempGenre, setTempGenre] = useState<GenreModel>(DefaultGenre);
  const [selectedTag, setSelectedTag] = useState<TagModel | null>(null);
  const [tempTag, setTempTag] = useState<TagModel | null>(null);
  const [tagSearch, setTagSearch] = useState("");
  const [sortBy, setSortBy] = useState(urlSort);
  const [showAllGenres, setShowAllGenres] = useState(false);
  const [isFilterSheetOpen, setFilterSheetOpen] = useState(false);
  const [loadingMore, setLoadingMore] = useState(false);
  const [novelList, setNovelList] = useState<PostModel[]>(novels);
  const [currentPage, setCurrentPage] = useState(urlPage);
  const [hasMore, setHasMore] = useState(true);

  useEffect(() => {
    const found = genres.find((g) => g.id === urlGenre);
    setSelectedGenre(found || DefaultGenre);
  }, [urlGenre, genres]);

  useEffect(() => {
    setTempGenre(selectedGenre);
  }, [selectedGenre]);

  useEffect(() => {
    const found = tags.find((tg) => tg.id === urlTag);
    setSelectedTag(found || null);
  }, [urlTag, tags]);

  useEffect(() => {
    setTempTag(selectedTag);
  }, [selectedTag]);

  const displayedGenres = useMemo(() => {
    return showAllGenres ? genres : genres.slice(0, 8);
  }, [genres, showAllGenres]);

  const filteredTags = useMemo(() => {
    if (!tagSearch.trim()) return tags;
    return tags.filter((tg) => tg.title.toLowerCase().includes(tagSearch.trim().toLowerCase()));
  }, [tags, tagSearch]);

  const applyFilters = (genre: GenreModel, tag: TagModel | null) => {
    const params = new URLSearchParams(searchParams.toString());

    if (genre.id === "semua") params.delete("genre");
    else params.set("genre", genre.id);

    if (!tag) params.delete("tag");
    else params.set("tag", tag.id);

    params.set("page", "1");

    router.push(`${pathname}?${params.toString()}`);
    setFilterSheetOpen(false);
  };

  const changeGenre = (genre: GenreModel) => applyFilters(genre, selectedTag);

  const changeTag = (tag: TagModel | null) => applyFilters(selectedGenre, tag);

  const changeSort = (value: string) => {
    setSortBy(value);

    const params = new URLSearchParams(searchParams.toString());
    params.set("sort", value);
    params.set("page", "1");

    router.push(`${pathname}?${params.toString()}`);
  };

  const loadMore = async () => {
    if (loadingMore || !hasMore) return;

    setLoadingMore(true);

    const nextPage = currentPage + 1;

    const params = new URLSearchParams(searchParams.toString());
    params.set("page", String(nextPage));

    const res = await fetch(`/api/novel?${params.toString()}`);
    const newNovels: PostModel[] = await res.json();

    if (newNovels.length === 0) {
      setHasMore(false);
    } else {
      setNovelList((prev) => [...prev, ...newNovels]);
      setCurrentPage(nextPage);
    }

    setLoadingMore(false);
  };

  useEffect(() => {
    setNovelList(novels);
    setCurrentPage(urlPage);
    setHasMore(true);
  }, [novels, urlPage]);

  useEffect(() => {
    if (isFilterSheetOpen) {
      document.body.style.overflow = "hidden";
    } else {
      document.body.style.overflow = "";
    }

    return () => {
      document.body.style.overflow = "";
    };
  }, [isFilterSheetOpen]);

  const handleSelectPage = (p: number) => {
    if (p < 1 || p > totalPages) return;

    const params = new URLSearchParams(searchParams.toString());
    params.set("page", String(p));

    router.push(`${pathname}?${params.toString()}`);
  };

  return (
    <div className="relative w-full max-w-340 mx-auto px-4 sm:px-6 lg:px-10 xl:px-12 py-6 lg:py-10 flex gap-10">
      <aside className="hidden lg:flex flex-col gap-8 w-64 shrink-0">
        <div className="flex flex-col gap-5">
          <h1 className="font-serif text-2xl font-semibold text-kb-ink capitalize">{t("nav.genre")}</h1>

          <Genres
            items={displayedGenres}
            selected={selectedGenre}
            onSelect={changeGenre}
          />

          {genres.length > 8 && (
            <button
              className="text-sm font-semibold text-primary-600 hover:underline w-fit cursor-pointer"
              onClick={() => setShowAllGenres((prev) => !prev)}
            >
              {t(showAllGenres ? "show less" : "show more")}
            </button>
          )}
        </div>

        <div className="flex flex-col gap-3 pt-6 border-t border-kb-line">
          <h2 className="font-serif text-xl font-semibold text-kb-ink">Cari Tag</h2>

          <div className="relative">
            <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-kb-muted" />
            <input
              value={tagSearch}
              onChange={(e) => setTagSearch(e.target.value)}
              placeholder="Cari tag..."
              className="w-full h-10 pl-9 pr-3 rounded-xl border border-kb-line text-sm text-kb-ink placeholder:text-kb-muted focus:outline-none focus:border-primary-500"
            />
          </div>

          {selectedTag && (
            <button
              onClick={() => changeTag(null)}
              className="flex items-center gap-1.5 text-xs font-semibold text-primary-600 w-fit cursor-pointer hover:underline"
            >
              <X className="w-3 h-3" />
              {toCapitalize(selectedTag.title)}
            </button>
          )}

          <div className="flex flex-wrap gap-2 max-h-64 overflow-y-auto pr-1">
            {filteredTags.map((tagItem) => {
              const isActive = selectedTag?.id === tagItem.id;
              return (
                <button
                  key={tagItem.id}
                  onClick={() => changeTag(isActive ? null : tagItem)}
                  className={`px-3 py-1.5 rounded-full text-xs font-medium transition-colors cursor-pointer ${
                    isActive
                      ? "bg-primary-600 text-white"
                      : "bg-kb-paper-alt text-kb-ink hover:bg-kb-tint"
                  }`}
                >
                  {toCapitalize(tagItem.title)}
                </button>
              );
            })}
            {filteredTags.length === 0 && (
              <p className="text-xs text-kb-muted">Tag tidak ditemukan.</p>
            )}
          </div>
        </div>
      </aside>

      <main className="flex-1 flex flex-col gap-4 lg:gap-5 items-start min-w-0">
        <div className="flex items-center justify-between gap-3 w-full">
          <h1 className="font-serif text-2xl lg:text-[32px] font-semibold text-kb-ink capitalize">
            {t("novels")}
          </h1>
          <button
            onClick={() => setFilterSheetOpen(true)}
            className="lg:hidden flex items-center gap-2 bg-primary-600 text-white px-3.5 py-2 rounded-xl text-sm font-semibold cursor-pointer"
          >
            <SlidersHorizontal className="w-4 h-4" />
            Filter
          </button>
        </div>

        <SortOption selected={sortBy} onChange={changeSort} />

        <NovelList novels={novelList} />

        {hasMore && (
          <div className="w-full flex justify-center lg:hidden">
            <button
              onClick={loadMore}
              disabled={loadingMore}
              className="cursor-pointer mx-auto px-6 py-3 text-sm font-semibold rounded-xl border border-primary-500 text-primary-600 hover:bg-primary-500 hover:text-white transition capitalize"
            >
              {loadingMore ? <Loader size="small" /> : t("show more")}
            </button>
          </div>
        )}

        <div className="hidden w-full justify-center lg:flex">
          <PaginationGenre
            currentPage={urlPage}
            totalPages={totalPages}
            onPageChange={handleSelectPage}
          />
        </div>
      </main>

      {isFilterSheetOpen && (
        <div
          className="lg:hidden fixed inset-0 z-50 bg-black/40 flex items-end"
          onClick={() => setFilterSheetOpen(false)}
        >
          <div
            className="w-full bg-white rounded-t-3xl px-4 pt-4 pb-6 animate-slide-up max-h-[85vh] flex flex-col"
            onClick={(e) => e.stopPropagation()}
          >
            <div className="flex items-center justify-between mb-4 pb-3 border-b border-kb-line shrink-0">
              <h2 className="font-serif text-lg font-semibold text-kb-ink">Filter Novel</h2>

              <button onClick={() => setFilterSheetOpen(false)} className="cursor-pointer text-kb-ink">
                <X className="w-5 h-5" />
              </button>
            </div>

            <div className="flex flex-col gap-6 overflow-y-auto overscroll-contain">
              <div className="flex flex-col gap-1.5">
                <p className="text-xs font-bold uppercase tracking-wide text-kb-muted mb-1">{t("nav.genre")}</p>
                {[DefaultGenre, ...genres].map((genre) => {
                  const isActive = tempGenre.id === genre.id;

                  return (
                    <button
                      key={genre.id}
                      onClick={() => setTempGenre(genre)}
                      className={`text-left px-4 py-2.5 rounded-xl text-sm transition-colors cursor-pointer ${
                        isActive
                          ? "bg-kb-tint text-primary-600 font-bold"
                          : "text-kb-ink font-medium hover:bg-kb-paper-alt"
                      }`}
                    >
                      {toCapitalize(genre.title)}
                    </button>
                  );
                })}
              </div>

              <div className="flex flex-col gap-3">
                <p className="text-xs font-bold uppercase tracking-wide text-kb-muted">Tag</p>

                <div className="relative">
                  <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-kb-muted" />
                  <input
                    value={tagSearch}
                    onChange={(e) => setTagSearch(e.target.value)}
                    placeholder="Cari tag..."
                    className="w-full h-10 pl-9 pr-3 rounded-xl border border-kb-line text-sm text-kb-ink placeholder:text-kb-muted focus:outline-none focus:border-primary-500"
                  />
                </div>

                {tempTag && (
                  <button
                    onClick={() => setTempTag(null)}
                    className="flex items-center gap-1.5 text-xs font-semibold text-primary-600 w-fit cursor-pointer hover:underline"
                  >
                    <X className="w-3 h-3" />
                    {toCapitalize(tempTag.title)}
                  </button>
                )}

                <div className="flex flex-wrap gap-2">
                  {filteredTags.map((tagItem) => {
                    const isActive = tempTag?.id === tagItem.id;
                    return (
                      <button
                        key={tagItem.id}
                        onClick={() => setTempTag(isActive ? null : tagItem)}
                        className={`px-3 py-1.5 rounded-full text-xs font-medium transition-colors cursor-pointer ${
                          isActive
                            ? "bg-primary-600 text-white"
                            : "bg-kb-paper-alt text-kb-ink hover:bg-kb-tint"
                        }`}
                      >
                        {toCapitalize(tagItem.title)}
                      </button>
                    );
                  })}
                </div>
              </div>
            </div>

            <div className="grid grid-cols-2 gap-3 pt-5 shrink-0">
              <button
                onClick={() => {
                  setTempGenre(DefaultGenre);
                  setTempTag(null);
                }}
                className="h-12 rounded-xl border border-kb-line font-semibold text-sm text-kb-ink cursor-pointer hover:bg-kb-paper-alt"
              >
                Reset
              </button>

              <button
                onClick={() => applyFilters(tempGenre, tempTag)}
                className="h-12 rounded-xl bg-primary-600 text-white font-semibold text-sm cursor-pointer hover:brightness-110"
              >
                Terapkan
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
