'use client';

import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { FoxBadge } from '@fox/core/components/fox-badge';
import { FoxButton } from '@fox/core/components/fox-button';
import {
  FoxListContainer,
  type FoxListColumn,
} from '@fox/core/components/fox-list-container';
import { FoxSelectText } from '@fox/core/components/fox-select-text';
import { formatPhoneNumber } from '@/lib/domain/phone-number';
import {
  formatGradeClassNumber,
  type StudentMember,
} from '@/lib/domain/student-member';
import {
  STUDENT_MEMBERS_EXCEL_PATH,
  STUDENT_MEMBER_PAGE_SIZE_OPTIONS,
  STUDENT_MEMBER_SEARCH_FIELD_OPTIONS,
  STUDENT_MEMBER_SORT_OPTIONS,
  buildStudentMemberHref,
  type StudentMemberPageSize,
  type StudentMemberQuery,
  type StudentMemberSearchField,
  type StudentMemberSortOption,
} from '@/lib/domain/student-member-query';
import { StudentDetailModal } from './student-detail-modal';

interface StudentListProps {
  items: StudentMember[];
  query: StudentMemberQuery;
  /** 화면이 실제로 보여주는 페이지 — 순번 계산의 기준이다. */
  currentPage: number;
  totalPages: number;
  totalCount: number;
}

/** 값이 없으면 시안처럼 자리를 비우지 않고 `-`로 채운다. */
function text(value: string | number | null | undefined) {
  return value === null || value === undefined || value === '' ? '-' : String(value);
}

/**
 * 학생 회원 목록 — 시안: 관리자페이지(QsFVFFUKGH68xAPVkF3SJ9) container 5199:9014
 *
 * 뼈대는 `FoxListContainer`가 전부 그린다. 이 파일이 갖는 것은 **이 화면 고유의 것**뿐이다 —
 * 13개 열의 정의, 정렬·페이지 크기 셀렉트, 엑셀 다운로드, 그리고 URL을 갱신하는 방법.
 *
 * 이동은 두 갈래로 나뉜다. 페이지네이션은 `buildHref`로 **링크**가 되고(주소가 곧 상태라
 * 새로고침·뒤로가기·공유가 그대로 동작한다), 검색·정렬·페이지 크기는 컨트롤이 눌린 순간
 * `router.replace`로 같은 주소 규칙을 태운다. 어느 쪽이든 목록을 다시 그리는 것은 서버다.
 *
 * 순번은 `query.page`가 아니라 `currentPage`를 기준으로 센다 — 백엔드가 범위를 벗어난 페이지
 * 요청을 잘라서 응답하면 둘이 어긋나, "1/1 페이지"인데 순번은 31부터 시작하는 상태가 된다.
 */
