'use client';

/**
 * 출금관리 - UniversalListPage 마이그레이션
 *
 * 기존 IntegratedListTemplateV2 → UniversalListPage config 기반으로 변환
 * - 클라이언트 사이드 필터링 (검색, 필터, 정렬)
 * - Stats 카드 (총 출금, 당월 출금, 거래처 미설정, 출금유형 미설정)
 * - DateRangeSelector + beforeTableContent (계정과목명 + 저장 + 새로고침)
 * - tableHeaderActions (거래처, 출금유형, 정렬)
 * - tableFooter (합계)
 * - 삭제 기능 (deleteConfirmMessage)
 */

import { useState, useMemo, useCallback } from 'react';
import { useRouter } from 'next/navigation';
import {
  Banknote,
  Pencil,
  Plus,
  Save,
  Trash2,
  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 {
  WithdrawalRecord,
  SortOption,
} from './types';
import {
  SORT_OPTIONS,
  WITHDRAWAL_TYPE_LABELS,
  WITHDRAWAL_TYPE_FILTER_OPTIONS,
} from './types';
import { deleteWithdrawal, updateWithdrawalTypes, getWithdrawals } 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: 'withdrawalDate', label: '출금일', className: 'w-[100px]', sortable: true, copyable: true },
  { key: 'accountName', label: '출금계좌', className: 'min-w-[120px]', sortable: true, copyable: true },
  { key: 'recipientName', label: '수취인명', className: 'min-w-[100px]', sortable: true, copyable: true },
  { key: 'withdrawalAmount', label: '출금금액', className: 'text-right w-[110px]', sortable: true, copyable: true },
  { key: 'vendorName', label: '거래처', className: 'min-w-[100px]', sortable: true, copyable: true },
  { key: 'note', label: '적요', className: 'min-w-[150px]', sortable: true, copyable: true },
  { key: 'withdrawalType', label: '출금유형', className: 'text-center w-[90px]', sortable: true, copyable: true },
];

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

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

  // ===== 외부 상태 (UniversalListPage 외부에서 관리) =====
  const [withdrawalData, setWithdrawalData] = useState<WithdrawalRecord[]>(initialData);

  // 날짜 범위
  const { startDate, endDate, setStartDate, setEndDate } = useDateRange('currentYear');

  // 인라인 필터 상태
  const [vendorFilter, setVendorFilter] = useState<string>('all');
  const [withdrawalTypeFilter, setWithdrawalTypeFilter] = useState<string>('all');
  const [sortOption, setSortOption] = useState<SortOption>('latest');

  // 상단 계정과목명 선택 (저장용)
  const [selectedAccountSubject, setSelectedAccountSubject] = useState<string>('');

  // 검색어 상태 (헤더에서 직접 관리)
  const [searchQuery, setSearchQuery] = useState('');

  // 로딩 상태
  const [isRefreshing, setIsRefreshing] = useState(false);

  // 다이얼로그 상태
  const [showSaveDialog, setShowSaveDialog] = useState(false);
  const [saveTargetIds, setSaveTargetIds] = useState<string[]>([]);
  const [showSelectWarningDialog, setShowSelectWarningDialog] = useState(false);

  // ===== Stats 계산 =====
  const stats = useMemo(() => {
    const totalWithdrawal = withdrawalData.reduce((sum, d) => sum + (d.withdrawalAmount ?? 0), 0);
    const monthlyWithdrawal = computeMonthlyTotal(withdrawalData, 'withdrawalDate', 'withdrawalAmount');

    // 거래처 미설정 건수
    const vendorUnsetCount = withdrawalData.filter(d => !d.vendorName).length;

    // 출금유형 미설정 건수
    const withdrawalTypeUnsetCount = withdrawalData.filter(d => d.withdrawalType === 'unset').length;

    return { totalWithdrawal, monthlyWithdrawal, vendorUnsetCount, withdrawalTypeUnsetCount };
  }, [withdrawalData]);

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

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

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

  const handleEdit = useCallback((item: WithdrawalRecord) => {
    router.push(`/ko/accounting/withdrawals/${item.id}?mode=edit`);
  }, [router]);

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

  // 계정과목명 저장 핸들러
  const handleSaveAccountSubject = useCallback((selectedItems: WithdrawalRecord[]) => {
    if (selectedItems.length === 0) {
      setShowSelectWarningDialog(true);
      return;
    }
    setSaveTargetIds(selectedItems.map(item => item.id));
    setShowSaveDialog(true);
  }, []);

  // 계정과목명 저장 확정
  const handleConfirmSaveAccountSubject = useCallback(async () => {
    const result = await updateWithdrawalTypes(saveTargetIds, selectedAccountSubject);
    if (result.success) {
      toast.success('계정과목명이 저장되었습니다.');
      setWithdrawalData(prev => prev.map(item =>
        saveTargetIds.includes(item.id)
          ? { ...item, withdrawalType: selectedAccountSubject as WithdrawalRecord['withdrawalType'] }
          : item
      ));
    } else {
      toast.error(result.error || '계정과목명 저장에 실패했습니다.');
    }
    setShowSaveDialog(false);
    setSaveTargetIds([]);
  }, [selectedAccountSubject, saveTargetIds]);

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

      // ID 추출
      idField: 'id',

      // API 액션
      actions: {
        getList: async () => {
          return {
            success: true,
            data: initialData,
            totalCount: initialData.length,
          };
        },
        deleteItem: async (id: string) => {
          const result = await deleteWithdrawal(id);
          if (result.success) {
            setWithdrawalData(prev => prev.filter(item => item.id !== id));
            invalidateDashboard('withdrawal');
            toast.success('출금 내역이 삭제되었습니다.');
          }
          return { success: result.success, error: result.error };
        },
      },

      // 테이블 컬럼
      columns: tableColumns,

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

      // 데이터 변경 콜백 (Stats 계산용)
      onDataChange: (data) => setWithdrawalData(data),

      // 검색 필터
      searchPlaceholder: '수취인명, 계좌명, 적요, 거래처 검색...',
      searchFilter: (item, searchValue) => {
        const search = searchValue.toLowerCase();
        return (
          item.recipientName.toLowerCase().includes(search) ||
          item.accountName.toLowerCase().includes(search) ||
          item.note.toLowerCase().includes(search) ||
          item.vendorName.toLowerCase().includes(search)
        );
      },

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

      // 검색창 숨김 (dateRangeSelector extraActions로 렌더링)
      hideSearch: true,

      // 커스텀 필터 함수
      customFilterFn: (items) => {
        return applyFilters(items, [
          textFilter(searchQuery, ['recipientName', 'accountName', 'note', 'vendorName']),
          enumFilter('vendorName', vendorFilter),
          enumFilter('withdrawalType', withdrawalTypeFilter),
        ]);
      },

      // 커스텀 정렬 함수
      customSortFn: (items) =>
        createDateAmountSortFn<WithdrawalRecord>('withdrawalDate', 'withdrawalAmount', sortOption as SortDirection)(items),

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

      // 날짜 범위 선택기 (달력 | 프리셋버튼 | 검색창(자동) - 한 줄)
      dateRangeSelector: {
        enabled: true,
        showPresets: true,
        startDate,
        endDate,
        onStartDateChange: setStartDate,
        onEndDateChange: setEndDate,
      },

      // 헤더 액션: 계정과목명 검색 Select + 저장 + 새로고침
      headerActions: ({ selectedItems }) => {
        const selectedArray = withdrawalData.filter(item => selectedItems.has(item.id));
        return (
          <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(selectedArray)} 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/withdrawals?mode=new'),
      },


      // tableFooter: 합계 행
      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>
      ),

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

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

      // 테이블 행 렌더링
      renderTableRow: (
        item: WithdrawalRecord,
        index: number,
        globalIndex: number,
        handlers: SelectionHandlers & RowClickHandlers<WithdrawalRecord>
      ) => {
        const isVendorUnset = !item.vendorName;
        const isWithdrawalTypeUnset = item.withdrawalType === '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.withdrawalDate}</TableCell>
            {/* 출금계좌 */}
            <TableCell>{item.accountName}</TableCell>
            {/* 수취인명 */}
            <TableCell>{item.recipientName}</TableCell>
            {/* 출금금액 */}
            <TableCell className="text-right font-medium">{formatNumber(item.withdrawalAmount ?? 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={isWithdrawalTypeUnset ? 'border-red-300 text-red-500 bg-red-50' : ''}
              >
                {WITHDRAWAL_TYPE_LABELS[item.withdrawalType]}
              </Badge>
            </TableCell>
          </TableRow>
        );
      },

      // 모바일 카드 렌더링
      renderMobileCard: (
        item: WithdrawalRecord,
        index: number,
        globalIndex: number,
        handlers: SelectionHandlers & RowClickHandlers<WithdrawalRecord>
      ) => (
        <MobileCard
          key={item.id}
          title={item.recipientName}
          subtitle={item.accountName}
          badge={WITHDRAWAL_TYPE_LABELS[item.withdrawalType]}
          badgeVariant="outline"
          isSelected={handlers.isSelected}
          onToggle={handlers.onToggle}
          onClick={() => handleRowClick(item)}
          details={[
            { label: '출금일', value: item.withdrawalDate || '-' },
            { label: '출금액', value: `${formatNumber(item.withdrawalAmount ?? 0)}원` },
            { label: '거래처', value: item.vendorName || '-' },
            { label: '적요', value: item.note || '-' },
          ]}
          actions={
            handlers.isSelected ? (
              <div className="flex gap-2 w-full">
                <Button variant="outline" className="flex-1" onClick={() => handleEdit(item)}>
                  <Pencil className="w-4 h-4 mr-2" /> 수정
                </Button>
                <Button
                  variant="outline"
                  className="flex-1 text-red-500 border-red-200 hover:bg-red-50 hover:text-red-600"
                  onClick={() => handlers.onDelete?.(item)}
                >
                  <Trash2 className="w-4 h-4 mr-2" /> 삭제
                </Button>
              </div>
            ) : undefined
          }
        />
      ),
    }),
    [
      initialData,
      withdrawalData,
      stats,
      startDate,
      endDate,
      searchQuery,
      vendorFilter,
      withdrawalTypeFilter,
      sortOption,
      selectedAccountSubject,
      isRefreshing,
      vendorOptions,
      tableTotals,
      handleRowClick,
      handleEdit,
      handleRefresh,
      handleSaveAccountSubject,
    ]
  );

  return (
    <>
      <UniversalListPage
        config={config}
        initialData={initialData}
        onFilterChange={(filters) => {
          if (filters.vendor !== undefined) setVendorFilter(filters.vendor as string);
          if (filters.withdrawalType !== undefined) setWithdrawalTypeFilter(filters.withdrawalType 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>
              {saveTargetIds.length}개의 출금 유형을 선택한 계정과목으로 모두 변경하시겠습니까?
            </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>
    </>
  );
}
