'use client';

/**
 * 수기 전표 입력 팝업
 *
 * - 거래 정보: 전표일자*(필수), 전표번호(자동생성, 읽기전용), 적요 Input
 * - 분개 내역 테이블: 구분(차변/대변 토글), 계정과목 Select, 거래처 Select, 차변 금액, 대변 금액, 적요, 삭제
 * - 행 추가 버튼 + 합계 행
 * - 버튼: 취소, 저장
 */

import { useState, useCallback, useEffect, useMemo } from 'react';
import { toast } from 'sonner';
import { Plus, Trash2, Loader2 } from 'lucide-react';
import { formatNumber } from '@/lib/utils/amount';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { DatePicker } from '@/components/ui/date-picker';
import { CurrencyInput } from '@/components/ui/currency-input';
import { FormField } from '@/components/molecules/FormField';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from '@/components/ui/dialog';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
  TableFooter,
} from '@/components/ui/table';
import { AccountSubjectSelect } from '@/components/accounting/common';
import { createManualJournal, getVendorList } from './actions';
import type { JournalEntryRow, VendorOption } from './types';
import { JOURNAL_SIDE_OPTIONS } from './types';
import { getTodayString } from '@/lib/utils/date';

interface ManualJournalEntryModalProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSuccess: () => void;
}

function createEmptyRow(): JournalEntryRow {
  return {
    id: crypto.randomUUID(),
    side: 'debit',
    accountSubjectId: '',
    accountSubjectName: '',
    vendorId: '',
    vendorName: '',
    debitAmount: 0,
    creditAmount: 0,
    memo: '',
  };
}

