"use client";

import { useTheme } from "@/components/theme/ThemeProvider";
import {
  buildPageItems,
  pageRange,
  totalPageCount,
} from "@/lib/pagination/page-items";
import styles from "./Pagination.module.css";

/**
 * 一覧のページ送り（指示書AA 段階2）
 *
 * ★判断はこの部品に置かない★ — 何ページあるか / どの番号を描くかは
 *   `lib/pagination/page-items.ts` の純粋関数が決める（`components/**` は
 *   `vitest.config.ts` の include に入っておらずテストが走らないため）。
 *   この部品がやるのは「返ってきたものを描く」「押されたページを親に通知する」だけ。
 *
 * ★`page` / `perPage` を内部 state にしないこと★ — 親が持つ。
 *   取得（fetch）も親の仕事で、この部品は fetch しない。
 *
 * ★`components/ui/` で `useTheme()` を使う最初の部品★
 *   （既存の Pill / FilterButton / GradeBadge / StatCard / ProgressBar はどれも使っていない）。
 *   使うのは ★文言の対訳 `t` を取るためだけ★ で、色は CSS 変数から取る
 *   （`THEME_TOKENS` は import しない）。件数表示の文言を各画面に散らすと
 *   `.replace()` の連鎖が6画面に増えるため、ここ1箇所に閉じ込めている。
 *
 * ★モックに前例が無いUI★ — `d-watch-mock.jsx` にページ送りは1つも無い。
 *   `CLAUDE.md` §5（モックが画面の正）の例外として、ユーザーの明示の承認
 *   （2026-09-11「ページ送りは作成してください」）に基づき新規に作っている。
 */
interface PaginationProps {
  /**
   * 総件数。
   *
   * ★`meta.total` を渡すこと。`summary.total` を渡さないこと★（D-054 / 指示書AA 禁止事項4）。
   * `summary` は対応状況フィルタの**前**に計算されているため、一覧の件数とは別物で、
   * 総ページ数がずれる。
   */
  total: number;
  /** 現在ページ（1始まり） */
  page: number;
  /**
   * 1ページあたりの件数。
   *
   * ★`PAGINATION.defaultPerPage` を渡すこと。`50` を直書きしないこと★（`CLAUDE.md` §7）。
   */
  perPage: number;
  onPageChange: (page: number) => void;
}

export function Pagination({
  total,
  page,
  perPage,
  onPageChange,
}: PaginationProps) {
  const { t } = useTheme();

  const totalPages = totalPageCount(total, perPage);
  // ★0件のときは部品ごと出さない★ — 各画面が「該当する〜はありません」を
  //   既に出しているので、「全0件中 0〜0件」と二重に出るのを避ける
  if (totalPages === 0) return null;

  const { from, to } = pageRange(total, page, perPage);
  const current = Math.min(Math.max(page, 1), totalPages);
  const items = buildPageItems(current, totalPages);

  // ★渡す値は必ず実在するページに丸める★（押した先が「有りません」にならないように）
  function go(next: number) {
    const clamped = Math.min(Math.max(next, 1), totalPages);
    if (clamped !== current) onPageChange(clamped);
  }

  return (
    <div className={styles.footer}>
      <div className={styles.count}>
        {t("全{total}件中 {from}〜{to}件")
          .replace("{total}", String(total))
          .replace("{from}", String(from))
          .replace("{to}", String(to))}
      </div>
      {/* ★総ページ数が1のときは件数表示だけ出す★（押せないボタンを並べない） */}
      {totalPages > 1 && (
        <nav className={styles.nav} aria-label={t("ページ送り")}>
          <button
            type="button"
            className={styles.step}
            onClick={() => go(current - 1)}
            disabled={current <= 1}
          >
            {t("前へ")}
          </button>
          {items.map((item) =>
            item.kind === "page" ? (
              <button
                key={`p-${item.page}`}
                type="button"
                className={
                  item.page === current
                    ? `${styles.num} ${styles.numActive}`
                    : styles.num
                }
                onClick={() => go(item.page)}
                disabled={item.page === current}
                aria-current={item.page === current ? "page" : undefined}
              >
                {item.page}
              </button>
            ) : (
              // ★「…」は button にしないこと★ — 押せる見た目にすると
              //   「何ページに飛ぶのか」という存在しない問いが生まれる
              <span key={item.key} className={styles.gap} aria-hidden="true">
                …
              </span>
            )
          )}
          <button
            type="button"
            className={styles.step}
            onClick={() => go(current + 1)}
            disabled={current >= totalPages}
          >
            {t("次へ")}
          </button>
        </nav>
      )}
    </div>
  );
}
