'use client';

import { useState, useEffect, useCallback, useMemo } from 'react';
import { format } from 'date-fns';
import { formatNumber } from '@/lib/utils/amount';
import { Loader2, RotateCcw } from 'lucide-react';
import { toast } from 'sonner';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Badge } from '@/components/ui/badge';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { DatePicker } from '@/components/ui/date-picker';
import { TimePicker } from '@/components/ui/time-picker';
import type { BankTransaction, TransactionKind, TransactionFormData } from './types';
import {
  createManualTransaction,
  updateTransaction,
  deleteTransaction,
  restoreTransaction,
} from './actions';

// ===== Props =====
interface TransactionFormModalProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  mode: 'create' | 'edit';
  transaction?: BankTransaction | null;
  accountOptions: { id: number; label: string }[];
  onSuccess: () => void;
}

// ===== 시간 포맷 변환 (API: HHMMSS ↔ TimePicker: HH:mm:ss) =====
function apiTimeToPickerFormat(hhmmss: string): string {
  if (!hhmmss) return '';
  const clean = hhmmss.replace(/[^0-9]/g, '');
  if (clean.length < 4) return '';
  const h = clean.slice(0, 2);
  const m = clean.slice(2, 4);
  const s = clean.slice(4, 6) || '00';
  return `${h}:${m}:${s}`;
}

function pickerTimeToApiFormat(hhmm_ss: string): string {
  if (!hhmm_ss) return '';
  return hhmm_ss.replace(/:/g, '');
}

// ===== 초기 폼 데이터 =====
function getInitialFormData(transaction?: BankTransaction | null): TransactionFormData {
  if (transaction) {
    const amount = transaction.type === 'deposit'
      ? transaction.depositAmount
      : transaction.withdrawalAmount;
    return {
      bankAccountId: transaction.bankAccountId ?? null,
      transactionDate: transaction.transactionDate?.split(' ')[0] || format(new Date(), 'yyyy-MM-dd'),
      transactionTime: apiTimeToPickerFormat(transaction.transactionTime || ''),
      type: transaction.type,
      amount,
      note: transaction.note || '',
      depositorName: transaction.depositorName || '',
      memo: transaction.memo || '',
      branch: transaction.branch || '',
    };
  }
  return {
    bankAccountId: null,
    transactionDate: format(new Date(), 'yyyy-MM-dd'),
    transactionTime: '',
    type: 'deposit',
    amount: 0,
    note: '',
    depositorName: '',
    memo: '',
    branch: '',
  };
}

