"use client"

import * as React from "react"
import {
  useReactTable,
  getCoreRowModel,
  getSortedRowModel,
  getFilteredRowModel,
  type ColumnDef,
  type SortingState,
  type ColumnFiltersState,
  flexRender,
  type Column,
} from "@tanstack/react-table"
import { useVirtualizer } from "@tanstack/react-virtual"
import { useSession } from "next-auth/react"
import { toast } from "sonner"
import { ChevronDown, ChevronUp, Search, Download, FileSpreadsheet, Upload } from "lucide-react"

import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import { columns, type VendorPoolItem } from "./vendor-pool-table-columns"
import { createVendorPool, updateVendorPool, deleteVendorPool } from "../service"
import type { VendorPool } from "@/db/schema/avl/vendor-pool"
import { BulkInsertDialog } from "./bulk-insert-dialog"
import { ImportVendorPoolButton } from "./vendor-pool-excel-import-button"
import { exportVendorPoolToExcel, createVendorPoolTemplate } from "../excel-utils"
import { ImportResultDialog, type ImportResult } from "./import-result-dialog"

// 테이블 메타 타입
interface VendorPoolTableMeta {
  onCellUpdate?: (id: string | number, field: string, newValue: any) => Promise<void>
  onCellCancel?: (id: string | number, field: string) => void
  onAction?: (action: string, data?: any) => void
  onSaveEmptyRow?: (tempId: string) => Promise<void>
  onCancelEmptyRow?: (tempId: string) => void
  isEmptyRow?: (id: string) => boolean
  getPendingChanges?: () => Record<string, Partial<VendorPoolItem>>
}

interface VendorPoolVirtualTableProps {
  data: VendorPoolItem[]
  onRefresh?: () => void
}

// 빈 행 기본값
const createEmptyVendorPoolBase = (): Omit<VendorPool, 'id'> & { id?: string | number } => ({
  constructionSector: "",
  htDivision: "",
  discipline: "",
  equipBulkDivision: "",
  materialGroupCode: null,
  materialGroupName: null,
  similarMaterialNamePurchase: null,
  vendorCode: null,
  vendorName: "",
  taxId: null,
  faTarget: false,
  faStatus: null,
  tier: null,
  headquarterLocation: "",
  manufacturingLocation: "",
  avlVendorName: null,
  similarVendorName: null,
  isBlacklist: false,
  isBcc: false,
  purchaseOpinion: null,
  recentQuoteDate: null,
  recentQuoteNumber: null,
  recentOrderDate: null,
  recentOrderNumber: null,
  registrationDate: null,
  registrant: null,
  lastModifiedDate: null,
  lastModifier: null,
})

function Filter({ column }: { column: Column<any, unknown> }) {
  const columnFilterValue = column.getFilterValue()
  const id = column.id

  // Boolean 필터 (faTarget, isBlacklist, isBcc 등)
  if (id === 'faTarget' || id === 'isBlacklist' || id === 'isBcc') {
    return (
      <div onClick={(e) => e.stopPropagation()} className="mt-2">
        <Select
          value={(columnFilterValue as string) ?? "all"}
          onValueChange={(value) => column.setFilterValue(value === "all" ? undefined : value === "true")}
        >
          <SelectTrigger className="h-8 w-full">
            <SelectValue placeholder="All" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="all">All</SelectItem>
            <SelectItem value="true">Yes</SelectItem>
            <SelectItem value="false">No</SelectItem>
          </SelectContent>
        </Select>
      </div>
    )
  }

  // FA Status 필터 (O 또는 빈 값)
  if (id === 'faStatus') {
    return (
      <div onClick={(e) => e.stopPropagation()} className="mt-2">
        <Select
          value={(columnFilterValue as string) ?? "all"}
          onValueChange={(value) => column.setFilterValue(value === "all" ? undefined : value)}
        >
          <SelectTrigger className="h-8 w-full">
            <SelectValue placeholder="All" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="all">All</SelectItem>
            <SelectItem value="O">YES</SelectItem>
            <SelectItem value="X">NO</SelectItem>
          </SelectContent>
        </Select>
      </div>
    )
  }

  // 일반 텍스트 검색
  return (
    <div onClick={(e) => e.stopPropagation()} className="mt-2">
      <Input
        type="text"
        value={(columnFilterValue ?? '') as string}
        onChange={(e) => column.setFilterValue(e.target.value)}
        placeholder="Search..."
        className="h-8 w-full font-normal bg-background"
      />
    </div>
  )
}

