'use client';

import { useState, useMemo, useCallback, useEffect, useRef, useTransition } from 'react';
import { Download, FileText, Save, Loader2, RefreshCw, ChevronDown, ChevronUp } from 'lucide-react';
import { formatNumber } from '@/lib/utils/amount';
import { Button } from '@/components/ui/button';
import { Switch } from '@/components/ui/switch';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Card, CardContent } from '@/components/ui/card';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, TableFooter } from '@/components/ui/table';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { PageLayout } from '@/components/organisms/PageLayout';
import { PageHeader } from '@/components/organisms/PageHeader';
import { SearchFilter } from '@/components/organisms/SearchFilter';
import type {
  VendorReceivables,
  CategoryType,
  SortOption,
  ReceivablesListResponse,
  MemoUpdateRequest,
} from './types';
import {
  CATEGORY_LABELS,
  SORT_OPTIONS,
} from './types';
import { getReceivablesList, getReceivablesSummary, updateOverdueStatus, updateMemos, exportReceivablesExcel } from './actions';
import { toast } from 'sonner';
import { filterByText } from '@/lib/utils/search';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { usePermission } from '@/hooks/usePermission';

// ===== Props 인터페이스 =====
interface ReceivablesStatusProps {
  highlightVendorId?: string;
  initialData?: ReceivablesListResponse;
  initialSummary?: {
    totalCarryForward: number;
    totalSales: number;
    totalDeposits: number;
    totalBills: number;
    totalReceivables: number;
    vendorCount: number;
    overdueVendorCount: number;
  };
}

// ===== 연도 옵션 생성 (0 = 최근 1년) =====
const YEAR_RECENT = 0; // 최근 1년 옵션 값
const generateYearOptions = (): Array<{ value: number; label: string }> => {
  const currentYear = new Date().getFullYear();
  const years = Array.from({ length: 5 }, (_, i) => ({
    value: currentYear - i,
    label: `${currentYear - i}년`,
  }));
  return [{ value: YEAR_RECENT, label: '최근 1년' }, ...years];
};

// ===== 카테고리 순서 (메모 제외) =====
const categoryOrder: CategoryType[] = ['sales', 'deposit', 'bill', 'receivable'];

