'use client';

import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { FoxButton } from '@fox/core/components/fox-button';
import { FoxButtonGroup } from '@fox/core/components/fox-button-group';
import { FoxCheckbox } from '@fox/core/components/fox-checkbox';
import { FoxInput } from '@fox/core/components/fox-input';
import {
  FoxListContainer,
  type FoxListColumn,
} from '@fox/core/components/fox-list-container';
import { FoxSelect } from '@fox/core/components/fox-select';
import { FoxSelectText } from '@fox/core/components/fox-select-text';
import { FoxStatusIndicator } from '@fox/core/components/fox-status-indicator';
import { useBlockingAction } from '@/app/_hooks/use-blocking-action';
import { useFeedback } from '@/app/_hooks/use-feedback';
import { formatCommonCode, type CommonCode } from '@/lib/domain/common-code';
import {
  EMPTY_FIELD_PLACEHOLDER,
  MERCHANT_DETAIL_VISIBILITY_OPTIONS,
  formatMerchantDetailStatusLabel,
  formatOptionalValue,
  type MerchantDetailSummary,
} from '@/lib/domain/merchant-detail';
import {
  FILTER_ALL,
  MERCHANT_DETAILS_PATH,
  MERCHANT_DETAIL_NEW_PATH,
  MERCHANT_DETAIL_PAGE_SIZE_OPTIONS,
  buildMerchantDetailHref,
  clampDateRange,
  type MerchantDetailPageSize,
  type MerchantDetailQuery,
} from '@/lib/domain/merchant-detail-query';
import { formatPhoneNumber } from '@/lib/domain/phone-number';
import {
  deactivateMerchantDetailsAction,
  deleteMerchantDetailsAction,
} from '../_actions';
import { MerchantDetailRowActions } from './merchant-detail-row-actions';
import { MerchantThumbnail } from './merchant-thumbnail';
import styles from './merchant-detail-list.module.scss';

interface MerchantDetailListProps {
  items: MerchantDetailSummary[];
  categories: CommonCode[];
  query: MerchantDetailQuery;
  currentPage: number;
  totalPages: number;
  totalCount: number;
  /** 서버가 정한 오늘(YYYY-MM-DD). 여기서 계산하면 서버·브라우저 시간대 차이로 hydration이 어긋난다. */
  today: string;
}

/**
 * 가맹몰 상세 목록 — 기획 BO-MAL-001을 「관리자관리 > 가맹몰 상세 관리」로 옮긴 것.
 *
 * 가맹점 전체가 서고 상세가 없는 건은 상태·등록일이 `-`다(사용자 확정) — Repository가 가맹점 목록에
 * 상세를 덧입혀 준다. [+ 업체 등록]은 가맹점을 고르는 등록 화면으로, 행의 [수정]은 그 가맹점의
 * 상세 화면으로 간다(상세가 없으면 거기서 처음 만든다).
 *
 */