export function VendorPoolVirtualTable({ data, onRefresh }: VendorPoolVirtualTableProps) {
  const { data: session } = useSession()

  // onRefresh를 ref로 관리하여 무한 루프 방지
  const onRefreshRef = React.useRef(onRefresh)
  React.useEffect(() => {
    onRefreshRef.current = onRefresh
  }, [onRefresh])

  // 상태 관리
  const [sorting, setSorting] = React.useState<SortingState>([])
  const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
  const [globalFilter, setGlobalFilter] = React.useState("")
  const [pendingChanges, setPendingChanges] = React.useState<Record<string, Partial<VendorPoolItem>>>({})
  const [isSaving, setIsSaving] = React.useState(false)
  const [emptyRows, setEmptyRows] = React.useState<Record<string, VendorPoolItem>>({})
  const [isCreating, setIsCreating] = React.useState(false)
  const [bulkInsertDialogOpen, setBulkInsertDialogOpen] = React.useState(false)
  const [importResult, setImportResult] = React.useState<ImportResult | null>(null)
  const [showImportResultDialog, setShowImportResultDialog] = React.useState(false)

  const handleImportComplete = React.useCallback((result: ImportResult) => {
    setImportResult(result)
    setShowImportResultDialog(true)
  }, [])

  const handleImportDialogClose = React.useCallback((open: boolean) => {
    setShowImportResultDialog(open)
    if (!open && importResult && importResult.successCount > 0) {
      onRefreshRef.current?.()
    }
  }, [importResult])

  // 인라인 편집 핸들러
  const handleCellUpdate = React.useCallback(async (id: string | number, field: string, newValue: any) => {
    const isEmptyRow = String(id).startsWith('temp-')

    if (isEmptyRow) {
      setEmptyRows(prev => ({
        ...prev,
        [id]: {
          ...prev[id],
          [field]: newValue
        }
      }))
    }

    setPendingChanges(prev => ({
      ...prev,
      [id]: {
        ...prev[id],
        [field]: newValue
      }
    }))
  }, [])

  // 편집 취소 핸들러
  const handleCellCancel = React.useCallback((id: string | number, field: string) => {
    const isEmptyRow = String(id).startsWith('temp-')

    if (isEmptyRow) {
      setEmptyRows(prev => ({
        ...prev,
        [id]: {
          ...prev[id],
          [field]: prev[id][field]
        }
      }))

      setPendingChanges(prev => {
        const itemChanges = { ...prev[id] }
        delete itemChanges[field]

        if (Object.keys(itemChanges).length === 0) {
          const newChanges = { ...prev }
          delete newChanges[id]
          return newChanges
        }

        return {
          ...prev,
          [id]: itemChanges
        }
      })
    } else {
      setPendingChanges(prev => {
        const itemChanges = { ...prev[id] }
        delete itemChanges[field]

        if (Object.keys(itemChanges).length === 0) {
          const newChanges = { ...prev }
          delete newChanges[id]
          return newChanges
        }

        return {
          ...prev,
          [id]: itemChanges
        }
      })
    }
  }, [])

  // 일괄 저장 핸들러
  const handleBatchSave = React.useCallback(async () => {
    if (Object.keys(pendingChanges).length === 0) return

    setIsSaving(true)
    let successCount = 0
    let errorCount = 0
    let duplicateErrors: string[] = []

    try {
      for (const [id, changes] of Object.entries(pendingChanges)) {
        try {
          const { id: _, no: __, selected: ___, ...updateData } = changes
          const updateDataWithModifier: any = {
            ...updateData,
            lastModifier: session?.user?.name || null
          }
          const result = await updateVendorPool(Number(id), updateDataWithModifier)
          if (result) {
            successCount++
          } else {
            errorCount++
          }
        } catch (error) {
          console.error(`항목 ${id} 저장 실패:`, error)

          const errorMessage = error instanceof Error ? error.message : String(error);
          if (errorMessage === 'DUPLICATE_VENDOR_POOL') {
            const changes = pendingChanges[id]
            duplicateErrors.push(`항목 ${id}: 공사부문(${changes.constructionSector}), H/T(${changes.htDivision}), 자재그룹코드(${changes.materialGroupCode}), 협력업체명(${changes.vendorName})`)
          }
          errorCount++
        }
      }

      setPendingChanges({})

      if (successCount > 0) {
        toast.success(`${successCount}개 항목이 저장되었습니다.`)
        onRefreshRef.current?.()
      }

      if (duplicateErrors.length > 0) {
        duplicateErrors.forEach(errorMsg => {
          toast.error(`중복된 항목입니다. ${errorMsg}`)
        })
      }

      const generalErrorCount = errorCount - duplicateErrors.length
      if (generalErrorCount > 0) {
        toast.error(`${generalErrorCount}개 항목 저장에 실패했습니다.`)
      }
    } catch (error) {
      console.error("Batch save error:", error)
      toast.error("저장 중 오류가 발생했습니다.")
    } finally {
      setIsSaving(false)
    }
  }, [pendingChanges, session]) // ✅ onRefresh 제거

  // 빈 행 생성
  const createEmptyRow = React.useCallback(() => {
    if (isCreating) return

    const tempId = `temp-${Date.now()}`
    const userName = session?.user?.name || null

    const emptyRow: VendorPoolItem = {
      ...createEmptyVendorPoolBase(),
      id: tempId,
      no: 0,
      selected: false,
      registrationDate: "",
      registrant: userName || "",
      lastModifiedDate: "",
      lastModifier: userName || "",
    } as unknown as VendorPoolItem

    setEmptyRows(prev => ({ ...prev, [tempId]: emptyRow }))
    setIsCreating(true)

    setPendingChanges(prev => ({
      ...prev,
      [tempId]: { ...emptyRow }
    }))
  }, [isCreating, session])

  // 빈 행 저장
  const saveEmptyRow = React.useCallback(async (tempId: string) => {
    const rowData = emptyRows[tempId]
    const changes = pendingChanges[tempId]

    if (!rowData || !changes) {
      console.error('rowData 또는 changes가 없음')
      return
    }

    const finalData = { ...rowData, ...changes }

    const requiredFields = ['constructionSector', 'htDivision', 'discipline', 'vendorName', 'materialGroupCode', 'materialGroupName', 'tier', 'headquarterLocation', 'manufacturingLocation', 'avlVendorName']

    const fieldLabels: Record<string, string> = {
      constructionSector: '공사부문',
      htDivision: 'H/T구분',
      discipline: '설계공종',
      vendorName: '협력업체명',
      materialGroupCode: '자재그룹코드',
      materialGroupName: '자재그룹명',
      tier: '등급(Tier)',
      headquarterLocation: '위치(국가)',
      manufacturingLocation: '제작/선적지(국가)',
      avlVendorName: 'AVL등재업체명'
    }

    const missingFields = requiredFields.filter(field => {
      const value = finalData[field as keyof VendorPoolItem]
      return !value || value === ''
    })

    if (missingFields.length > 0) {
      const missingFieldLabels = missingFields.map(field => fieldLabels[field]).join(', ')
      toast.error(`필수 항목을 입력해주세요: ${missingFieldLabels}`)
      return
    }

    try {
      setIsSaving(true)

      const { id: _, no: __, selected: ___, registrationDate: ____, lastModifiedDate: _____, ...createData } = finalData

      const result = await createVendorPool(createData as any)

      if (result) {
        toast.success("새 항목이 추가되었습니다.")

        setEmptyRows(prev => {
          const newRows = { ...prev }
          delete newRows[tempId]
          return newRows
        })

        setPendingChanges(prev => {
          const newChanges = { ...prev }
          delete newChanges[tempId]
          return newChanges
        })

        setIsCreating(false)
        onRefreshRef.current?.()
      }
    } catch (error) {
      console.error("빈 행 저장 실패:", error)

      const errorMessage = error instanceof Error ? error.message : String(error);
      if (errorMessage === 'DUPLICATE_VENDOR_POOL') {
        toast.error(`중복된 항목입니다. (공사부문: ${finalData.constructionSector}, H/T: ${finalData.htDivision}, 자재그룹코드: ${finalData.materialGroupCode}, 협력업체명: ${finalData.vendorName})`)
      } else {
        toast.error("저장 중 오류가 발생했습니다.")
      }
    } finally {
      setIsSaving(false)
    }
  }, [emptyRows, pendingChanges]) // ✅ onRefresh 제거

  // 빈 행 취소
  const cancelEmptyRow = React.useCallback((tempId: string) => {
    setEmptyRows(prev => {
      const newRows = { ...prev }
      delete newRows[tempId]
      return newRows
    })

    setPendingChanges(prev => {
      const newChanges = { ...prev }
      delete newChanges[tempId]
      return newChanges
    })

    setIsCreating(false)
    toast.info("새 항목 추가가 취소되었습니다.")
  }, [])

  // 데이터 병합 (빈 행 + 기존 데이터)
  const combinedData = React.useMemo(() => {
    const emptyRowList = Object.values(emptyRows)

    const updatedEmptyRows = emptyRowList.map((row, index) => ({
      ...row,
      no: -(emptyRowList.length - index)
    }))

    // 최적화: 변경사항이 없으면 기존 객체 재사용
    const updatedExistingData = data.map((row) => {
      const rowId = String(row.id)
      const pendingChange = pendingChanges[rowId]

      if (pendingChange) {
        return { ...row, ...pendingChange }
      }
      
      return row
    })

    return [...updatedEmptyRows, ...updatedExistingData]
  }, [data, emptyRows, pendingChanges])

  // 액션 핸들러
  const handleAction = React.useCallback(async (action: string, data?: any) => {
    try {
      switch (action) {
        case 'new-registration':
          createEmptyRow()
          break

        case 'bulk-import':
          setBulkInsertDialogOpen(true)
          break

        case 'excel-export':
          try {
            await exportVendorPoolToExcel(
              combinedData,
              `vendor-pool-${new Date().toISOString().split('T')[0]}.xlsx`,
              true
            )
            toast.success('Excel 파일이 다운로드되었습니다.')
          } catch (error) {
            console.error('Excel export 실패:', error)
            toast.error('Excel 내보내기에 실패했습니다.')
          }
          break

        case 'excel-template':
          try {
            await createVendorPoolTemplate(
              `vendor-pool-template-${new Date().toISOString().split('T')[0]}.xlsx`
            )
            toast.success('Excel 템플릿이 다운로드되었습니다.')
          } catch (error) {
            console.error('Excel template export 실패:', error)
            toast.error('Excel 템플릿 다운로드에 실패했습니다.')
          }
          break

        case 'delete':
          if (data?.id && confirm('정말 삭제하시겠습니까?')) {
            const success = await deleteVendorPool(Number(data.id))
            if (success) {
              toast.success('삭제가 완료되었습니다.')
              onRefreshRef.current?.()
            } else {
              toast.error('삭제에 실패했습니다.')
            }
          }
          break

        default:
          console.log('알 수 없는 액션:', action)
          toast.error('알 수 없는 액션입니다.')
      }
    } catch (error) {
      console.error('액션 처리 실패:', error)
      toast.error('액션 처리 중 오류가 발생했습니다.')
    }
  }, [createEmptyRow, combinedData]) // ✅ onRefresh 제거, combinedData 추가

  // 테이블 메타
  const tableMeta: VendorPoolTableMeta = {
    onAction: handleAction,
    onCellUpdate: handleCellUpdate,
    onCellCancel: handleCellCancel,
    onSaveEmptyRow: saveEmptyRow,
    onCancelEmptyRow: cancelEmptyRow,
    isEmptyRow: (id: string) => String(id).startsWith('temp-'),
    getPendingChanges: () => pendingChanges
  }

  // TanStack Table 설정
  const table = useReactTable({
    data: combinedData,
    columns,
    state: {
      sorting,
      columnFilters,
      globalFilter,
    },
    onSortingChange: setSorting,
    onColumnFiltersChange: setColumnFilters,
    onGlobalFilterChange: setGlobalFilter,
    columnResizeMode: "onChange",
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getRowId: (originalRow) => String(originalRow.id),
    meta: tableMeta,
  })

  // 일괄입력 핸들러
  const handleBulkInsert = React.useCallback(async (bulkData: Record<string, any>) => {
    const selectedRows = table.getFilteredSelectedRowModel().rows

    if (selectedRows.length === 0) {
      toast.error('일괄 입력할 행이 선택되지 않았습니다.')
      return
    }

    try {
      for (const row of selectedRows) {
        const rowId = String(row.original.id)

        Object.entries(bulkData).forEach(([field, value]) => {
          if (value !== undefined && value !== null && value !== '') {
            handleCellUpdate(rowId, field as keyof VendorPool, value)
          }
        })
      }

      toast.success(`${selectedRows.length}개 행에 일괄 입력이 적용되었습니다.`)
      setBulkInsertDialogOpen(false)
    } catch (error) {
      console.error('일괄입력 처리 실패:', error)
      toast.error('일괄입력 처리 중 오류가 발생했습니다.')
    }
  }, [table, handleCellUpdate]) // table dependency 추가

  // Virtual Scrolling 설정
  const tableContainerRef = React.useRef<HTMLDivElement>(null)

  const { rows } = table.getRowModel()

  const rowVirtualizer = useVirtualizer({
    count: rows.length,
    getScrollElement: () => tableContainerRef.current,
    estimateSize: () => 50, // 행 높이 추정값
    overscan: 10, // 화면 밖 렌더링할 행 수
  })

  const virtualRows = rowVirtualizer.getVirtualItems()
  const totalSize = rowVirtualizer.getTotalSize()

  const paddingTop = virtualRows.length > 0 ? virtualRows?.[0]?.start || 0 : 0
  const paddingBottom = virtualRows.length > 0
    ? totalSize - (virtualRows?.[virtualRows.length - 1]?.end || 0)
    : 0

  const hasPendingChanges = Object.keys(pendingChanges).length > 0

  return (
    <div className="flex flex-col flex-1 min-h-0 space-y-4">
      {/* 툴바 */}
      <div className="flex items-center justify-between gap-4">
        <div className="flex items-center gap-2 flex-1">
          <div className="relative flex-1 max-w-sm">
            <Search className="absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
            <Input
              placeholder="전체 검색..."
              value={globalFilter ?? ""}
              onChange={(e) => setGlobalFilter(e.target.value)}
              className="pl-8"
            />
          </div>
          <div className="text-sm text-muted-foreground">
            전체 {combinedData.length}건 중 {rows.length}건 표시
          </div>
        </div>

        <div className="flex items-center gap-2">
          <Button
            onClick={() => handleAction('new-registration')}
            disabled={isCreating}
            variant="outline"
            size="sm"
          >
            신규등록
          </Button>

          <Button
            onClick={() => handleAction('bulk-import')}
            variant="outline"
            size="sm"
          >
            일괄입력
          </Button>

          <ImportVendorPoolButton onImportComplete={handleImportComplete} />

          <Button
            onClick={() => handleAction('excel-export')}
            variant="outline"
            size="sm"
          >
            <Download className="mr-2 h-4 w-4" />
            Excel Export
          </Button>

          <Button
            onClick={() => handleAction('excel-template')}
            variant="outline"
            size="sm"
          >
            <FileSpreadsheet className="mr-2 h-4 w-4" />
            Template
          </Button>

          <Button
            onClick={handleBatchSave}
            disabled={!hasPendingChanges || isSaving}
            variant={hasPendingChanges && !isSaving ? "default" : "outline"}
            size="sm"
          >
            {isSaving ? "저장 중..." : `저장${hasPendingChanges ? ` (${Object.keys(pendingChanges).length})` : ""}`}
          </Button>
        </div>
      </div>

      {/* 테이블 */}
      <div
        ref={tableContainerRef}
        className="relative flex-1 overflow-auto border rounded-md"
      >
        <table
          className="table-fixed border-collapse"
          style={{ width: table.getTotalSize() }}
        >
          <thead className="sticky top-0 z-10 bg-muted">
            {table.getHeaderGroups().map((headerGroup) => (
              <tr key={headerGroup.id}>
                {headerGroup.headers.map((header) => (
                  <th
                    key={header.id}
                    className="border-b px-4 py-2 text-left text-sm font-medium relative group"
                    style={{ width: header.getSize() }}
                  >
                    {header.isPlaceholder ? null : (
                      <>
                        <div
                          className={
                            header.column.getCanSort()
                            ? "flex items-center gap-2 cursor-pointer select-none"
                            : ""
                          }
                          onClick={header.column.getToggleSortingHandler()}
                        >
                          {flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                          {header.column.getCanSort() && (
                            <div className="flex flex-col">
                              {header.column.getIsSorted() === "asc" ? (
                                <ChevronUp className="h-4 w-4" />
                              ) : header.column.getIsSorted() === "desc" ? (
                                <ChevronDown className="h-4 w-4" />
                              ) : (
                                <div className="h-4 w-4" />
                              )}
                            </div>
                          )}
                        </div>
                        {header.column.getCanFilter() && (
                          <Filter column={header.column} />
                        )}
                        <div
                          onMouseDown={header.getResizeHandler()}
                          onTouchStart={header.getResizeHandler()}
                          className={`absolute right-0 top-0 h-full w-1 cursor-col-resize select-none touch-none hover:bg-primary/50 ${
                            header.column.getIsResizing() ? 'bg-primary' : 'bg-transparent'
                          }`}
                        />
                      </>
                    )}
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <tbody>
            {paddingTop > 0 && (
              <tr>
                <td style={{ height: `${paddingTop}px` }} />
              </tr>
            )}
            {virtualRows.map((virtualRow) => {
              const row = rows[virtualRow.index]
              const isEmptyRow = String(row.original.id).startsWith('temp-')
              
              return (
                <tr
                  key={row.id}
                  data-index={virtualRow.index}
                  ref={rowVirtualizer.measureElement}
                  data-row-id={row.id}
                  className={isEmptyRow ? "bg-blue-50 border-blue-200" : "hover:bg-muted/50"}
                >
                  {row.getVisibleCells().map((cell) => (
                    <td
                      key={cell.id}
                      className="border-b px-4 py-2 text-sm whitespace-normal break-words"
                      style={{ width: cell.column.getSize() }}
                    >
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext()
                      )}
                    </td>
                  ))}
                </tr>
              )
            })}
            {paddingBottom > 0 && (
              <tr>
                <td style={{ height: `${paddingBottom}px` }} />
              </tr>
            )}
          </tbody>
        </table>
      </div>

      <BulkInsertDialog
        open={bulkInsertDialogOpen}
        onOpenChange={setBulkInsertDialogOpen}
        onSubmit={handleBulkInsert}
      />

      <ImportResultDialog
        open={showImportResultDialog}
        onOpenChange={handleImportDialogClose}
        result={importResult}
      />
    </div>
  )
}