export function StudentList({
  items,
  query,
  currentPage,
  totalPages,
  totalCount,
}: StudentListProps) {
  const router = useRouter();
  const [detailMember, setDetailMember] = useState<StudentMember | null>(null);

  /** 목록 조건이 바뀌면 늘 1페이지로 되돌린다 — 이전 페이지 번호는 새 조건에서 의미가 다르다. */
  function go(patch: Partial<StudentMemberQuery>) {
    router.replace(buildStudentMemberHref(query, { ...patch, page: 1 }));
  }

  const columns: FoxListColumn<StudentMember>[] = [
    {
      key: 'no',
      header: '번호',
      width: 80,
      // 저장된 값이 아니라 현재 페이지 기준 표시 순번이다(종전 표와 같은 규칙).
      render: (_row, index) => (currentPage - 1) * query.pageSize + index + 1,
    },
    { key: 'memberCode', header: '회원코드', width: 120 },
    { key: 'name', header: '이름', width: 120 },
    { key: 'loginId', header: '아이디', width: 160 },
    {
      key: 'phoneNumber',
      header: '휴대전화번호',
      width: 160,
      render: (row) => text(formatPhoneNumber(row.phoneNumber)),
    },
    { key: 'email', header: '이메일', width: 200, render: (row) => text(row.email) },
    {
      key: 'role',
      header: '역할',
      width: 120,
      render: (row) => (
        <FoxBadge type="pastel" color="primary" size="md">
          {row.role}
        </FoxBadge>
      ),
    },
    {
      key: 'schoolName',
      header: '학교',
      width: 160,
      render: (row) => text(row.schoolName),
    },
    { key: 'classInfo', header: '학년/반/번호', width: 160, render: formatGradeClassNumber },
    {
      key: 'guardianName',
      header: '보호자이름',
      width: 120,
      render: (row) => text(row.guardianName),
    },
    {
      key: 'guardianPhoneNumber',
      header: '보호자연락처',
      width: 160,
      render: (row) => text(formatPhoneNumber(row.guardianPhoneNumber)),
    },
    {
      key: 'joinedAt',
      header: '가입일',
      width: 160,
      render: (row) => text(row.joinedAt),
    },
  ];

  return (
    <>
      <FoxListContainer<StudentMember>
      title="학생 회원 목록"
      breadcrumb={[
        { label: '홈', href: '/' },
        { label: '회원정보관리' },
        { label: '학생 회원' },
      ]}
      caption="학생 회원 목록"
      columns={columns}
      rows={items}
      rowKey={(row) => row.id}
      totalCount={totalCount}
      emptyMessage="검색 결과가 없습니다. 다른 검색어로 다시 시도해 주세요."
      sorts={
        <>
          <FoxSelectText
            size="sm"
            ariaLabel="정렬"
            icon={<i className="fox-ico fox-ico-ArrowsDownUp" aria-hidden="true" />}
            options={STUDENT_MEMBER_SORT_OPTIONS.map((option) => ({
              value: option.value,
              label: option.label,
            }))}
            value={query.sort}
            onValueChange={(value) => go({ sort: value as StudentMemberSortOption })}
          />
          <FoxSelectText
            size="sm"
            ariaLabel="페이지 크기"
            options={STUDENT_MEMBER_PAGE_SIZE_OPTIONS.map((size) => ({
              value: String(size),
              label: `${size}개씩 보기`,
            }))}
            value={String(query.pageSize)}
            onValueChange={(value) =>
              go({ pageSize: Number(value) as StudentMemberPageSize })
            }
          />
        </>
      }
      searchFields={STUDENT_MEMBER_SEARCH_FIELD_OPTIONS.map((option) => ({
        value: option.value,
        label: option.label,
      }))}
      searchField={query.searchField}
      keyword={query.keyword}
      toolbarActions={
        // 네이티브 GET 폼이라야 한다 — 응답이 첨부파일(Content-Disposition)이라 라우터
        // 내비게이션으로는 처리할 수 없고, 브라우저가 화면을 둔 채 파일만 내려받는다.
        // 검색·페이징 값을 싣지 않는 것이 사양이다(파일은 항상 전체 데이터).
        <form action={STUDENT_MEMBERS_EXCEL_PATH} method="get">
          <FoxButton
            type="secondary"
            size="md"
            htmlType="submit"
            leadingIcon={<i className="fox-ico fox-ico-DownloadSimple" aria-hidden="true" />}
            label="엑셀 다운로드"
          />
        </form>
      }
      onRowSelect={(row) => setDetailMember(row)}
      page={currentPage}
      totalPages={totalPages}
      buildHref={(patch) =>
        buildStudentMemberHref(query, { page: Number(patch.page ?? 1) })
      }
      onQueryChange={(patch) => {
        if (patch.keyword !== undefined || patch.searchField !== undefined) {
          go({
            keyword: String(patch.keyword ?? ''),
            searchField: (patch.searchField ??
              query.searchField) as StudentMemberSearchField,
          });
        }
      }}
      />
      {detailMember && (
        <StudentDetailModal
          member={detailMember}
          onClose={() => setDetailMember(null)}
        />
      )}
    </>
  );
}
