import Link from "next/link";
import {
  ChevronLeft,
  ChevronRight,
  ChevronsLeft,
  ChevronsRight,
  Search,
} from "lucide-react";

import { Button, buttonVariants } from "@/components/ui/button";
import { MaestrosTable } from "@/components/data-table/maestros-table";
import { AutoSubmitSelect } from "@/components/forms/auto-submit-select";
import {
  ACCOUNT_TYPE_LABELS,
  ACCOUNT_TYPES,
  ACTIVATE_STATUS_LABELS,
  ACTIVATE_STATUSES,
} from "@/lib/constants";
import { getMaestros, type RawSearchParams } from "@/lib/maestros";
import { cn } from "@/lib/utils";

type MaestrosPageProps = {
  searchParams: Promise<RawSearchParams>;
};

const activateStatusOptions = [
  ACTIVATE_STATUSES.PENDING,
  ACTIVATE_STATUSES.TRIAL,
  ACTIVATE_STATUSES.ACTIVE,
  ACTIVATE_STATUSES.CANCELED,
] as const;

const accountTypeOptions = [
  ACCOUNT_TYPES.BASIC_20,
  ACCOUNT_TYPES.STANDARD_50,
  ACCOUNT_TYPES.PRO_100,
  ACCOUNT_TYPES.SCHOOL_500,
  ACCOUNT_TYPES.SCHOOL_1000,
] as const;

const sortOptions = [
  { value: "id-desc", label: "ID 최신순" },
  { value: "id-asc", label: "ID 오래된순" },
  { value: "joinedAt-desc", label: "가입일 최신순" },
  { value: "joinedAt-asc", label: "가입일 오래된순" },
  { value: "availableAt-desc", label: "사용 가능일 최신순" },
  { value: "availableAt-asc", label: "사용 가능일 오래된순" },
] as const;