export function MerchantDetailList({
  items,
  categories,
  query,
  currentPage,
  totalPages,
  totalCount,
  today,
}: MerchantDetailListProps) {
  const router = useRouter();
  const { showAlert, hideAlert, showToast } = useFeedback();
  const [isBusy, startAction] = useBlockingAction();
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
  const [draft, setDraft] = useState({
    category: query.category,
    visibility: query.visibility,
    startDate: query.startDate,
    endDate: query.endDate,
  });

  const allIds = items.map((row) => row.id);
  const isAllSelected = allIds.length > 0 && allIds.every((id) => selectedIds.has(id));

  function go(patch: Partial<MerchantDetailQuery>) {
    router.replace(buildMerchantDetailHref(query, { ...patch, page: 1 }));
  }

  /** 업체명 검색은 검색 상자가 바로 반영하고, 나머지 필터는 [적용]을 눌러야 간다(사용자 확정). */
  function applyFilters() {
    go({ ...draft, ...clampDateRange(draft.startDate, draft.endDate, today) });
  }

  function toggleAll(checked: boolean) {
    setSelectedIds(checked ? new Set(allIds) : new Set());
  }

  /** 모든 필터를 비우고 첫 페이지로 — 초안과 URL을 함께 되돌린다. */
  function resetFilters() {
    setDraft({ category: FILTER_ALL, visibility: FILTER_ALL, startDate: '', endDate: '' });
    router.replace(MERCHANT_DETAILS_PATH);
  }

  function toggleOne(id: string, checked: boolean) {
    setSelectedIds((current) => {
      const next = new Set(current);
      if (checked) next.add(id);
      else next.delete(id);
      return next;
    });
  }

  function runBulk(
    run: (ids: string[]) => Promise<{ status: 'success' } | { status: 'error'; message: string }>,
    successMessage: string
  ) {
    hideAlert();
    const ids = items
      .filter((row) => selectedIds.has(row.id) && row.hasDetail)
      .map((row) => row.id);
    if (ids.length === 0) {
      showToast({ variant: 'warning', message: '상세가 등록된 행만 처리할 수 있습니다.' });
      return;
    }
    startAction(async () => {
      const result = await run(ids);
      showToast(
        result.status === 'error'
          ? { variant: 'danger', message: result.message }
          : { variant: 'success', message: successMessage }
      );
      if (result.status === 'success') setSelectedIds(new Set());
    });
  }

  const selectedDetailCount = items.filter(
    (row) => selectedIds.has(row.id) && row.hasDetail
  ).length;

  function confirmBulkDelete() {
    showAlert({
      variant: 'danger',
      title: '선택한 상세를 삭제하시겠습니까?',
      message: `${selectedDetailCount}건의 상세 정보를 삭제합니다. 삭제 후에는 되돌릴 수 없습니다.`,
      actions: (
        <FoxButtonGroup size="md">
          <FoxButton type="default" size="md" label="취소" onAction={hideAlert} />
          <FoxButton
            type="primary"
            size="md"
            label="삭제"
            onAction={() => runBulk(deleteMerchantDetailsAction, '삭제했습니다.')}
          />
        </FoxButtonGroup>
      ),
    });
  }

  const columns: FoxListColumn<MerchantDetailSummary>[] = [
    {
      key: 'select',
      header: (
        <FoxCheckbox
          size="md"
          label="전체 선택"
          hideLabel
          checked={isAllSelected}
          disabled={allIds.length === 0}
          onChange={toggleAll}
        />
      ),
      width: 56,
      align: 'center',
      render: (row) => (
        <FoxCheckbox
          size="md"
          label={`${row.name} 선택`}
          hideLabel
          checked={selectedIds.has(row.id)}
          onChange={(checked) => toggleOne(row.id, checked)}
        />
      ),
    },
    {
      key: 'no',
      header: 'No',
      width: 72,
      align: 'center',
      render: (_row, index) => (currentPage - 1) * query.pageSize + index + 1,
    },
    {
      key: 'thumbnail',
      header: '대표이미지',
      width: 140,
      align: 'center',
      render: (row) => (
        <MerchantThumbnail src={row.thumbnailUrl} alt={`${row.name} 대표이미지`} />
      ),
    },
    { key: 'name', header: '업체명', width: 220, emphasis: true },
    {
      key: 'category',
      header: '카테고리',
      width: 140,
      render: (row) =>
        row.categoryLabel ??
        (row.categoryCode ? formatCommonCode(categories, row.categoryCode) : EMPTY_FIELD_PLACEHOLDER),
    },
    {
      key: 'phoneNumber',
      header: '연락처',
      width: 150,
      render: (row) => formatOptionalValue(formatPhoneNumber(row.phoneNumber)),
    },
    {
      key: 'address',
      header: '주소',
      width: 280,
      render: (row) => formatOptionalValue(row.address),
    },
    {
      key: 'productCount',
      header: '메뉴',
      width: 72,
      align: 'center',
      render: (row) => (row.productCount === null ? EMPTY_FIELD_PLACEHOLDER : String(row.productCount)),
    },
    {
      key: 'status',
      header: '상태',
      width: 110,
      align: 'center',
      render: (row) =>
        row.hasDetail && row.isVisible !== null ? (
          <FoxStatusIndicator
            type={row.isVisible ? 'success' : 'danger'}
            label={formatMerchantDetailStatusLabel(row)}
          />
        ) : (
          formatMerchantDetailStatusLabel(row)
        ),
    },
    {
      key: 'registeredAt',
      header: '등록일',
      width: 120,
      align: 'center',
      render: (row) => formatOptionalValue(row.registeredAt),
    },
    {
      key: 'actions',
      header: '관리',
      width: 220,
      align: 'center',
      render: (row) => <MerchantDetailRowActions row={row} />,
    },
  ];

  return (
    <FoxListContainer<MerchantDetailSummary>
      title="가맹몰 상세 관리"
      description="지역상생몰(바우처 사용처)에 노출되는 업체를 등록·관리한다"
      breadcrumb={[
        { label: '홈', href: '/' },
        { label: '관리자관리' },
        { label: '가맹몰 상세 관리' },
      ]}
      caption="가맹몰 상세 목록"
      columns={columns}
      rows={items}
      rowKey={(row) => row.id}
      totalCount={totalCount}
      emptyMessage="검색 결과가 없습니다."
      sorts={
        <FoxSelectText
          size="sm"
          ariaLabel="페이지 크기"
          options={MERCHANT_DETAIL_PAGE_SIZE_OPTIONS.map((size) => ({
            value: String(size),
            label: `${size}개씩`,
          }))}
          value={String(query.pageSize)}
          onValueChange={(value) =>
            go({ pageSize: Number(value) as MerchantDetailPageSize })
          }
        />
      }
      filter={
        <div className={styles.filter}>
          <div className={styles.select}>
            <FoxSelect
              size="md"
              ariaLabel="카테고리"
              options={[
                { value: FILTER_ALL, label: '카테고리: 전체' },
                ...categories.map((code) => ({ value: code.code, label: code.label })),
              ]}
              value={draft.category}
              onValueChange={(value) => setDraft((current) => ({ ...current, category: value }))}
            />
          </div>
          <div className={styles.select}>
            <FoxSelect
              size="md"
              ariaLabel="노출 상태"
              options={[
                { value: FILTER_ALL, label: '노출 상태: 전체' },
                ...MERCHANT_DETAIL_VISIBILITY_OPTIONS.map((option) => ({
                  value: option.value,
                  label: option.label,
                })),
              ]}
              value={draft.visibility}
              onValueChange={(value) => setDraft((current) => ({ ...current, visibility: value }))}
            />
          </div>
          {/* 등록일 기간 — 백엔드가 조건에 쓰지 않아 Repository가 등록일로 거른다. */}
          <div className={styles.period}>
            <FoxInput
              size="md"
              type="date"
              aria-label="등록일 시작"
              max={today}
              value={draft.startDate}
              onChange={(value) =>
                setDraft((current) => ({ ...current, ...clampDateRange(value, current.endDate, today) }))
              }
            />
            <span aria-hidden="true">~</span>
            <FoxInput
              size="md"
              type="date"
              aria-label="등록일 종료"
              min={draft.startDate || undefined}
              value={draft.endDate}
              onChange={(value) =>
                setDraft((current) => ({ ...current, ...clampDateRange(current.startDate, value, today) }))
              }
            />
          </div>
          <FoxButtonGroup size="md">
            <FoxButton type="secondary" size="md" label="적용" onAction={applyFilters} />
            <FoxButton type="default" size="md" label="초기화" onAction={resetFilters} />
          </FoxButtonGroup>
        </div>
      }
      searchFields={[]}
      keyword={query.keyword}
      searchPlaceholder="업체명을 입력하세요."
      toolbarActions={
        <>
          <FoxButton
            type="default"
            size="md"
            label="선택 비활성"
            disabled={isBusy || selectedIds.size === 0}
            onAction={() => runBulk(deactivateMerchantDetailsAction, '비활성으로 바꿨습니다.')}
          />
          <FoxButton
            type="default"
            size="md"
            label="선택 삭제"
            disabled={isBusy || selectedIds.size === 0}
            onAction={confirmBulkDelete}
          />
          <FoxButton
            type="primary"
            size="md"
            leadingIcon={<i className="fox-ico fox-ico-Plus" aria-hidden="true" />}
            label="업체 등록"
            onAction={() => router.push(MERCHANT_DETAIL_NEW_PATH)}
          />
        </>
      }
      page={currentPage}
      totalPages={totalPages}
      buildHref={(patch) =>
        buildMerchantDetailHref(query, {
          ...(patch.keyword !== undefined ? { keyword: String(patch.keyword) } : {}),
          ...(patch.page !== undefined ? { page: patch.page } : {}),
        })
      }
    />
  );
}