export function TransactionFormModal({
  open,
  onOpenChange,
  mode,
  transaction,
  accountOptions,
  onSuccess,
}: TransactionFormModalProps) {
  const [formData, setFormData] = useState<TransactionFormData>(() =>
    getInitialFormData(transaction)
  );
  const [isSaving, setIsSaving] = useState(false);
  const [isDeleting, setIsDeleting] = useState(false);
  const [isRestoring, setIsRestoring] = useState(false);

  // 원본 데이터 (수정 감지용)
  const [originalFormData, setOriginalFormData] = useState<TransactionFormData>(() =>
    getInitialFormData(transaction)
  );

  // transaction 변경 시 폼 데이터 리셋
  useEffect(() => {
    if (open) {
      const data = getInitialFormData(transaction);
      setFormData(data);
      setOriginalFormData(data);
    }
  }, [open, transaction]);

  // 수정된 필드 감지
  const modifiedFields = useMemo(() => {
    if (mode === 'create') return [];
    const fields: string[] = [];
    const keys: (keyof TransactionFormData)[] = [
      'bankAccountId', 'transactionDate', 'transactionTime', 'type',
      'amount', 'note', 'depositorName', 'memo', 'branch',
    ];
    for (const key of keys) {
      if (String(formData[key]) !== String(originalFormData[key])) {
        fields.push(key);
      }
    }
    return fields;
  }, [formData, originalFormData, mode]);

  const isFieldModified = useCallback(
    (field: keyof TransactionFormData) => modifiedFields.includes(field),
    [modifiedFields]
  );

  // 필드 변경 핸들러
  const handleChange = useCallback(
    <K extends keyof TransactionFormData>(key: K, value: TransactionFormData[K]) => {
      setFormData((prev) => ({ ...prev, [key]: value }));
    },
    []
  );

  // 잔액 자동계산 (표시용)
  const calculatedBalance = useMemo(() => {
    if (!transaction) return formData.amount;
    const prevBalance = transaction.balance;
    if (formData.type === 'deposit') {
      return prevBalance + formData.amount;
    }
    return prevBalance - formData.amount;
  }, [formData.amount, formData.type, transaction]);

  // 저장/수정
  const handleSubmit = useCallback(async () => {
    if (!formData.bankAccountId) {
      toast.error('계좌를 선택해주세요.');
      return;
    }
    if (!formData.transactionDate) {
      toast.error('거래일을 입력해주세요.');
      return;
    }
    if (formData.amount <= 0) {
      toast.error('금액을 입력해주세요.');
      return;
    }

    setIsSaving(true);
    try {
      // TimePicker HH:mm:ss → API HHMMSS 변환
      const apiFormData = {
        ...formData,
        transactionTime: pickerTimeToApiFormat(formData.transactionTime),
      };

      if (mode === 'create') {
        const result = await createManualTransaction(apiFormData);
        if (result.success) {
          toast.success('수기 입력이 완료되었습니다.');
          onOpenChange(false);
          onSuccess();
        } else {
          toast.error(result.error || '수기 입력에 실패했습니다.');
        }
      } else if (transaction) {
        const result = await updateTransaction(transaction.sourceId, apiFormData);
        if (result.success) {
          toast.success('수정이 완료되었습니다.');
          onOpenChange(false);
          onSuccess();
        } else {
          toast.error(result.error || '수정에 실패했습니다.');
        }
      }
    } catch {
      toast.error('처리 중 오류가 발생했습니다.');
    } finally {
      setIsSaving(false);
    }
  }, [formData, mode, transaction, onOpenChange, onSuccess]);

  // 삭제
  const handleDelete = useCallback(async () => {
    if (!transaction) return;
    setIsDeleting(true);
    try {
      const result = await deleteTransaction(transaction.sourceId);
      if (result.success) {
        toast.success('삭제가 완료되었습니다.');
        onOpenChange(false);
        onSuccess();
      } else {
        toast.error(result.error || '삭제에 실패했습니다.');
      }
    } catch {
      toast.error('삭제 중 오류가 발생했습니다.');
    } finally {
      setIsDeleting(false);
    }
  }, [transaction, onOpenChange, onSuccess]);

  // 원본으로 복원 (③)
  const handleRestore = useCallback(async () => {
    if (!transaction) return;
    setIsRestoring(true);
    try {
      const result = await restoreTransaction(transaction.sourceId);
      if (result.success) {
        toast.success('원본으로 복원되었습니다.');
        onOpenChange(false);
        onSuccess();
      } else {
        toast.error(result.error || '복원에 실패했습니다.');
      }
    } catch {
      toast.error('복원 중 오류가 발생했습니다.');
    } finally {
      setIsRestoring(false);
    }
  }, [transaction, onOpenChange, onSuccess]);

  const isProcessing = isSaving || isDeleting || isRestoring;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[560px] max-h-[90vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle>입출금 수기 입력</DialogTitle>
        </DialogHeader>

        <div className="space-y-5 py-2">
          {/* 계좌 * (①) */}
          <div className="space-y-2">
            <Label className="font-medium">
              계좌 <span className="text-red-500">*</span>
            </Label>
            <Select
              key={`account-${formData.bankAccountId}`}
              value={formData.bankAccountId ? String(formData.bankAccountId) : ''}
              onValueChange={(v) => handleChange('bankAccountId', parseInt(v, 10))}
            >
              <SelectTrigger>
                <SelectValue placeholder="계좌를 선택하세요" />
              </SelectTrigger>
              <SelectContent>
                {accountOptions.map((opt) => (
                  <SelectItem key={opt.id} value={String(opt.id)}>
                    {opt.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          {/* 거래일 * / 거래시간 */}
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label className="font-medium">
                거래일 <span className="text-red-500">*</span>
              </Label>
              <DatePicker
                value={formData.transactionDate}
                onChange={(date) => handleChange('transactionDate', date)}
                placeholder="날짜 선택"
              />
            </div>
            <div className="space-y-2">
              <Label className="font-medium">거래시간</Label>
              <TimePicker
                value={formData.transactionTime || undefined}
                onChange={(time) => handleChange('transactionTime', time)}
                placeholder="시간 선택"
                showSeconds
                secondStep={1}
                minuteStep={1}
              />
            </div>
          </div>

          {/* 거래유형 * */}
          <div className="space-y-2">
            <Label className="font-medium">
              거래유형 <span className="text-red-500">*</span>
            </Label>
            <RadioGroup
              value={formData.type}
              onValueChange={(v) => handleChange('type', v as TransactionKind)}
              className="flex gap-6"
            >
              <div className="flex items-center gap-2">
                <RadioGroupItem value="deposit" id="type-deposit" />
                <Label htmlFor="type-deposit" className="cursor-pointer">입금</Label>
              </div>
              <div className="flex items-center gap-2">
                <RadioGroupItem value="withdrawal" id="type-withdrawal" />
                <Label htmlFor="type-withdrawal" className="cursor-pointer">출금</Label>
              </div>
            </RadioGroup>
          </div>

          {/* 금액 * / 잔액 (자동계산) */}
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label className="font-medium">
                금액 <span className="text-red-500">*</span>
              </Label>
              <Input
                type="text"
                inputMode="numeric"
                value={formData.amount ? formatNumber(formData.amount) : ''}
                onChange={(e) => {
                  const raw = e.target.value.replace(/[^0-9]/g, '');
                  handleChange('amount', raw ? parseInt(raw, 10) : 0);
                }}
              />
            </div>
            <div className="space-y-2">
              <Label className="font-medium text-gray-500">잔액 (자동계산)</Label>
              <Input
                value={formatNumber(calculatedBalance)}
                disabled
                className="bg-gray-50"
              />
            </div>
          </div>

          {/* 적요 + 수정 스티커 (②) */}
          <div className="space-y-2">
            <div className="flex items-center gap-2">
              <Label className="font-medium">적요</Label>
              {mode === 'edit' && isFieldModified('note') && (
                <Badge variant="outline" className="bg-green-50 text-green-700 border-green-300 text-xs">
                  수정
                </Badge>
              )}
            </div>
            <Input
              value={formData.note}
              onChange={(e) => handleChange('note', e.target.value)}
              placeholder="내용"
            />
          </div>

          {/* 상대계좌 예금주명 */}
          <div className="space-y-2">
            <Label className="font-medium">상대계좌 예금주명</Label>
            <Input
              value={formData.depositorName}
              onChange={(e) => handleChange('depositorName', e.target.value)}
              placeholder="예금주명"
            />
          </div>

          {/* 메모 */}
          <div className="space-y-2">
            <Label className="font-medium">메모</Label>
            <Input
              value={formData.memo}
              onChange={(e) => handleChange('memo', e.target.value)}
            />
          </div>

          {/* 취급점 */}
          <div className="space-y-2">
            <Label className="font-medium">취급점</Label>
            <Input
              value={formData.branch}
              onChange={(e) => handleChange('branch', e.target.value)}
            />
          </div>
        </div>

        {/* 하단 버튼 */}
        <div className="flex flex-col gap-2 pt-4 border-t">
          {/* 삭제 + 수정/등록 (50:50) */}
          <div className="flex gap-2">
            {mode === 'edit' && (
              <Button
                variant="outline"
                onClick={handleDelete}
                disabled={isProcessing}
                className="flex-1"
              >
                {isDeleting ? <Loader2 className="h-4 w-4 mr-1 animate-spin" /> : null}
                삭제
              </Button>
            )}
            <Button
              onClick={handleSubmit}
              disabled={isProcessing}
              className="flex-1"
            >
              {isSaving ? <Loader2 className="h-4 w-4 mr-1 animate-spin" /> : null}
              {mode === 'create' ? '등록' : '수정'}
            </Button>
          </div>

          {/* 원본으로 복원 (100%) - 수정 모드에서만 */}
          {mode === 'edit' && (
            <Button
              variant="outline"
              onClick={handleRestore}
              disabled={isProcessing}
              className="w-full gap-1"
            >
              {isRestoring ? (
                <Loader2 className="h-4 w-4 animate-spin" />
              ) : (
                <RotateCcw className="h-4 w-4" />
              )}
              원본으로 복원
            </Button>
          )}
        </div>
      </DialogContent>
    </Dialog>
  );
}
