'use client';

/**
 * 입금관리 - UniversalListPage 마이그레이션
 *
 * 기존 IntegratedListTemplateV2 → UniversalListPage config 기반으로 변환
 * - 클라이언트 사이드 필터링 (검색, 필터, 정렬)
 * - Stats 카드 (단순 표시, 클릭 없음)
 * - beforeTableContent (계정과목명 Select + 저장 버튼 + 새로고침)
 * - tableHeaderActions (3개 인라인 필터: 거래처, 입금유형, 정렬)
 * - tableFooter (합계 행)
 * - 커스텀 Dialog (계정과목명 저장, 선택 필요 경고) - UniversalListPage 외부 유지
 * - deleteConfirmMessage로 삭제 다이얼로그 처리
 */

import { useState, useMemo, useCallback } from 'react';
import { useRouter } from 'next/navigation';
import {
  Banknote,
  Plus,
  Save,
  RefreshCw,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Badge } from '@/components/ui/badge';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { TableRow, TableCell } from '@/components/ui/table';
import {
  UniversalListPage,
  type UniversalListConfig,
  type SelectionHandlers,
  type RowClickHandlers,
  type StatCard,
} from '@/components/templates/UniversalListPage';
import { MobileCard } from '@/components/organisms/MobileCard';
import { AccountSubjectSelect } from '@/components/accounting/common';
import type {
  DepositRecord,
  SortOption,
} from './types';
import {
  SORT_OPTIONS,
  DEPOSIT_TYPE_LABELS,
  DEPOSIT_TYPE_FILTER_OPTIONS,
} from './types';
import { deleteDeposit, updateDepositTypes, getDeposits } from './actions';
import { formatNumber } from '@/lib/utils/amount';
import { applyFilters, textFilter, enumFilter } from '@/lib/utils/search';
import { toast } from 'sonner';
import { invalidateDashboard } from '@/lib/dashboard-invalidation';
import { useDateRange } from '@/hooks';
import {
  extractUniqueOptions,
  createDateAmountSortFn,
  computeMonthlyTotal,
  type SortDirection,
} from '../shared';

// ===== 테이블 컬럼 정의 =====
const tableColumns = [
  { key: 'depositDate', label: '입금일', sortable: true, copyable: true },
  { key: 'accountName', label: '입금계좌', sortable: true, copyable: true },
  { key: 'depositorName', label: '입금자명', sortable: true, copyable: true },
  { key: 'depositAmount', label: '입금금액', className: 'text-right', sortable: true, copyable: true },
  { key: 'vendorName', label: '거래처', sortable: true, copyable: true },
  { key: 'note', label: '적요', sortable: true, copyable: true },
  { key: 'depositType', label: '입금유형', className: 'text-center', sortable: true, copyable: true },
];

// ===== 컴포넌트 Props =====
interface DepositManagementProps {
  initialData: DepositRecord[];
  initialPagination: {
    currentPage: number;
    lastPage: number;
    perPage: number;
    total: number;
  };
}

