"use client";

import { useState, useEffect } from "react";
import {
  ChevronLeft,
  ChevronRight,
  ChevronsLeft,
  ChevronsRight,
} from "lucide-react";

import { Button, buttonVariants } from "@/components/ui/button";
import { cn, formatDateTime } from "@/lib/utils";
import type { MaestroLogsResult } from "@/lib/maestros";

type LogsSectionProps = {
  maestroID: number;
};

export function LogsSection({ maestroID }: LogsSectionProps) {
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(10);

  const [data, setData] = useState<MaestroLogsResult | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [errorMessage, setErrorMessage] = useState("");

  useEffect(() => {
    let cancelled = false;

    const run = async () => {
      setIsLoading(true);
      setErrorMessage("");

      try {
        const params = new URLSearchParams({
          page: String(page),
          pageSize: String(pageSize),
        });

        const response = await fetch(
          `/api/maestros/${maestroID}/logs?${params.toString()}`
        );

        if (!response.ok) {
          throw new Error("처리 로그를 불러오지 못했습니다.");
        }

        const result = (await response.json()) as MaestroLogsResult;

        if (!cancelled) {
          setData(result);
        }
      } catch (err) {
        if (!cancelled) {
          setErrorMessage(
            err instanceof Error
              ? err.message
              : "처리 로그를 불러오지 못했습니다."
          );
        }
      } finally {
        if (!cancelled) {
          setIsLoading(false);
        }
      }
    };

    void run();

    return () => {
      cancelled = true;
    };
  }, [maestroID, page, pageSize]);

  return (
    <section className="rounded-lg border bg-background p-5">
      <div>
        <h2 className="text-base font-semibold">처리 로그</h2>
        <p className="mt-1 text-sm text-muted-foreground">
          {data ? `전체 ${data.totalCount.toLocaleString()}건` : "로딩 중..."}
        </p>
      </div>

      {errorMessage ? (
        <p className="mt-4 text-sm text-destructive">{errorMessage}</p>
      ) : (
        <>
          <LogTable isLoading={isLoading} result={data} />
          {data ? (
            <LogPagination
              onPageChange={setPage}
              onPageSizeChange={(size) => {
                setPageSize(size);
                setPage(1);
              }}
              page={data.page}
              pageSize={pageSize}
              totalPages={data.totalPages}
            />
          ) : null}
        </>
      )}
    </section>
  );
}

function LogTable({
  result,
  isLoading,
}: {
  result: MaestroLogsResult | null;
  isLoading: boolean;
}) {
  if (isLoading || !result) {
    return (
      <div className="mt-4 flex h-24 items-center justify-center rounded-lg border">
        <p className="text-sm text-muted-foreground">로딩 중...</p>
      </div>
    );
  }

  return (
    <div className="mt-4 overflow-hidden rounded-lg border">
      <div className="overflow-x-auto">
        <table className="w-full min-w-[560px] border-collapse text-sm">
          <thead className="bg-muted/60">
            <tr className="border-b">
              <th className="h-10 px-3 text-left text-xs font-medium text-muted-foreground">
                LogID
              </th>
              <th className="h-10 px-3 text-left text-xs font-medium text-muted-foreground">
                유형
              </th>
              <th className="h-10 px-3 text-left text-xs font-medium text-muted-foreground">
                처리일시
              </th>
              <th className="h-10 px-3 text-left text-xs font-medium text-muted-foreground">
                내용
              </th>
            </tr>
          </thead>
          <tbody>
            {result.items.length > 0 ? (
              result.items.map((log) => (
                <tr
                  className="border-b last:border-b-0"
                  key={log.maestroLogID}
                >
                  <td className="h-11 px-3 align-middle">
                    <span className="font-mono text-xs tabular-nums">
                      {log.maestroLogID}
                    </span>
                  </td>
                  <td className="h-11 px-3 align-middle">{log.type}</td>
                  <td className="h-11 px-3 align-middle">
                    {formatDateTime(new Date(log.logDateTime))}
                  </td>
                  <td className="h-11 max-w-[360px] break-words px-3 align-middle">
                    {log.remark}
                  </td>
                </tr>
              ))
            ) : (
              <tr>
                <td
                  className="h-24 px-3 text-center text-sm text-muted-foreground"
                  colSpan={4}
                >
                  처리 로그가 없습니다.
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function LogPagination({
  page,
  pageSize,
  totalPages,
  onPageChange,
  onPageSizeChange,
}: {
  page: number;
  pageSize: number;
  totalPages: number;
  onPageChange: (page: number) => void;
  onPageSizeChange: (pageSize: number) => void;
}) {
  const showNav = totalPages > 1;
  const paginationItems = buildPaginationItems(page, totalPages);
  const firstVisiblePage = paginationItems[0] ?? 1;
  const lastVisiblePage = paginationItems.at(-1) ?? totalPages;
  const hasFirstPage = paginationItems.includes(1);
  const hasLastPage = paginationItems.includes(totalPages);
  const hasPreviousPageGroup = firstVisiblePage > 1;
  const hasNextPageGroup = lastVisiblePage < totalPages;

  return (
    <div className="mt-3 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
      <label className="flex items-center gap-2">
        <span className="text-sm text-muted-foreground">페이지당</span>
        <select
          className="h-7 rounded-md border bg-background px-2 text-sm outline-none transition-colors focus:border-ring focus:ring-3 focus:ring-ring/30"
          onChange={(e) => onPageSizeChange(Number(e.target.value))}
          value={pageSize}
        >
          {[10, 20, 50].map((size) => (
            <option key={size} value={size}>
              {size}
            </option>
          ))}
        </select>
        <span className="text-sm text-muted-foreground">개 표시</span>
      </label>
      {showNav ? (
        <nav
          aria-label="처리 로그 페이지"
          className="self-end flex flex-wrap items-center gap-1.5 sm:self-auto"
        >
          {!hasFirstPage ? (
            <Button
              aria-label="처음 페이지"
              className={buttonVariants({ variant: "outline", size: "icon-sm" })}
              onClick={() => onPageChange(1)}
              type="button"
            >
              <ChevronsLeft aria-hidden="true" className="size-4" />
            </Button>
          ) : null}

          {hasPreviousPageGroup ? (
            <Button
              aria-label="이전 5페이지"
              className={buttonVariants({ variant: "outline", size: "icon-sm" })}
              onClick={() => onPageChange(Math.max(1, page - 5))}
              type="button"
            >
              <ChevronLeft aria-hidden="true" className="size-4" />
            </Button>
          ) : null}

          {paginationItems.map((item) => (
            <Button
              aria-current={item === page ? "page" : undefined}
              className={cn(
                buttonVariants({
                  variant: item === page ? "default" : "outline",
                  size: "sm",
                }),
                "min-w-8 px-2"
              )}
              key={item}
              onClick={() => onPageChange(item)}
              type="button"
            >
              {item}
            </Button>
          ))}

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

          {!hasLastPage ? (
            <Button
              aria-label="끝 페이지"
              className={buttonVariants({ variant: "outline", size: "icon-sm" })}
              onClick={() => onPageChange(totalPages)}
              type="button"
            >
              <ChevronsRight aria-hidden="true" className="size-4" />
            </Button>
          ) : null}
        </nav>
      ) : null}
    </div>
  );
}

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
  );
}
