'use client';

import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { FoxButton } from '@fox/core/components/fox-button';
import { FoxHeadingGroup } from '@fox/core/components/fox-heading-group';
import {
  FoxListContainer,
  type FoxListColumn,
} from '@fox/core/components/fox-list-container';
import { FoxPageHeader } from '@fox/core/components/fox-page-header';
import { useFeedback } from '@/app/_hooks/use-feedback';
import { useBlockingAction } from '@/app/_hooks/use-blocking-action';
import {
  formatOptionalText,
  type CommonCodeDetail,
  type CommonCodeGroup,
} from '@/lib/domain/common-code';
import {
  COMMON_CODE_PAGE_SIZE,
  COMMON_CODE_SEARCH_FIELD_OPTIONS,
  buildCommonCodeHref,
  type CommonCodeQuery,
  type CommonCodeSearchField,
} from '@/lib/domain/common-code-query';
import { deleteCodeDetailAction, deleteCodeGroupAction } from '../_actions';
import { CodeDetailModal } from './code-detail-modal';
import { CodeGroupModal } from './code-group-modal';
import { CodeRowActions } from './code-row-actions';
import styles from './code-management.module.scss';

interface CodeManagementProps {
  query: CommonCodeQuery;
  groups: CommonCodeGroup[];
  groupTotalCount: number;
  groupPage: number;
  groupTotalPages: number;
  /** 화면이 실제로 보여주는 선택 — URL 값이 목록에 없으면 서버가 첫 행으로 바꿔 넘긴다. */
  selectedComCd: string | null;
  details: CommonCodeDetail[];
  detailTotalCount: number;
  detailPage: number;
  detailTotalPages: number;
  nextSortSeq: number;
}

/**
 * 설명 칸 — 한 줄로 줄이고 넘치면 말줄임한다(스타일 주석 참조). 잘린 글자를 읽을 방법이
 * 있어야 하므로 전문을 `title`로 남긴다.
 */
function Truncated({ text }: { text: string | null }) {
  const value = formatOptionalText(text);
  return (
    <span className={styles.truncate} title={text ?? undefined}>
      {value}
    </span>
  );
}

/** 어느 팝업이 열려 있는지. 한 번에 하나만 열린다. */
type OpenModal =
  | { kind: 'group-create' }
  | { kind: 'group-edit'; group: CommonCodeGroup }
  | { kind: 'detail-create' }
  | { kind: 'detail-edit'; detail: CommonCodeDetail }
  | null;

/**
 * 코드관리 — 기획 SYS_COD_001, 시안 관리자페이지(QsFVFFUKGH68xAPVkF3SJ9) 5402:13399
 *
 * 목록이 둘이지만 화면은 하나다. 좌측 공통코드를 **행 전체로 눌러** 고르면 우측 상세코드가 그
 * 그룹으로 갱신된다(기획 ④) — 선택은 URL에 실리므로 갱신은 서버가 다시 그려 준다.
 *
 * 두 목록 모두 `FoxListContainer`를 쓰되 화면 제목은 위에서 한 번만 그린다(`FoxPageHeader`).
 * 패널 이름은 `FoxHeadingGroup`이다 — 화면에 여럿 설 수 있는 구역 제목이라 `<h2>`로 나간다.
 *
 * 우측에는 검색이 없다(시안) — 상세코드는 선택된 그룹에 속한 것이 전부라 걸러 낼 대상이 아니다.
 */