export function ReceivablesStatus({ highlightVendorId, initialData, initialSummary }: ReceivablesStatusProps) {
  const { canExport } = usePermission();
  // ===== Refs =====
  const highlightRowRef = useRef<HTMLTableRowElement>(null);

  // ===== 상태 관리 =====
  const [isPending, startTransition] = useTransition();
  const [selectedYear, setSelectedYear] = useState<number>(YEAR_RECENT); // 기본: 최근 1년
  const [sortOption, setSortOption] = useState<SortOption>('overdueFirst'); // 기본: 연체 업체 우선
  const [searchQuery, setSearchQuery] = useState('');
  const [monthLabels, setMonthLabels] = useState<string[]>(initialData?.monthLabels || []);
  const [data, setData] = useState<VendorReceivables[]>(initialData?.items || []);
  const [originalOverdueMap, setOriginalOverdueMap] = useState<Map<string, boolean>>(new Map());
  const [originalMemoMap, setOriginalMemoMap] = useState<Map<string, string>>(new Map());
  const [summary, setSummary] = useState(initialSummary || {
    totalCarryForward: 0,
    totalSales: 0,
    totalDeposits: 0,
    totalBills: 0,
    totalReceivables: 0,
    vendorCount: 0,
    overdueVendorCount: 0,
  });
  const [isLoading, setIsLoading] = useState(!initialData?.items?.length);
  const [expandedMemos, setExpandedMemos] = useState<Set<string>>(new Set());

  // ===== 데이터 로드 =====
  const loadData = useCallback(async () => {
    setIsLoading(true);
    try {
      const [listResult, summaryResult] = await Promise.all([
        getReceivablesList({ year: selectedYear, search: searchQuery || undefined }),
        getReceivablesSummary({ year: selectedYear }),
      ]);

      if (listResult.success) {
        setMonthLabels(listResult.data.monthLabels);
        setData(listResult.data.items);
        // 원본 연체 상태 저장
        const overdueMap = new Map<string, boolean>();
        const memoMap = new Map<string, string>();
        listResult.data.items.forEach(vendor => {
          overdueMap.set(vendor.id, vendor.isOverdue);
          memoMap.set(vendor.id, vendor.memo || '');
        });
        setOriginalOverdueMap(overdueMap);
        setOriginalMemoMap(memoMap);
      }

      if (summaryResult.success && summaryResult.data) {
        setSummary(summaryResult.data);
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      console.error('Failed to load receivables:', error);
    } finally {
      setIsLoading(false);
    }
  }, [selectedYear, searchQuery]);

  // ===== 초기 로드 및 필터 변경시 재로드 =====
  useEffect(() => {
    loadData();
  }, [loadData]);

  // ===== 하이라이트된 행으로 스크롤 =====
  useEffect(() => {
    if (highlightVendorId && highlightRowRef.current) {
      highlightRowRef.current.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
  }, [highlightVendorId]);

  // ===== 필터링된 데이터 =====
  const filteredData = useMemo(() => {
    return filterByText(data, searchQuery, ['vendorName']);
  }, [data, searchQuery]);

  // ===== 정렬된 데이터 =====
  // 정렬에는 원본 연체 상태(originalOverdueMap)를 사용하여 토글 시 위치 이동 방지
  const sortedData = useMemo(() => {
    const sorted = [...filteredData];

    switch (sortOption) {
      case 'overdueFirst':
        // 연체 업체 우선 (원본 연체 상태 기준으로 정렬, 토글해도 위치 유지)
        sorted.sort((a, b) => {
          const aOriginalOverdue = originalOverdueMap.get(a.id) ?? a.isOverdue;
          const bOriginalOverdue = originalOverdueMap.get(b.id) ?? b.isOverdue;
          if (aOriginalOverdue !== bOriginalOverdue) {
            return aOriginalOverdue ? -1 : 1;
          }
          return a.vendorName.localeCompare(b.vendorName, 'ko');
        });
        break;
      case 'vendorName':
        // 거래처명 순
        sorted.sort((a, b) => a.vendorName.localeCompare(b.vendorName, 'ko'));
        break;
      case 'totalDesc':
        // 금액 높은순 (미수금 합계 기준)
        sorted.sort((a, b) => {
          const aTotal = a.categories.find(c => c.category === 'receivable')?.amounts.total || 0;
          const bTotal = b.categories.find(c => c.category === 'receivable')?.amounts.total || 0;
          return bTotal - aTotal;
        });
        break;
      case 'totalAsc':
        // 금액 낮은순 (미수금 합계 기준)
        sorted.sort((a, b) => {
          const aTotal = a.categories.find(c => c.category === 'receivable')?.amounts.total || 0;
          const bTotal = b.categories.find(c => c.category === 'receivable')?.amounts.total || 0;
          return aTotal - bTotal;
        });
        break;
    }

    return sorted;
  }, [filteredData, sortOption, originalOverdueMap]);

  // ===== 연체 토글 핸들러 =====
  const handleOverdueToggle = useCallback((vendorId: string, checked: boolean) => {
    setData(prev => prev.map(vendor =>
      vendor.id === vendorId ? { ...vendor, isOverdue: checked } : vendor
    ));
  }, []);

  // ===== 메모 변경 핸들러 =====
  const handleMemoChange = useCallback((vendorId: string, memo: string) => {
    setData(prev => prev.map(vendor =>
      vendor.id === vendorId ? { ...vendor, memo } : vendor
    ));
  }, []);

  // ===== 메모 펼치기/접기 토글 =====
  const toggleMemoExpand = useCallback((vendorId: string) => {
    setExpandedMemos(prev => {
      const newSet = new Set(prev);
      if (newSet.has(vendorId)) {
        newSet.delete(vendorId);
      } else {
        newSet.add(vendorId);
      }
      return newSet;
    });
  }, []);

  // ===== 엑셀 다운로드 핸들러 =====
  const handleExcelDownload = useCallback(async () => {
    const result = await exportReceivablesExcel({
      year: selectedYear,
      search: searchQuery || undefined,
    });

    if (result.success && result.data) {
      const url = URL.createObjectURL(result.data);
      const a = document.createElement('a');
      a.href = url;
      a.download = result.filename || '채권현황.xlsx';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
      toast.success('엑셀 파일이 다운로드되었습니다.');
    } else {
      toast.error(result.error || '엑셀 다운로드에 실패했습니다.');
    }
  }, [selectedYear, searchQuery]);

  // ===== 변경된 연체 항목 확인 =====
  const changedOverdueItems = useMemo(() => {
    return data.filter(vendor => {
      const originalValue = originalOverdueMap.get(vendor.id);
      return originalValue !== undefined && originalValue !== vendor.isOverdue;
    }).map(vendor => ({
      id: vendor.id,
      isOverdue: vendor.isOverdue,
    }));
  }, [data, originalOverdueMap]);

  // ===== 변경된 메모 항목 확인 =====
  const changedMemoItems = useMemo(() => {
    return data.filter(vendor => {
      const originalMemo = originalMemoMap.get(vendor.id);
      return originalMemo !== undefined && originalMemo !== vendor.memo;
    }).map(vendor => ({
      id: vendor.id,
      memo: vendor.memo,
    }));
  }, [data, originalMemoMap]);

  // ===== 총 변경 항목 수 =====
  const totalChangedCount = changedOverdueItems.length + changedMemoItems.length;

  // ===== 저장 핸들러 =====
  const handleSave = useCallback(async () => {
    if (totalChangedCount === 0) {
      toast.info('변경된 항목이 없습니다.');
      return;
    }

    startTransition(async () => {
      const promises: Promise<{ success: boolean; error?: string }>[] = [];

      // 연체 상태 업데이트
      if (changedOverdueItems.length > 0) {
        promises.push(updateOverdueStatus(changedOverdueItems));
      }

      // 메모 업데이트
      if (changedMemoItems.length > 0) {
        promises.push(updateMemos(changedMemoItems as MemoUpdateRequest[]));
      }

      const results = await Promise.all(promises);
      const allSuccess = results.every(r => r.success);

      if (allSuccess) {
        // 원본 상태 업데이트
        const newOverdueMap = new Map(originalOverdueMap);
        changedOverdueItems.forEach(item => {
          newOverdueMap.set(item.id, item.isOverdue);
        });
        setOriginalOverdueMap(newOverdueMap);

        const newMemoMap = new Map(originalMemoMap);
        changedMemoItems.forEach(item => {
          newMemoMap.set(item.id, item.memo);
        });
        setOriginalMemoMap(newMemoMap);

        toast.success(`${totalChangedCount}건이 저장되었습니다.`);
      } else {
        const errors = results.filter(r => !r.success).map(r => r.error).join(', ');
        toast.error(errors || '저장에 실패했습니다.');
      }
    });
  }, [changedOverdueItems, changedMemoItems, totalChangedCount, originalOverdueMap, originalMemoMap]);

  // ===== 금액 포맷 =====
  const formatAmount = (amount: number) => {
    if (amount === 0) return '';
    return formatNumber(amount);
  };

  // ===== 합계 계산 (동적 월) =====
  const grandTotals = useMemo(() => {
    const monthCount = monthLabels.length || 12;
    const values = new Array(monthCount).fill(0);
    let total = 0;

    filteredData.forEach(vendor => {
      const receivableCat = vendor.categories.find(c => c.category === 'receivable');
      if (receivableCat) {
        receivableCat.amounts.values.forEach((val, idx) => {
          if (idx < monthCount) {
            values[idx] += val;
          }
        });
        total += receivableCat.amounts.total;
      }
    });

    return { values, total };
  }, [filteredData, monthLabels.length]);

  // ===== 월 개수 (동적) =====
  const monthCount = monthLabels.length || 12;

  // ===== 카테고리 순서 (메모 제외 - 별도 렌더링) =====
  const categoryOrder: CategoryType[] = ['sales', 'deposit', 'bill', 'receivable'];

  return (
    <PageLayout>
      {/* 페이지 헤더 */}
      <PageHeader
        title="미수금 현황"
        description="거래처별 월별 미수금 현황을 조회합니다."
        icon={FileText}
      />

      {/* 헤더 액션 (연도 선택, 버튼) */}
      <Card>
        <CardContent className="p-4">
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-4">
              {/* 연도 선택 */}
              <div className="flex items-center gap-2">
                <span className="text-sm font-medium text-gray-700">연도</span>
                <Select
                  value={String(selectedYear)}
                  onValueChange={(value) => setSelectedYear(Number(value))}
                >
                  <SelectTrigger className="min-w-[120px] w-auto">
                    <SelectValue placeholder="연도 선택" />
                  </SelectTrigger>
                  <SelectContent>
                    {generateYearOptions().map((option) => (
                      <SelectItem key={option.value} value={String(option.value)}>
                        {option.label}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>

              {/* 정렬 선택 */}
              <div className="flex items-center gap-2">
                <span className="text-sm font-medium text-gray-700">정렬</span>
                <Select
                  value={sortOption}
                  onValueChange={(value) => setSortOption(value as SortOption)}
                >
                  <SelectTrigger className="min-w-[140px] w-auto">
                    <SelectValue placeholder="정렬 선택" />
                  </SelectTrigger>
                  <SelectContent>
                    {SORT_OPTIONS.map((option) => (
                      <SelectItem key={option.value} value={option.value}>
                        {option.label}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
            </div>
            <div className="flex items-center gap-2">
              <Button
                variant="outline"
                size="sm"
                onClick={loadData}
                disabled={isLoading}
              >
                {isLoading ? (
                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                ) : (
                  <RefreshCw className="mr-2 h-4 w-4" />
                )}
                새로고침
              </Button>
              {canExport && (
                <Button
                  variant="outline"
                  size="sm"
                  onClick={handleExcelDownload}
                >
                  <Download className="mr-2 h-4 w-4" />
                  엑셀 다운로드
                </Button>
              )}
              <Button
                size="sm"
                onClick={handleSave}
                disabled={isPending || totalChangedCount === 0}
                className="bg-blue-500 hover:bg-blue-600 disabled:opacity-50"
              >
                {isPending ? (
                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                ) : (
                  <Save className="mr-2 h-4 w-4" />
                )}
                저장 {totalChangedCount > 0 && `(${totalChangedCount})`}
              </Button>
            </div>
          </div>
        </CardContent>
      </Card>

      {/* 검색 */}
      <Card>
        <CardContent className="p-6">
          <SearchFilter
            searchValue={searchQuery}
            onSearchChange={setSearchQuery}
            searchPlaceholder="거래처 검색..."
            filterButton={false}
          />
        </CardContent>
      </Card>

      {/* 테이블 */}
      <Card>
        <CardContent className="pt-6">
          <div className="rounded-md border overflow-x-auto">
            <Table className="border-separate border-spacing-0" style={{ minWidth: `${200 + 70 + (monthCount * 100) + 120}px` }}>
              <TableHeader>
                <TableRow>
                  {/* 거래처/연체 - 왼쪽 고정 */}
                  <TableHead className="w-[200px] min-w-[200px] max-w-[200px] sticky left-0 z-20 bg-white border-r border-gray-200">
                    거래처 / 연체
                  </TableHead>
                  {/* 구분 - 왼쪽 고정 (거래처 옆) */}
                  <TableHead className="w-[70px] min-w-[70px] text-center sticky left-[200px] z-20 bg-white border-r border-gray-200">
                    구분
                  </TableHead>
                  {/* 동적 월 레이블 - 스크롤 영역 */}
                  {monthLabels.map((month, idx) => (
                    <TableHead key={`${month}-${idx}`} className="w-[80px] min-w-[80px] text-right">
                      {month}
                    </TableHead>
                  ))}
                  {/* 합계 - 오른쪽 고정 */}
                  <TableHead className="w-[100px] min-w-[100px] text-right sticky right-0 z-20 bg-white border-l border-gray-200">
                    합계
                  </TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {isLoading ? (
                  <TableRow>
                    <TableCell colSpan={monthCount + 3} className="h-24 text-center">
                      <div className="flex items-center justify-center gap-2">
                        <Loader2 className="h-5 w-5 animate-spin text-gray-400" />
                        <span className="text-gray-500">데이터를 불러오는 중...</span>
                      </div>
                    </TableCell>
                  </TableRow>
                ) : sortedData.length === 0 ? (
                  <TableRow>
                    <TableCell colSpan={monthCount + 3} className="h-24 text-center">
                      검색 결과가 없습니다.
                    </TableCell>
                  </TableRow>
                ) : (
                  sortedData.map((vendor) => {
                    const isOverdueRow = vendor.isOverdue;
                    const isHighlighted = highlightVendorId === vendor.id;
                    // 하이라이트 > 연체 > 기본 순으로 배경색 결정
                    const rowBgClass = isHighlighted
                      ? 'bg-yellow-100'
                      : isOverdueRow
                        ? 'bg-red-50'
                        : 'bg-white';

                    // 구분별 행 (매출, 입금, 어음, 미수금) + 메모 행 = 총 5개 행
                    const rows = [];

                    // 구분별 행 렌더링 (rowSpan 대신 각 행마다 개별 거래처 셀로 sticky 안정화)
                    categoryOrder.forEach((category, catIndex) => {
                      const categoryData = vendor.categories.find(c => c.category === category);
                      if (!categoryData) return;

                      rows.push(
                        <TableRow
                          key={`${vendor.id}-${category}`}
                          ref={catIndex === 0 && isHighlighted ? highlightRowRef : undefined}
                          className={`${catIndex === 0 ? 'border-t-2 border-gray-300' : ''} ${isHighlighted ? 'ring-2 ring-yellow-400 ring-inset' : ''}`}
                        >
                          {/* 거래처명 - 왼쪽 고정 (매 행마다 개별 셀, 첫 행만 내용 표시) */}
                          <TableCell
                            className={`font-medium border-r border-gray-200 sticky left-0 z-10 w-[200px] min-w-[200px] max-w-[200px] overflow-hidden whitespace-normal ${rowBgClass} ${catIndex === 0 ? 'align-top pt-3' : 'p-0'}`}
                          >
                            {catIndex === 0 && (
                              <div className="flex flex-col gap-2 overflow-hidden">
                                <span className="text-sm line-clamp-2 break-words" title={vendor.vendorName}>{vendor.vendorName}</span>
                                <div className="flex items-center gap-2">
                                  <Switch
                                    checked={vendor.isOverdue}
                                    onCheckedChange={(checked) => handleOverdueToggle(vendor.id, checked)}
                                    className="data-[state=checked]:bg-red-500"
                                  />
                                  {vendor.isOverdue && (
                                    <span className="text-xs text-red-500 font-medium">연체</span>
                                  )}
                                </div>
                              </div>
                            )}
                          </TableCell>

                          {/* 구분 - 왼쪽 고정 */}
                          <TableCell className={`text-center border-r border-gray-200 text-sm sticky left-[200px] z-10 ${rowBgClass}`}>
                            {CATEGORY_LABELS[category]}
                          </TableCell>

                          {/* 월별 금액 - 스크롤 영역 */}
                          {categoryData.amounts.values.map((amount, monthIndex) => (
                            <TableCell
                              key={`${vendor.id}-${category}-${monthIndex}`}
                              className={`text-right text-sm border-r border-gray-200 ${rowBgClass}`}
                            >
                              {formatAmount(amount)}
                            </TableCell>
                          ))}

                          {/* 합계 - 오른쪽 고정 */}
                          <TableCell className={`text-right font-medium text-sm sticky right-0 z-10 border-l border-gray-200 ${rowBgClass}`}>
                            {formatAmount(categoryData.amounts.total)}
                          </TableCell>
                        </TableRow>
                      );
                    });

                    // 메모 행 추가 (마지막 행)
                    const isMemoExpanded = expandedMemos.has(vendor.id);
                    rows.push(
                      <TableRow key={`${vendor.id}-memo`}>
                        {/* 거래처명 셀 (빈 셀 - 시각적 병합 유지) */}
                        <TableCell className={`border-r border-gray-200 sticky left-0 z-10 w-[200px] min-w-[200px] max-w-[200px] overflow-hidden p-0 ${rowBgClass}`} />

                        {/* 구분: 메모 + 접기/펼치기 버튼 */}
                        <TableCell className={`text-center border-r border-gray-200 text-sm sticky left-[200px] z-10 ${rowBgClass}`}>
                          <div className="flex items-center justify-center gap-1">
                            <span>메모</span>
                            <button
                              type="button"
                              onClick={() => toggleMemoExpand(vendor.id)}
                              className="p-0.5 hover:bg-gray-200 rounded"
                            >
                              {isMemoExpanded ? (
                                <ChevronUp className="h-4 w-4 text-gray-500" />
                              ) : (
                                <ChevronDown className="h-4 w-4 text-gray-500" />
                              )}
                            </button>
                          </div>
                        </TableCell>

                        {/* 메모 입력 - 모든 월 컬럼 + 합계 컬럼 병합 */}
                        <TableCell colSpan={monthCount + 1} className={`p-1 ${rowBgClass}`}>
                          <Textarea
                            value={vendor.memo}
                            onChange={(e) => handleMemoChange(vendor.id, e.target.value)}
                            placeholder="거래처 메모를 입력하세요..."
                            className="w-full text-sm resize-none transition-all !min-h-0 !py-1"
                            style={{
                              height: isMemoExpanded ? '72px' : '32px',
                              lineHeight: '24px',
                              overflowY: isMemoExpanded ? 'auto' : 'hidden',
                            }}
                          />
                        </TableCell>
                      </TableRow>
                    );

                    return rows;
                  })
                )}
              </TableBody>
              <TableFooter>
                <TableRow className="bg-gray-100 font-semibold border-t-2 border-gray-300">
                  {/* 합계 행 - 왼쪽 고정 */}
                  <TableCell className="border-r border-gray-200 sticky left-0 z-10 bg-gray-100">
                    합계
                  </TableCell>
                  <TableCell className="text-center border-r border-gray-200 sticky left-[200px] z-10 bg-gray-100">
                    미수금
                  </TableCell>
                  {/* 월별 합계 - 스크롤 영역 */}
                  {grandTotals.values.map((amount, idx) => (
                    <TableCell key={`total-${idx}`} className="text-right text-sm border-r border-gray-200">
                      {formatAmount(amount)}
                    </TableCell>
                  ))}
                  {/* 총합계 - 오른쪽 고정 */}
                  <TableCell className="text-right font-bold sticky right-0 z-10 bg-gray-100 border-l border-gray-200">
                    {formatAmount(grandTotals.total)}
                  </TableCell>
                </TableRow>
              </TableFooter>
            </Table>
          </div>
        </CardContent>
      </Card>
    </PageLayout>
  );
}