"use client";

import type { ReactNode } from "react";
import { cx } from "../../utils";
import { FoxCaretLeftIcon, FoxCaretRightIcon } from "../../icons";

export interface FoxPaginationProps {
  /** 1부터 센다. */
  currentPage: number;
  totalPages: number;
  onPageChange?: (page: number) => void;
  /**
   * 페이지 번호를 링크로 만들 때. 주면 `<a>`가 되고, 없으면 `<button>`이 된다.
   * 라우팅은 호출부 몫이다.
   */
  buildHref?: (page: number) => string;
  /** 한 번에 보여줄 번호 개수. 기본 5. */
  windowSize?: number;
  /**
   * 창 밖에 페이지가 더 있으면 `…`을 붙인다. 시안의 pagination-item에 있는 모양이다.
   * 기본값은 꺼짐 — 시안의 pagination 조합에는 없다.
   */
  ellipsis?: boolean;

  previousLabel?: string;
  nextLabel?: string;
  /** 스크린리더가 읽을 이름. 한 화면에 둘 이상 두면 서로 다르게 준다. */
  label?: string;
  /** 참이면 렌더하지 않는다(DOM에 남지 않는다). */
  hidden?: boolean;
  /** 배치 조정용. */
  className?: string;
}

/** 현재 페이지를 가운데 두고 `size`개를 [1, total] 안에서 민다. */
function pageWindow(current: number, total: number, size: number): number[] {
  if (total < 1) {
    return [];
  }
  const start = Math.max(1, Math.min(current - Math.floor(size / 2), total - size + 1));
  const end = Math.min(total, start + size - 1);

  const pages: number[] = [];
  for (let page = Math.max(1, start); page <= end; page += 1) {
    pages.push(page);
  }
  return pages;
}

/**
 * @fox 페이지네이션.
 *
 * PC는 [이전] [번호들] [다음]이 한 줄이고, 모바일은 이전·다음이 위로 빠지고 번호가 아래
 * 줄에 선다(시안의 device 축). 그 전환은 CSS가 화면 폭을 보고 하므로 프롭이 없다.
 *
 * ⚠️ 스타일은 이 파일이 import하지 않는다 — 호스트 앱이 `@use "@fox/styles/components"`
 * (또는 개별 파티셜)로 한 번 불러와야 한다.
 */
export function FoxPagination({
  currentPage,
  totalPages,
  onPageChange,
  buildHref,
  windowSize = 5,
  ellipsis = false,
  previousLabel = "이전",
  nextLabel = "다음",
  label = "페이지",
  hidden = false,
  className,
}: FoxPaginationProps) {
  if (hidden || totalPages < 1) {
    return null;
  }

  const pages = pageWindow(currentPage, totalPages, windowSize);
  const first = pages[0] ?? 1;
  const last = pages[pages.length - 1] ?? 1;

  const step = (target: number, disabled: boolean, direction: "prev" | "next", text: string) => {
    const icon = (
      <span className="fox-pagination__step-icon" aria-hidden="true">
        {direction === "prev" ? <FoxCaretLeftIcon /> : <FoxCaretRightIcon />}
      </span>
    );
    const body: ReactNode =
      direction === "prev" ? (
        <>
          {icon}
          {text}
        </>
      ) : (
        <>
          {text}
          {icon}
        </>
      );
    const itemClass = cx("fox-pagination__item", "fox-pagination__step");

    // 갈 곳이 없으면 링크로 두지 않는다 — 눌리지 않는 링크는 스크린리더에서도 걸린다.
    if (disabled) {
      return (
        <span className={itemClass} aria-disabled="true">
          {body}
        </span>
      );
    }
    return buildHref ? (
      <a className={itemClass} href={buildHref(target)} onClick={() => onPageChange?.(target)}>
        {body}
      </a>
    ) : (
      <button className={itemClass} type="button" onClick={() => onPageChange?.(target)}>
        {body}
      </button>
    );
  };

  const number = (page: number) => {
    const current = page === currentPage;
    const itemClass = cx(
      "fox-pagination__item",
      "fox-pagination__number",
      current && "fox-pagination__number--current"
    );

    if (current) {
      return (
        <span className={itemClass} aria-current="page">
          {page}
        </span>
      );
    }
    return buildHref ? (
      <a
        className={itemClass}
        href={buildHref(page)}
        aria-label={`${page}페이지`}
        onClick={() => onPageChange?.(page)}
      >
        {page}
      </a>
    ) : (
      <button
        className={itemClass}
        type="button"
        aria-label={`${page}페이지`}
        onClick={() => onPageChange?.(page)}
      >
        {page}
      </button>
    );
  };

  const more = (
    <span className="fox-pagination__item fox-pagination__ellipsis" aria-hidden="true">
      …
    </span>
  );

  // 이전·목록·다음이 형제다. 모바일에서 목록만 한 줄을 통째로 차지해 아래로 밀린다.
  return (
    <nav className={cx("fox-pagination", className)} aria-label={label}>
      {step(currentPage - 1, currentPage <= 1, "prev", previousLabel)}

      <ul className="fox-pagination__list">
        {ellipsis && first > 1 && <li>{more}</li>}
        {pages.map((page) => (
          <li key={page}>{number(page)}</li>
        ))}
        {ellipsis && last < totalPages && <li>{more}</li>}
      </ul>

      {step(currentPage + 1, currentPage >= totalPages, "next", nextLabel)}
    </nav>
  );
}
