import type { Metadata } from 'next';
import { verifySession } from '@/lib/auth/dal';
import {
  fetchCodeDetails,
  fetchCodeGroups,
} from '@/lib/data/repositories/common-code-repository';
import type { CommonCodeGroup } from '@/lib/domain/common-code';
import {
  COMMON_CODE_DETAIL_PAGE_SIZE,
  COMMON_CODE_PAGE_SIZE,
  parseCommonCodeQuery,
  type CommonCodeQuery,
} from '@/lib/domain/common-code-query';
import { CodeManagement } from './_components/code-management';

export const metadata: Metadata = {
  title: '코드관리',
};

// cookies()로 이미 동적이지만, 정적 프리렌더로 데이터가 빌드 산출물에 박히는 경로를
// 원천 차단하기 위해 명시적으로 강제한다.
export const dynamic = 'force-dynamic';

interface PageProps {
  searchParams: Promise<Record<string, string | string[] | undefined>>;
}

/** 부분일치 검색 — 백엔드가 완전일치만 지원해 여기서 거른다(Repository 주석 참조). */
function filterGroups(
  groups: CommonCodeGroup[],
  query: CommonCodeQuery
): CommonCodeGroup[] {
  const keyword = query.keyword.trim().toLowerCase();
  if (!keyword) {
    return groups;
  }

  return groups.filter((group) => {
    const target = query.searchField === 'comCd' ? group.comCd : group.name;
    return target.toLowerCase().includes(keyword);
  });
}

/** 1-based 페이지를 잘라낸다. 범위를 벗어난 페이지는 마지막 페이지로 맞춘다. */
function paginate<T>(rows: T[], page: number, pageSize: number) {
  const totalPages = Math.max(1, Math.ceil(rows.length / pageSize));
  const currentPage = Math.min(Math.max(page, 1), totalPages);
  const offset = (currentPage - 1) * pageSize;

  return {
    rows: rows.slice(offset, offset + pageSize),
    currentPage,
    totalPages,
    totalCount: rows.length,
  };
}

/**
 * 코드관리 — 기획 SYS_COD_001, 시안 관리자페이지(QsFVFFUKGH68xAPVkF3SJ9) 5402:13399
 *
 * 좌측 공통코드를 고르면 우측 상세코드 목록이 그 그룹으로 갱신된다. 선택·검색·두 목록의 페이지가
 * 모두 URL에 실려, 이 서버 컴포넌트가 매 요청 그 조건대로 데이터를 만들어 넘긴다.
 *
 * **검색·페이징을 서버에서 처리한다** — 백엔드가 두 목록 모두 전체를 반환하고 검색도 완전일치라
 * (Repository 주석 참조), 부분일치 필터와 페이지 자르기를 여기서 한다. 전체를 받으므로 총건수는
 * 정확하다(다른 목록 화면의 하한값 보정이 여기에는 필요 없다).
 *
 * **선택된 공통코드가 목록에 없으면 첫 행으로 대체한다** — 검색으로 걸러졌거나 삭제된 코드가
 * URL에 남아 있으면 우측이 영영 비어 보이기 때문이다.
 */
export default async function Page({ searchParams }: PageProps) {
  await verifySession();

  const query = parseCommonCodeQuery(await searchParams);

  const groups = filterGroups(await fetchCodeGroups(), query);
  const groupPage = paginate(groups, query.page, COMMON_CODE_PAGE_SIZE);

  const selectedComCd =
    groups.find((group) => group.comCd === query.comCd)?.comCd ??
    groupPage.rows[0]?.comCd ??
    null;

  const details = selectedComCd ? await fetchCodeDetails(selectedComCd) : [];
  const detailPage = paginate(
    details,
    query.detailPage,
    COMMON_CODE_DETAIL_PAGE_SIZE
  );

  return (
    <CodeManagement
      query={query}
      groups={groupPage.rows}
      groupTotalCount={groupPage.totalCount}
      groupPage={groupPage.currentPage}
      groupTotalPages={groupPage.totalPages}
      selectedComCd={selectedComCd}
      details={detailPage.rows}
      detailTotalCount={detailPage.totalCount}
      detailPage={detailPage.currentPage}
      detailTotalPages={detailPage.totalPages}
      // 새 상세코드의 기본 정렬번호 — 시안 등록 팝업이 기존 개수 다음 번호를 채워 둔다.
      nextSortSeq={details.length + 1}
    />
  );
}