export default async function MaestrosPage({
  searchParams,
}: MaestrosPageProps) {
  const params = await searchParams;
  const result = await getMaestros(params);
  const paginationItems = buildPaginationItems(result.page, result.totalPages);
  const firstVisiblePage = paginationItems[0] ?? 1;
  const lastVisiblePage = paginationItems.at(-1) ?? result.totalPages;
  const hasFirstPage = paginationItems.includes(1);
  const hasLastPage = paginationItems.includes(result.totalPages);
  const hasPreviousPageGroup = firstVisiblePage > 1;
  const hasNextPageGroup = lastVisiblePage < result.totalPages;

  return (
    <section className="space-y-5">
      <div className="flex flex-col gap-1 sm:flex-row sm:items-end sm:justify-between">
        <div>
          <h1 className="text-2xl font-semibold tracking-normal">마에스트로</h1>
          <p className="mt-1 text-sm text-muted-foreground">
            전체 {result.totalCount.toLocaleString()}명 중 {result.page} /{" "}
            {result.totalPages} 페이지
          </p>
        </div>
      </div>

      <form
        className="grid grid-cols-1 gap-3 rounded-lg border bg-background p-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-[minmax(220px,1fr)_160px_180px_190px_110px_auto]"
        method="get"
      >
        <label className="min-w-0 space-y-1.5">
          <span className="text-xs font-medium text-muted-foreground">
            검색
          </span>
          <div className="relative min-w-0">
            <Search
              className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground"
              aria-hidden="true"
            />
            <input
              className="h-9 w-full min-w-0 rounded-md border bg-background pl-9 pr-3 text-sm outline-none transition-colors focus:border-ring focus:ring-3 focus:ring-ring/30"
              defaultValue={result.q}
              name="q"
              placeholder="이름, 이메일, ID"
              type="search"
            />
          </div>
        </label>

        <label className="min-w-0 space-y-1.5">
          <span className="text-xs font-medium text-muted-foreground">
            상태
          </span>
          <AutoSubmitSelect
            className="h-9 w-full min-w-0 rounded-md border bg-background px-3 text-sm outline-none transition-colors focus:border-ring focus:ring-3 focus:ring-ring/30"
            name="activateStatus"
            value={result.activateStatus ?? "all"}
          >
            <option value="all">전체</option>
            {activateStatusOptions.map((status) => (
              <option key={status} value={status}>
                {ACTIVATE_STATUS_LABELS[status]}
              </option>
            ))}
          </AutoSubmitSelect>
        </label>

        <label className="min-w-0 space-y-1.5">
          <span className="text-xs font-medium text-muted-foreground">
            계정 유형
          </span>
          <AutoSubmitSelect
            className="h-9 w-full min-w-0 rounded-md border bg-background px-3 text-sm outline-none transition-colors focus:border-ring focus:ring-3 focus:ring-ring/30"
            name="accountType"
            value={result.accountType ?? "all"}
          >
            <option value="all">전체</option>
            {accountTypeOptions.map((accountType) => (
              <option key={accountType} value={accountType}>
                {ACCOUNT_TYPE_LABELS[accountType]}
              </option>
            ))}
          </AutoSubmitSelect>
        </label>

        <label className="min-w-0 space-y-1.5">
          <span className="text-xs font-medium text-muted-foreground">
            정렬
          </span>
          <AutoSubmitSelect
            className="h-9 w-full min-w-0 rounded-md border bg-background px-3 text-sm outline-none transition-colors focus:border-ring focus:ring-3 focus:ring-ring/30"
            name="sort"
            value={result.sort}
          >
            {sortOptions.map((option) => (
              <option key={option.value} value={option.value}>
                {option.label}
              </option>
            ))}
          </AutoSubmitSelect>
        </label>

        <label className="min-w-0 space-y-1.5">
          <span className="text-xs font-medium text-muted-foreground">
            페이지 크기
          </span>
          <AutoSubmitSelect
            className="h-9 w-full min-w-0 rounded-md border bg-background px-3 text-sm outline-none transition-colors focus:border-ring focus:ring-3 focus:ring-ring/30"
            name="pageSize"
            value={result.pageSize}
          >
            {[10, 20, 50, 100].map((pageSize) => (
              <option key={pageSize} value={pageSize}>
                {pageSize}
              </option>
            ))}
          </AutoSubmitSelect>
        </label>

        <div className="flex min-w-0 flex-wrap items-end gap-2 sm:col-span-2 xl:col-span-1">
          <Button className="h-9" type="submit">
            적용
          </Button>
          <Link
            className={buttonVariants({
              variant: "outline",
              size: "default",
              className: "h-9",
            })}
            href="/maestros"
          >
            초기화
          </Link>
        </div>
      </form>

      <MaestrosTable data={result.items} />

      <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <p className="text-sm text-muted-foreground">
          페이지당 {result.pageSize}개 표시
        </p>
        <nav
          aria-label="마에스트로 목록 페이지"
          className="flex flex-wrap items-center gap-1.5"
        >
          {!hasFirstPage ? (
            <Link
              aria-label="처음 페이지"
              className={buttonVariants({
                variant: "outline",
                size: "icon-sm",
              })}
              href={buildPageHref(params, 1)}
            >
              <ChevronsLeft className="size-4" aria-hidden="true" />
            </Link>
          ) : null}

          {hasPreviousPageGroup ? (
            <Link
              aria-label="이전 5페이지"
              className={buttonVariants({
                variant: "outline",
                size: "icon-sm",
              })}
              href={buildPageHref(params, Math.max(1, result.page - 5))}
            >
              <ChevronLeft className="size-4" aria-hidden="true" />
            </Link>
          ) : null}

          {paginationItems.map((item) => (
            <Link
              aria-current={item === result.page ? "page" : undefined}
              className={cn(
                buttonVariants({
                  variant: item === result.page ? "default" : "outline",
                  size: "sm",
                }),
                "min-w-8 px-2"
              )}
              href={buildPageHref(params, item)}
              key={item}
            >
              {item}
            </Link>
          ))}

          {hasNextPageGroup ? (
            <Link
              aria-label="다음 5페이지"
              className={buttonVariants({
                variant: "outline",
                size: "icon-sm",
              })}
              href={buildPageHref(
                params,
                Math.min(result.totalPages, result.page + 5)
              )}
            >
              <ChevronRight className="size-4" aria-hidden="true" />
            </Link>
          ) : null}

          {!hasLastPage ? (
            <Link
              aria-label="끝 페이지"
              className={buttonVariants({
                variant: "outline",
                size: "icon-sm",
              })}
              href={buildPageHref(params, result.totalPages)}
            >
              <ChevronsRight className="size-4" aria-hidden="true" />
            </Link>
          ) : null}
        </nav>
      </div>
    </section>
  );
}

function buildPageHref(rawParams: RawSearchParams, page: number) {
  const params = new URLSearchParams();

  Object.entries(rawParams).forEach(([key, value]) => {
    const firstValue = Array.isArray(value) ? value[0] : value;

    if (firstValue && key !== "page") {
      params.set(key, firstValue);
    }
  });
  params.set("page", String(Math.max(1, page)));

  return `/maestros?${params.toString()}`;
}

function buildPaginationItems(currentPage: number, totalPages: number) {
  const startPage = Math.max(1, currentPage - 2);
  const endPage = Math.min(totalPages, currentPage + 2);

  return Array.from(
    { length: endPage - startPage + 1 },
    (_, index) => startPage + index
  );
}