export function DepositManagement({ initialData, initialPagination: _initialPagination }: DepositManagementProps) {
  const router = useRouter();

  // ===== 외부 상태 (UniversalListPage 외부에서 관리) =====
  const { startDate, endDate, setStartDate, setEndDate } = useDateRange('currentYear');
  const [depositData, setDepositData] = useState<DepositRecord[]>(initialData);
  const [isRefreshing, setIsRefreshing] = useState(false);
  const [searchQuery, setSearchQuery] = useState('');

  // 인라인 필터 상태 (tableHeaderActions에서 사용)
  const [vendorFilter, setVendorFilter] = useState<string>('all');
  const [depositTypeFilter, setDepositTypeFilter] = useState<string>('all');
  const [sortOption, setSortOption] = useState<SortOption>('latest');

  // 계정과목명 저장 다이얼로그
  const [selectedAccountSubject, setSelectedAccountSubject] = useState<string>('');
  const [showSaveDialog, setShowSaveDialog] = useState(false);
  const [selectedItemsForSave, setSelectedItemsForSave] = useState<Set<string>>(new Set());

  // 선택 필요 경고 다이얼로그
  const [showSelectWarningDialog, setShowSelectWarningDialog] = useState(false);

  // ===== 통계 계산 =====
  const stats = useMemo(() => {
    const totalDeposit = depositData.reduce((sum, d) => sum + (d.depositAmount ?? 0), 0);
    const monthlyDeposit = computeMonthlyTotal(depositData, 'depositDate', 'depositAmount');
    const vendorUnsetCount = depositData.filter(d => !d.vendorName).length;
    const depositTypeUnsetCount = depositData.filter(d => d.depositType === 'unset').length;
    return { totalDeposit, monthlyDeposit, vendorUnsetCount, depositTypeUnsetCount };
  }, [depositData]);

  // ===== 거래처 목록 (필터용) =====
  const vendorOptions = useMemo(
    () => extractUniqueOptions(depositData, 'vendorName'),
    [depositData]
  );

  // ===== 핸들러 =====
  const handleRowClick = useCallback((item: DepositRecord) => {
    router.push(`/ko/accounting/deposits/${item.id}?mode=view`);
  }, [router]);

  // 새로고침 핸들러
  const handleRefresh = useCallback(async () => {
    setIsRefreshing(true);
    try {
      const result = await getDeposits({
        perPage: 100,
        startDate,
        endDate,
        depositType: depositTypeFilter !== 'all' ? depositTypeFilter : undefined,
      });
      if (result.success) {
        setDepositData(result.data);
        toast.success('데이터를 새로고침했습니다.');
      } else {
        toast.error(result.error || '새로고침에 실패했습니다.');
      }
    } catch {
      toast.error('새로고침 중 오류가 발생했습니다.');
    } finally {
      setIsRefreshing(false);
    }
  }, [startDate, endDate, depositTypeFilter]);

  // 계정과목명 저장 핸들러
  const handleSaveAccountSubject = useCallback((selectedItems: Set<string>) => {
    if (selectedItems.size === 0) {
      setShowSelectWarningDialog(true);
      return;
    }
    setSelectedItemsForSave(selectedItems);
    setShowSaveDialog(true);
  }, []);

  const handleConfirmSaveAccountSubject = useCallback(async () => {
    const ids = Array.from(selectedItemsForSave);
    const result = await updateDepositTypes(ids, selectedAccountSubject);
    if (result.success) {
      toast.success('계정과목명이 저장되었습니다.');
      setDepositData(prev => prev.map(item =>
        selectedItemsForSave.has(item.id)
          ? { ...item, depositType: selectedAccountSubject as DepositRecord['depositType'] }
          : item
      ));
      setSelectedItemsForSave(new Set());
    } else {
      toast.error(result.error || '계정과목명 저장에 실패했습니다.');
    }
    setShowSaveDialog(false);
  }, [selectedAccountSubject, selectedItemsForSave]);

  // ===== 테이블 합계 계산 =====
  const tableTotals = useMemo(() => {
    const totalAmount = depositData.reduce((sum, item) => sum + (item.depositAmount ?? 0), 0);
    return { totalAmount };
  }, [depositData]);

  // ===== UniversalListPage Config =====
  const config: UniversalListConfig<DepositRecord> = useMemo(
    () => ({
      // 페이지 기본 정보
      title: '입금관리',
      description: '입금 내역을 등록합니다',
      icon: Banknote,
      basePath: '/accounting/deposits',

      // ID 추출
      idField: 'id',

      // API 액션
      actions: {
        getList: async () => {
          return {
            success: true,
            data: initialData,
            totalCount: initialData.length,
          };
        },
        deleteItem: async (id: string) => {
          const result = await deleteDeposit(id);
          if (result.success) {
            invalidateDashboard('deposit');
            toast.success('입금 내역이 삭제되었습니다.');
            // 서버에서 재조회 (로컬 필터링 대신 - 페이지네이션 정합성 보장)
            await handleRefresh();
          }
          return { success: result.success, error: result.error };
        },
      },

      // 테이블 컬럼
      columns: tableColumns,

      // 클라이언트 사이드 필터링
      clientSideFiltering: true,
      itemsPerPage: 20,

      // 데이터 변경 콜백
      onDataChange: (data) => setDepositData(data),

      // 검색 필터
      searchPlaceholder: '입금자명, 계좌명, 적요, 거래처 검색...',
      searchFilter: (item, searchValue) => {
        const search = searchValue.toLowerCase();
        return (
          item.depositorName.toLowerCase().includes(search) ||
          item.accountName.toLowerCase().includes(search) ||
          (item.note?.toLowerCase().includes(search) || false) ||
          (item.vendorName?.toLowerCase().includes(search) || false)
        );
      },

      // 커스텀 필터 함수
      customFilterFn: (items) => {
        if (!items || items.length === 0) return items;
        return applyFilters(items, [
          textFilter(searchQuery, ['depositorName', 'accountName', 'note', 'vendorName']),
          enumFilter('vendorName', vendorFilter),
          enumFilter('depositType', depositTypeFilter),
        ]);
      },

      // 커스텀 정렬 함수
      customSortFn: (items) =>
        createDateAmountSortFn<DepositRecord>('depositDate', 'depositAmount', sortOption as SortDirection)(items),

      // 검색창 (공통 컴포넌트에서 자동 생성)
      hideSearch: true,
      searchValue: searchQuery,
      onSearchChange: setSearchQuery,

      // 공통 헤더 옵션
      dateRangeSelector: {
        enabled: true,
        showPresets: true,
        startDate,
        endDate,
        onStartDateChange: setStartDate,
        onEndDateChange: setEndDate,
      },

      // 필터 설정
      filterConfig: [
        {
          key: 'vendor',
          label: '거래처',
          type: 'single',
          options: vendorOptions.filter(o => o.value !== 'all'),
        },
        {
          key: 'depositType',
          label: '입금유형',
          type: 'single',
          options: DEPOSIT_TYPE_FILTER_OPTIONS.filter(o => o.value !== 'all'),
        },
        {
          key: 'sortBy',
          label: '정렬',
          type: 'single',
          options: SORT_OPTIONS,
        },
      ],
      initialFilters: {
        vendor: vendorFilter,
        depositType: depositTypeFilter,
        sortBy: sortOption,
      },
      filterTitle: '입금 필터',

      // 헤더 액션: 계정과목명 검색 Select + 저장 + 새로고침
      headerActions: ({ selectedItems }) => (
        <div className="flex items-center gap-2">
          <span className="text-sm font-medium text-gray-700 whitespace-nowrap">계정과목명</span>
          <AccountSubjectSelect
            value={selectedAccountSubject}
            onValueChange={setSelectedAccountSubject}
            placeholder="계정과목 선택"
            size="sm"
            className="min-w-[180px] w-auto"
          />
          <Button onClick={() => handleSaveAccountSubject(selectedItems)} size="sm">
            <Save className="h-4 w-4 mr-1" />
            저장
          </Button>
          <Button
            variant="outline"
            size="sm"
            onClick={handleRefresh}
            disabled={isRefreshing}
          >
            <RefreshCw className={`h-4 w-4 mr-1 ${isRefreshing ? 'animate-spin' : ''}`} />
            {isRefreshing ? '조회중...' : '새로고침'}
          </Button>
        </div>
      ),

      // 등록 버튼
      createButton: {
        label: '입금등록',
        icon: Plus,
        onClick: () => router.push('/ko/accounting/deposits?mode=new'),
      },

      // Stats 카드
      computeStats: (): StatCard[] => [
        { label: '총 입금', value: `${formatNumber(stats.totalDeposit)}원`, icon: Banknote, iconColor: 'text-blue-500' },
        { label: '당월 입금', value: `${formatNumber(stats.monthlyDeposit)}원`, icon: Banknote, iconColor: 'text-green-500' },
        { label: '거래처 미설정', value: `${stats.vendorUnsetCount}건`, icon: Banknote, iconColor: 'text-orange-500' },
        { label: '입금유형 미설정', value: `${stats.depositTypeUnsetCount}건`, icon: Banknote, iconColor: 'text-red-500' },
      ],


      // 테이블 하단 합계 행
      tableFooter: (
        <TableRow className="bg-muted/50 font-medium">
          <TableCell className="text-center"></TableCell>
          <TableCell className="font-bold">합계</TableCell>
          <TableCell></TableCell>
          <TableCell></TableCell>
          <TableCell className="text-right font-bold">{formatNumber(tableTotals.totalAmount)}</TableCell>
          <TableCell></TableCell>
          <TableCell></TableCell>
          <TableCell></TableCell>
        </TableRow>
      ),

      // 삭제 확인 메시지
      deleteConfirmMessage: {
        title: '입금 삭제',
        description: '이 입금 내역을 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.',
      },

      // 테이블 행 렌더링
      renderTableRow: (
        item: DepositRecord,
        index: number,
        globalIndex: number,
        handlers: SelectionHandlers & RowClickHandlers<DepositRecord>
      ) => {
        const isVendorUnset = !item.vendorName;
        const isDepositTypeUnset = item.depositType === 'unset';
        return (
          <TableRow
            key={item.id}
            className="hover:bg-muted/50 cursor-pointer"
            onClick={() => handleRowClick(item)}
          >
            <TableCell className="text-center" onClick={(e) => e.stopPropagation()}>
              <Checkbox checked={handlers.isSelected} onCheckedChange={handlers.onToggle} />
            </TableCell>
            <TableCell>{item.depositDate}</TableCell>
            <TableCell>{item.accountName}</TableCell>
            <TableCell>{item.depositorName}</TableCell>
            <TableCell className="text-right font-medium">{formatNumber(item.depositAmount ?? 0)}</TableCell>
            <TableCell className={isVendorUnset ? 'text-red-500 font-medium' : ''}>
              {item.vendorName || '미설정'}
            </TableCell>
            <TableCell className="text-gray-500">{item.note || '-'}</TableCell>
            <TableCell className="text-center">
              <Badge
                variant="outline"
                className={isDepositTypeUnset ? 'border-red-300 text-red-500 bg-red-50' : ''}
              >
                {DEPOSIT_TYPE_LABELS[item.depositType]}
              </Badge>
            </TableCell>
          </TableRow>
        );
      },

      // 모바일 카드 렌더링
      renderMobileCard: (
        item: DepositRecord,
        index: number,
        globalIndex: number,
        handlers: SelectionHandlers & RowClickHandlers<DepositRecord>
      ) => (
        <MobileCard
          key={item.id}
          title={item.depositorName}
          subtitle={item.accountName}
          badge={DEPOSIT_TYPE_LABELS[item.depositType]}
          badgeVariant="outline"
          isSelected={handlers.isSelected}
          onToggle={handlers.onToggle}
          onClick={() => handleRowClick(item)}
          details={[
            { label: '입금일', value: item.depositDate },
            { label: '입금액', value: `${formatNumber(item.depositAmount ?? 0)}원` },
            { label: '거래처', value: item.vendorName || '-' },
          ]}
        />
      ),
    }),
    [
      initialData,
      startDate,
      endDate,
      stats,
      vendorFilter,
      depositTypeFilter,
      sortOption,
      selectedAccountSubject,
      vendorOptions,
      tableTotals,
      isRefreshing,
      searchQuery,
      handleRowClick,
      handleRefresh,
      handleSaveAccountSubject,
    ]
  );

  return (
    <>
      <UniversalListPage
        config={config}
        initialData={initialData}
        onFilterChange={(filters) => {
          if (filters.vendor !== undefined) setVendorFilter(filters.vendor as string);
          if (filters.depositType !== undefined) setDepositTypeFilter(filters.depositType as string);
          if (filters.sortBy !== undefined) setSortOption(filters.sortBy as SortOption);
        }}
      />

      {/* 계정과목명 저장 확인 다이얼로그 */}
      <Dialog open={showSaveDialog} onOpenChange={setShowSaveDialog}>
        <DialogContent className="sm:max-w-[425px]">
          <DialogHeader>
            <DialogTitle>계정과목명 변경</DialogTitle>
            <DialogDescription>
              {selectedItemsForSave.size}개의 입금 유형을 선택한 계정과목으로 모두 변경하시겠습니까?
            </DialogDescription>
          </DialogHeader>
          <DialogFooter className="gap-3">
            <Button variant="outline" onClick={() => setShowSaveDialog(false)}>
              취소
            </Button>
            <Button
              onClick={handleConfirmSaveAccountSubject}
              className="bg-blue-500 hover:bg-blue-600"
            >
              확인
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 선택 필요 알림 다이얼로그 */}
      <AlertDialog open={showSelectWarningDialog} onOpenChange={setShowSelectWarningDialog}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>항목 선택 필요</AlertDialogTitle>
            <AlertDialogDescription>
              변경할 입금 항목을 먼저 선택해주세요.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogAction onClick={() => setShowSelectWarningDialog(false)}>
              확인
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </>
  );
}