export function ManualJournalEntryModal({
  open,
  onOpenChange,
  onSuccess,
}: ManualJournalEntryModalProps) {
  // 거래 정보
  const [journalDate, setJournalDate] = useState(() => getTodayString());
  const [journalNumber, setJournalNumber] = useState('자동생성');
  const [description, setDescription] = useState('');
  const [receiptNo, setReceiptNo] = useState('');

  // 분개 행
  const [rows, setRows] = useState<JournalEntryRow[]>([createEmptyRow()]);

  // 옵션 데이터
  const [vendors, setVendors] = useState<VendorOption[]>([]);
  const [isSubmitting, setIsSubmitting] = useState(false);

  // 옵션 로드
  useEffect(() => {
    if (!open) return;
    // 초기화
    setJournalDate(getTodayString());
    setJournalNumber('자동생성');
    setDescription('');
    setReceiptNo('');
    setRows([createEmptyRow()]);

    getVendorList().then((vendorsRes) => {
      if (vendorsRes.success && vendorsRes.data) {
        setVendors(vendorsRes.data);
      }
    });
  }, [open]);

  // 행 추가
  const handleAddRow = useCallback(() => {
    setRows((prev) => [...prev, createEmptyRow()]);
  }, []);

  // 행 삭제
  const handleRemoveRow = useCallback((rowId: string) => {
    setRows((prev) => {
      if (prev.length <= 1) return prev;
      return prev.filter((r) => r.id !== rowId);
    });
  }, []);

  // 행 수정
  const handleRowChange = useCallback(
    (rowId: string, field: keyof JournalEntryRow, value: string | number) => {
      setRows((prev) =>
        prev.map((r) => {
          if (r.id !== rowId) return r;
          const updated = { ...r, [field]: value };
          // 구분 변경 시 금액 초기화
          if (field === 'side') {
            if (value === 'debit') {
              updated.creditAmount = 0;
            } else {
              updated.debitAmount = 0;
            }
          }
          return updated;
        })
      );
    },
    []
  );

  // 합계
  const totals = useMemo(() => {
    const debitTotal = rows.reduce((sum, r) => sum + (r.debitAmount || 0), 0);
    const creditTotal = rows.reduce((sum, r) => sum + (r.creditAmount || 0), 0);
    return { debitTotal, creditTotal };
  }, [rows]);

  // 저장
  const handleSubmit = useCallback(async () => {
    if (!journalDate) {
      toast.warning('전표일자를 입력해주세요.');
      return;
    }

    const hasEmptyAccount = rows.some((r) => !r.accountSubjectId);
    if (hasEmptyAccount) {
      toast.warning('모든 행의 계정과목을 선택해주세요.');
      return;
    }

    if (totals.debitTotal !== totals.creditTotal) {
      toast.warning('차변 합계와 대변 합계가 일치하지 않습니다.');
      return;
    }

    if (totals.debitTotal === 0) {
      toast.warning('금액을 입력해주세요.');
      return;
    }

    setIsSubmitting(true);
    try {
      const result = await createManualJournal({
        journalDate,
        description,
        receiptNo: receiptNo || undefined,
        rows,
      });
      if (result.success) {
        toast.success('수기 전표가 등록되었습니다.');
        onOpenChange(false);
        onSuccess();
      } else {
        toast.error(result.error || '등록에 실패했습니다.');
      }
    } catch {
      toast.error('등록 중 오류가 발생했습니다.');
    } finally {
      setIsSubmitting(false);
    }
  }, [journalDate, description, receiptNo, rows, totals, onOpenChange, onSuccess]);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[850px] max-h-[85vh] flex flex-col">
        <DialogHeader>
          <DialogTitle>수기 전표 입력</DialogTitle>
          <DialogDescription className="sr-only">수기 전표를 입력하고 분개 내역을 등록합니다</DialogDescription>
        </DialogHeader>

        {/* 거래 정보 */}
        <div className="grid grid-cols-1 sm:grid-cols-4 gap-3 p-3 bg-muted/50 rounded-lg">
          <div>
            <Label className="text-sm font-medium">
              전표일자 <span className="text-red-500">*</span>
            </Label>
            <DatePicker
              value={journalDate}
              onChange={setJournalDate}
              className="mt-1"
              size="sm"
              displayFormat="yyyy년 MM월 dd일"
            />
          </div>
          <FormField
            label="전표번호"
            value={journalNumber}
            onChange={() => {}}
            disabled
          />
          <FormField
            label="적요"
            value={description}
            onChange={setDescription}
            placeholder="적요 입력"
          />
          <FormField
            label="증빙번호"
            value={receiptNo}
            onChange={setReceiptNo}
            placeholder="영수증/승인번호"
          />
        </div>

        {/* 분개 내역 헤더 */}
        <div className="flex items-center justify-between">
          <Label className="text-sm font-semibold">분개 내역</Label>
          <Button variant="outline" size="sm" onClick={handleAddRow}>
            <Plus className="h-4 w-4 mr-1" />
            행 추가
          </Button>
        </div>

        {/* 분개 테이블 */}
        <div className="flex-1 min-h-0 max-h-[40vh] overflow-auto border rounded-md">
          <Table className="min-w-[750px]">
            <TableHeader>
              <TableRow>
                <TableHead className="text-center w-[90px]">구분</TableHead>
                <TableHead className="w-[150px]">계정과목</TableHead>
                <TableHead className="w-[140px]">거래처</TableHead>
                <TableHead className="text-right w-[120px]">차변 금액</TableHead>
                <TableHead className="text-right w-[120px]">대변 금액</TableHead>
                <TableHead className="w-[120px]">적요</TableHead>
                <TableHead className="text-center w-[50px]"></TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {rows.map((row) => (
                <TableRow key={row.id}>
                  <TableCell className="p-1">
                    <div className="flex">
                      {JOURNAL_SIDE_OPTIONS.map((opt) => (
                        <Button
                          key={opt.value}
                          type="button"
                          size="sm"
                          variant={row.side === opt.value ? 'default' : 'outline'}
                          className="h-7 px-2 text-xs flex-1 rounded-none first:rounded-l-md last:rounded-r-md"
                          onClick={() => handleRowChange(row.id, 'side', opt.value)}
                        >
                          {opt.label}
                        </Button>
                      ))}
                    </div>
                  </TableCell>
                  <TableCell className="p-1">
                    <AccountSubjectSelect
                      value={row.accountSubjectId}
                      onValueChange={(v) =>
                        handleRowChange(row.id, 'accountSubjectId', v)
                      }
                      size="sm"
                      placeholder="선택"
                    />
                  </TableCell>
                  <TableCell className="p-1">
                    <Select
                      value={row.vendorId || 'none'}
                      onValueChange={(v) =>
                        handleRowChange(row.id, 'vendorId', v === 'none' ? '' : v)
                      }
                    >
                      <SelectTrigger className="h-8 text-sm">
                        <SelectValue placeholder="선택" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="none">선택</SelectItem>
                        {vendors.map((v) => (
                          <SelectItem key={v.id} value={v.id}>
                            {v.name}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                  </TableCell>
                  <TableCell className="p-1">
                    <CurrencyInput
                      value={row.debitAmount || 0}
                      onChange={(v) =>
                        handleRowChange(row.id, 'debitAmount', v ?? 0)
                      }
                      disabled={row.side === 'credit'}
                      className="h-8 text-sm"
                      showCurrency={false}
                    />
                  </TableCell>
                  <TableCell className="p-1">
                    <CurrencyInput
                      value={row.creditAmount || 0}
                      onChange={(v) =>
                        handleRowChange(row.id, 'creditAmount', v ?? 0)
                      }
                      disabled={row.side === 'debit'}
                      className="h-8 text-sm"
                      showCurrency={false}
                    />
                  </TableCell>
                  <TableCell className="p-1">
                    <Input
                      value={row.memo}
                      onChange={(e) => handleRowChange(row.id, 'memo', e.target.value)}
                      className="h-8 text-sm"
                      placeholder="적요"
                    />
                  </TableCell>
                  <TableCell className="p-1 text-center">
                    <Button
                      variant="ghost"
                      size="icon"
                      className="h-7 w-7 text-red-500 hover:text-red-600 hover:bg-red-50"
                      onClick={() => handleRemoveRow(row.id)}
                      disabled={rows.length <= 1}
                    >
                      <Trash2 className="h-3.5 w-3.5" />
                    </Button>
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
            <TableFooter>
              <TableRow className="bg-muted/50 font-medium">
                <TableCell colSpan={3} className="text-right text-sm">
                  합계
                </TableCell>
                <TableCell className="text-right text-sm font-bold">
                  {formatNumber(totals.debitTotal)}
                </TableCell>
                <TableCell className="text-right text-sm font-bold">
                  {formatNumber(totals.creditTotal)}
                </TableCell>
                <TableCell colSpan={2} />
              </TableRow>
            </TableFooter>
          </Table>
        </div>

        {/* 차대변 불일치 경고 */}
        {totals.debitTotal !== totals.creditTotal && totals.debitTotal > 0 && (
          <p className="text-xs text-red-500">
            차변 합계({formatNumber(totals.debitTotal)})와 대변 합계(
            {formatNumber(totals.creditTotal)})가 일치하지 않습니다.
          </p>
        )}

        <DialogFooter className="gap-3">
          <Button variant="outline" onClick={() => onOpenChange(false)} disabled={isSubmitting}>
            취소
          </Button>
          <Button onClick={handleSubmit} disabled={isSubmitting}>
            {isSubmitting ? (
              <>
                <Loader2 className="h-4 w-4 mr-2 animate-spin" />
                저장 중...
              </>
            ) : (
              '저장'
            )}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