export function CodeManagement({
  query,
  groups,
  groupTotalCount,
  groupPage,
  groupTotalPages,
  selectedComCd,
  details,
  detailTotalCount,
  detailPage,
  detailTotalPages,
  nextSortSeq,
}: CodeManagementProps) {
  const router = useRouter();
  const { showAlert, hideAlert, showToast } = useFeedback();
  const [modal, setModal] = useState<OpenModal>(null);
  const [isDeleting, startDeleting] = useBlockingAction();

  function go(patch: Partial<CommonCodeQuery>) {
    router.replace(buildCommonCodeHref(query, patch));
  }

  /**
   * 삭제는 되돌릴 수 없어 확인 얼럿을 거친다(기획 ④). 성공 뒤 화면 갱신은 Server Action의
   * `revalidatePath`가 맡으므로 여기서는 알림만 띄운다.
   */
  function confirmDelete(
    title: string,
    message: string,
    run: () => Promise<{ status: string; message?: string }>
  ) {
    showAlert({
      variant: 'danger',
      title,
      message,
      actions: (
        <>
          <FoxButton type="default" size="md" label="취소" onAction={hideAlert} />
          <FoxButton
            type="primary"
            size="md"
            label="삭제"
            onAction={() => {
              hideAlert();
              startDeleting(async () => {
                const result = await run();
                if (result.status === 'error') {
                  showToast({
                    variant: 'danger',
                    message: result.message ?? '삭제하지 못했습니다.',
                  });
                  return;
                }
                showToast({ variant: 'success', message: '삭제했습니다.' });
              });
            }}
          />
        </>
      ),
    });
  }

  const groupColumns: FoxListColumn<CommonCodeGroup>[] = [
    {
      key: 'no',
      header: '번호',
      width: 80,
      render: (_row, index) => (groupPage - 1) * COMMON_CODE_PAGE_SIZE + index + 1,
    },
    { key: 'comCd', header: '코드ID', width: 120 },
    { key: 'name', header: '코드명', width: 160, emphasis: true },
    {
      key: 'description',
      header: '코드설명',
      width: 156,
      render: (row) => <Truncated text={row.description} />,
    },
    {
      key: 'createdAt',
      header: '생성일',
      width: 120,
      render: (row) => formatOptionalText(row.createdAt),
    },
    {
      key: 'actions',
      header: '관리',
      width: 120,
      render: (row) => (
        <CodeRowActions
          target={row.comCd}
          deleting={isDeleting}
          onEdit={() => setModal({ kind: 'group-edit', group: row })}
          onDelete={() =>
            confirmDelete(
              '공통코드를 삭제하시겠습니까?',
              `${row.name}(${row.comCd})을(를) 삭제합니다. 속한 상세코드도 함께 쓸 수 없게 됩니다.`,
              () => deleteCodeGroupAction(row.comCd)
            )
          }
        />
      ),
    },
  ];

  const detailColumns: FoxListColumn<CommonCodeDetail>[] = [
    {
      key: 'no',
      header: '번호',
      width: 80,
      // 기획의 상세코드 목록은 이 자리에 정렬번호를 보여준다(FSC01→1, FSC10→10).
      render: (row) => row.sortSeq,
    },
    { key: 'comDtlCd', header: '상세코드ID', width: 120 },
    { key: 'name', header: '상세코드명', width: 120, emphasis: true },
    {
      key: 'description',
      header: '상세코드설명',
      width: 196,
      render: (row) => <Truncated text={row.description} />,
    },
    {
      key: 'createdAt',
      header: '생성일',
      width: 120,
      render: (row) => formatOptionalText(row.createdAt),
    },
    {
      key: 'actions',
      header: '관리',
      width: 120,
      render: (row) => (
        <CodeRowActions
          target={row.comDtlCd}
          deleting={isDeleting}
          onEdit={() => setModal({ kind: 'detail-edit', detail: row })}
          onDelete={() =>
            confirmDelete(
              '상세코드를 삭제하시겠습니까?',
              `${row.name}(${row.comDtlCd})을(를) 삭제합니다. 삭제 후에는 되돌릴 수 없습니다.`,
              () => deleteCodeDetailAction(row.comCd, row.comDtlCd)
            )
          }
        />
      ),
    },
  ];

  return (
    <div className={styles.page}>
      <FoxPageHeader
        title="코드관리"
        breadcrumb={[
          { label: '홈', href: '/' },
          { label: '시스템관리' },
          { label: '코드관리' },
        ]}
      />

      <div className={styles.columns}>
        <section className={styles.panel}>
          <FoxHeadingGroup title="공통코드 목록" />
          <FoxListContainer<CommonCodeGroup>
            caption="공통코드 목록"
            columns={groupColumns}
            rows={groups}
            rowKey={(row) => row.comCd}
            totalCount={groupTotalCount}
            emptyMessage="조회된 코드가 없습니다. 다른 검색어로 다시 시도해 주세요."
            searchFields={COMMON_CODE_SEARCH_FIELD_OPTIONS.map((option) => ({
              value: option.value,
              label: option.label,
            }))}
            searchField={query.searchField}
            keyword={query.keyword}
            toolbarActions={
              <FoxButton
                type="primary"
                size="md"
                leadingIcon={<i className="fox-ico fox-ico-Plus" aria-hidden="true" />}
                label="신규 등록"
                onAction={() => setModal({ kind: 'group-create' })}
              />
            }
            onRowSelect={(row) => go({ comCd: row.comCd })}
            page={groupPage}
            totalPages={groupTotalPages}
            buildHref={(patch) =>
              buildCommonCodeHref(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 CommonCodeSearchField,
                  // 검색하면 목록 자체가 달라지므로 선택도 첫 행으로 다시 잡게 비운다.
                  comCd: null,
                  page: 1,
                });
              }
            }}
          />
        </section>

        <section className={styles.panel}>
          <FoxHeadingGroup title="상세코드 목록" />
          <FoxListContainer<CommonCodeDetail>
            caption="상세코드 목록"
            columns={detailColumns}
            rows={details}
            rowKey={(row) => `${row.comCd}:${row.comDtlCd}`}
            totalCount={detailTotalCount}
            emptyMessage={
              selectedComCd
                ? '등록된 상세코드가 없습니다.'
                : '왼쪽에서 공통코드를 선택해 주세요.'
            }
            searchHidden
            toolbarActions={
              <FoxButton
                type="primary"
                size="md"
                leadingIcon={<i className="fox-ico fox-ico-Plus" aria-hidden="true" />}
                label="상세코드 등록"
                // 소속될 공통코드가 없으면 등록할 수 없다.
                disabled={!selectedComCd}
                onAction={() => setModal({ kind: 'detail-create' })}
              />
            }
            page={detailPage}
            totalPages={detailTotalPages}
            buildHref={(patch) =>
              buildCommonCodeHref(query, {
                comCd: selectedComCd,
                detailPage: Number(patch.page ?? 1),
              })
            }
          />
        </section>
      </div>

      {modal?.kind === 'group-create' && (
        <CodeGroupModal onClose={() => setModal(null)} />
      )}
      {modal?.kind === 'group-edit' && (
        <CodeGroupModal group={modal.group} onClose={() => setModal(null)} />
      )}
      {modal?.kind === 'detail-create' && selectedComCd && (
        <CodeDetailModal
          comCd={selectedComCd}
          nextSortSeq={nextSortSeq}
          onClose={() => setModal(null)}
        />
      )}
      {modal?.kind === 'detail-edit' && (
        <CodeDetailModal
          comCd={modal.detail.comCd}
          detail={modal.detail}
          nextSortSeq={nextSortSeq}
          onClose={() => setModal(null)}
        />
      )}
    </div>
  );
}
