"use client";

import React, { useCallback, useEffect, useState, useMemo } from "react";
import { Loader2, FoldVertical, UnfoldVertical } from "lucide-react";
import { Checkbox } from "@/components/ui/checkbox";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { TableGroupedComponentProps } from "./types";
import { useGroupedData } from "./hooks/useGroupedData";
import { GroupHeader } from "./components/GroupHeader";
import { useScreenContextOptional } from "@/contexts/ScreenContext";
import { useTableOptions } from "@/contexts/TableOptionsContext";
import type { DataProvidable, DataReceivable, DataReceiverConfig } from "@/types/data-transfer";
import { v2EventBus, V2_EVENTS } from "@/lib/v2-core/events";

/**
 * v2-table-grouped 메인 컴포넌트
 *
 * 데이터를 특정 컬럼 기준으로 그룹화하여 접기/펼치기 기능을 제공합니다.
 */
export function TableGroupedComponent({
  config,
  isDesignMode = false,
  formData,
  onSelectionChange,
  onGroupToggle,
  onRowClick,
  externalData,
  isLoading: externalLoading,
  error: externalError,
  componentId,
}: TableGroupedComponentProps) {
  // 화면 컨텍스트 (데이터 제공자로 등록)
  const screenContext = useScreenContextOptional();

  // TableOptions Context (검색필터 연동)
  const { registerTable, unregisterTable, updateTableDataCount } = useTableOptions();

  // 연결된 필터 상태 (다른 컴포넌트 값으로 필터링)
  const [linkedFilterValues, setLinkedFilterValues] = useState<Record<string, any>>({});

  // 필터 및 그룹 설정 상태 (검색필터 연동용)
  const [filters, setFilters] = useState<any[]>([]);
  const [grouping, setGrouping] = useState<string[]>([]);
  const [columnVisibility, setColumnVisibility] = useState<any[]>([]);

  // 그룹화 데이터 훅 (검색 필터 전달)
  const {
    groups,
    isLoading: hookLoading,
    error: hookError,
    toggleGroup,
    expandAll,
    collapseAll,
    toggleItemSelection,
    toggleGroupSelection,
    toggleAllSelection,
    selectedItems,
    isAllSelected,
    isIndeterminate,
    refresh,
    rawData,
    totalCount,
    groupCount,
  } = useGroupedData(config, externalData, linkedFilterValues);

  const isLoading = externalLoading ?? hookLoading;
  const error = externalError ?? hookError;

  // 필터링된 데이터 (훅에서 이미 필터 적용됨)
  const filteredData = rawData;

  // 연결된 필터 감시
  useEffect(() => {
    const linkedFilters = config.linkedFilters;

    if (!linkedFilters || linkedFilters.length === 0 || !screenContext) {
      return;
    }

    // 연결된 소스 컴포넌트들의 값을 주기적으로 확인
    const checkLinkedFilters = () => {
      const newFilterValues: Record<string, any> = {};
      let hasChanges = false;

      linkedFilters.forEach((filter) => {
        if (filter.enabled === false) return;

        const sourceProvider = screenContext.getDataProvider(filter.sourceComponentId);
        if (sourceProvider) {
          const selectedData = sourceProvider.getSelectedData();
          if (selectedData && selectedData.length > 0) {
            const sourceField = filter.sourceField || "value";
            const value = selectedData[0][sourceField];

            if (value !== linkedFilterValues[filter.targetColumn]) {
              newFilterValues[filter.targetColumn] = value;
              hasChanges = true;
            } else {
              newFilterValues[filter.targetColumn] = linkedFilterValues[filter.targetColumn];
            }
          }
        }
      });

      if (hasChanges) {
        setLinkedFilterValues(newFilterValues);
      }
    };

    // 초기 확인
    checkLinkedFilters();

    // 주기적 확인 (100ms 간격)
    const intervalId = setInterval(checkLinkedFilters, 100);

    return () => {
      clearInterval(intervalId);
    };
  }, [screenContext, config.linkedFilters, linkedFilterValues]);

  // DataProvidable 인터페이스 구현
  const dataProvider: DataProvidable = useMemo(
    () => ({
      componentId: componentId || "",
      componentType: "table-grouped",

      getSelectedData: () => {
        return selectedItems;
      },

      getAllData: () => {
        return filteredData;
      },

      clearSelection: () => {
        toggleAllSelection();
      },
    }),
    [componentId, selectedItems, filteredData, toggleAllSelection]
  );

  // DataReceivable 인터페이스 구현
  const dataReceiver: DataReceivable = useMemo(
    () => ({
      componentId: componentId || "",
      componentType: "table-grouped",

      receiveData: async (_receivedData: any[], _config: DataReceiverConfig) => {
        // 현재는 외부 데이터 수신 시 새로고침만 수행
        refresh();
      },

      clearData: async () => {
        // 데이터 클리어 시 새로고침
        refresh();
      },

      getConfig: () => {
        return {
          targetComponentId: componentId || "",
          mode: "replace" as const,
        };
      },
    }),
    [componentId, refresh]
  );

  // 화면 컨텍스트에 데이터 제공자/수신자로 등록
  useEffect(() => {
    if (screenContext && componentId) {
      screenContext.registerDataProvider(componentId, dataProvider);
      screenContext.registerDataReceiver(componentId, dataReceiver);

      return () => {
        screenContext.unregisterDataProvider(componentId);
        screenContext.unregisterDataReceiver(componentId);
      };
    }
  }, [screenContext, componentId, dataProvider, dataReceiver]);

  // 테이블 ID (검색필터 연동용)
  const tableId = componentId || `table-grouped-${config.selectedTable || "default"}`;

  // TableOptionsContext에 테이블 등록 (검색필터가 테이블을 찾을 수 있도록)
  useEffect(() => {
    if (isDesignMode || !config.selectedTable) return;

    const columnsToRegister = config.columns || [];

    // 고유 값 조회 함수
    const getColumnUniqueValues = async (columnName: string) => {
      const uniqueValues = new Set<string>();
      rawData.forEach((row) => {
        const value = row[columnName];
        if (value !== null && value !== undefined && value !== "") {
          uniqueValues.add(String(value));
        }
      });
      return Array.from(uniqueValues)
        .map((value) => ({ value, label: value }))
        .sort((a, b) => a.label.localeCompare(b.label));
    };

    const registration = {
      tableId,
      label: config.selectedTable,
      tableName: config.selectedTable,
      dataCount: totalCount,
      columns: columnsToRegister.map((col) => ({
        columnName: col.columnName,
        columnLabel: col.displayName || col.columnName,
        inputType: "text",
        visible: col.visible !== false,
        width: col.width || 150,
        sortable: true,
        filterable: true,
      })),
      onFilterChange: setFilters,
      onGroupChange: setGrouping,
      onColumnVisibilityChange: setColumnVisibility,
      getColumnUniqueValues,
    };

    registerTable(registration);

    return () => {
      unregisterTable(tableId);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [tableId, config.selectedTable, config.columns, totalCount, rawData, registerTable, isDesignMode]);

  // 데이터 건수 변경 시 업데이트
  useEffect(() => {
    if (!isDesignMode && config.selectedTable) {
      updateTableDataCount(tableId, totalCount);
    }
  }, [tableId, totalCount, updateTableDataCount, config.selectedTable, isDesignMode]);

  // 필터 변경 시 검색 조건 적용
  useEffect(() => {
    if (filters.length > 0) {
      const newFilterValues: Record<string, any> = {};
      filters.forEach((filter: any) => {
        if (filter.value) {
          newFilterValues[filter.columnName] = filter.value;
        }
      });
      setLinkedFilterValues((prev) => ({ ...prev, ...newFilterValues }));
    }
  }, [filters]);

  // 컬럼 설정
  const columns = config.columns || [];
  const visibleColumns = columns.filter((col) => col.visible !== false);

  // 체크박스 컬럼 포함 시 총 컬럼 수
  const totalColumnCount = visibleColumns.length + (config.showCheckbox ? 1 : 0);

  // 아이템 ID 추출 함수
  const getItemId = useCallback(
    (item: any): string => {
      if (item.id !== undefined) return String(item.id);
      const firstCol = columns[0]?.columnName;
      if (firstCol && item[firstCol] !== undefined) return String(item[firstCol]);
      return JSON.stringify(item);
    },
    [columns]
  );

  // 선택 변경 시 콜백 및 이벤트 발송
  useEffect(() => {
    // 기존 콜백 호출
    if (onSelectionChange && selectedItems.length >= 0) {
      onSelectionChange({
        selectedGroups: groups
          .filter((g) => g.selected)
          .map((g) => g.groupKey),
        selectedItems,
        isAllSelected,
      });
    }

    // TABLE_SELECTION_CHANGE 이벤트 발송 (선택 데이터 변경 시 다른 컴포넌트에 알림)
    v2EventBus.emit(V2_EVENTS.TABLE_SELECTION_CHANGE, {
      componentId: componentId || tableId,
      tableName: config.selectedTable || "",
      selectedRows: selectedItems,
      selectedCount: selectedItems.length,
    });

    console.log("[TableGroupedComponent] 선택 변경 이벤트 발송:", {
      componentId: componentId || tableId,
      tableName: config.selectedTable,
      selectedCount: selectedItems.length,
    });
  }, [selectedItems, groups, isAllSelected, onSelectionChange, componentId, tableId, config.selectedTable]);

  // 그룹 토글 핸들러
  const handleGroupToggle = useCallback(
    (groupKey: string) => {
      toggleGroup(groupKey);
      if (onGroupToggle) {
        const group = groups.find((g) => g.groupKey === groupKey);
        onGroupToggle({
          groupKey,
          expanded: !group?.expanded,
        });
      }
    },
    [toggleGroup, onGroupToggle, groups]
  );

  // 행 클릭 핸들러
  const handleRowClick = useCallback(
    (row: any, groupKey: string, indexInGroup: number) => {
      if (!config.rowClickable) return;
      if (onRowClick) {
        onRowClick({ row, groupKey, indexInGroup });
      }
    },
    [config.rowClickable, onRowClick]
  );

  // refreshTable 이벤트 구독
  useEffect(() => {
    const handleRefresh = () => {
      refresh();
    };

    window.addEventListener("refreshTable", handleRefresh);
    return () => {
      window.removeEventListener("refreshTable", handleRefresh);
    };
  }, [refresh]);

  // 디자인 모드 렌더링
  if (isDesignMode) {
    return (
      <div className="rounded-md border bg-muted/20 p-4">
        <div className="flex items-center gap-2 text-sm text-muted-foreground">
          <FoldVertical className="h-4 w-4" />
          <span>그룹화 테이블</span>
          {config.groupConfig?.groupByColumn && (
            <span className="text-xs">
              (그룹: {config.groupConfig.groupByColumn})
            </span>
          )}
        </div>
        <div className="mt-2 text-xs text-muted-foreground">
          테이블: {config.useCustomTable ? config.customTableName : config.selectedTable || "(미설정)"}
        </div>
      </div>
    );
  }

  // 로딩 상태
  if (isLoading) {
    return (
      <div className="flex items-center justify-center py-8">
        <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
        <span className="ml-2 text-sm text-muted-foreground">로딩 중...</span>
      </div>
    );
  }

  // 에러 상태
  if (error) {
    return (
      <div className="rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive">
        {error}
      </div>
    );
  }

  // 데이터 없음
  if (groups.length === 0) {
    return (
      <div className="flex items-center justify-center py-8 text-sm text-muted-foreground">
        {config.emptyMessage || "데이터가 없습니다."}
      </div>
    );
  }

  return (
    <div
      className="v2-table-grouped flex flex-col"
      style={{
        height: config.height,
        maxHeight: config.maxHeight,
      }}
    >
      {/* 툴바 */}
      {config.showExpandAllButton && (
        <div className="flex items-center justify-between border-b bg-muted/30 px-3 py-2">
          <div className="flex items-center gap-2">
            <Button
              variant="ghost"
              size="sm"
              onClick={expandAll}
              className="h-7 text-xs"
            >
              <UnfoldVertical className="mr-1 h-3 w-3" />
              전체 펼치기
            </Button>
            <Button
              variant="ghost"
              size="sm"
              onClick={collapseAll}
              className="h-7 text-xs"
            >
              <FoldVertical className="mr-1 h-3 w-3" />
              전체 접기
            </Button>
          </div>
          <div className="text-xs text-muted-foreground">
            {groupCount}개 그룹 | 총 {totalCount}건
          </div>
        </div>
      )}

      {/* 테이블 */}
      <div className="flex-1 overflow-auto">
        <table className="w-full border-collapse text-sm">
          {/* 테이블 헤더 */}
          <thead className="sticky top-0 z-10 bg-muted">
            <tr>
              {/* 전체 선택 체크박스 */}
              {config.showCheckbox && (
                <th className="w-10 whitespace-nowrap border-b px-3 py-2 text-left">
                  <Checkbox
                    checked={isAllSelected}
                    onCheckedChange={toggleAllSelection}
                    className={cn(isIndeterminate && "data-[state=checked]:bg-muted")}
                  />
                </th>
              )}
              {/* 컬럼 헤더 */}
              {visibleColumns.map((col) => (
                <th
                  key={col.columnName}
                  className={cn(
                    "whitespace-nowrap border-b px-3 py-2 font-medium text-muted-foreground",
                    col.align === "center" && "text-center",
                    col.align === "right" && "text-right"
                  )}
                  style={{ width: col.width ? `${col.width}px` : "auto" }}
                >
                  {col.displayName || col.columnName}
                </th>
              ))}
            </tr>
          </thead>

          {/* 테이블 바디 */}
          <tbody>
            {groups.map((group) => (
              <React.Fragment key={group.groupKey}>
                {/* 그룹 헤더 */}
                <GroupHeader
                  group={group}
                  config={config}
                  onToggle={() => handleGroupToggle(group.groupKey)}
                  onSelectToggle={
                    config.showCheckbox
                      ? () => toggleGroupSelection(group.groupKey)
                      : undefined
                  }
                  style={config.groupHeaderStyle}
                  columnCount={totalColumnCount}
                />

                {/* 그룹 아이템 (펼쳐진 경우만) */}
                {group.expanded &&
                  group.items.map((item, idx) => {
                    const itemId = getItemId(item);
                    const isSelected = group.selectedItemIds?.includes(itemId);

                    return (
                      <tr
                        key={itemId}
                        className={cn(
                          "border-b transition-colors",
                          config.rowClickable && "cursor-pointer hover:bg-muted/50",
                          isSelected && "bg-primary/10"
                        )}
                        onClick={() => handleRowClick(item, group.groupKey, idx)}
                      >
                        {/* 체크박스 */}
                        {config.showCheckbox && (
                          <td
                            className="px-3 py-2"
                            onClick={(e) => e.stopPropagation()}
                          >
                            <Checkbox
                              checked={isSelected}
                              onCheckedChange={() =>
                                toggleItemSelection(group.groupKey, itemId)
                              }
                            />
                          </td>
                        )}

                        {/* 데이터 컬럼 */}
                        {visibleColumns.map((col) => {
                          const value = item[col.columnName];
                          let displayValue: React.ReactNode = value;

                          // 포맷 적용
                          if (col.format === "number" && typeof value === "number") {
                            displayValue = value.toLocaleString();
                          } else if (col.format === "currency" && typeof value === "number") {
                            displayValue = `₩${value.toLocaleString()}`;
                          } else if (col.format === "date" && value) {
                            displayValue = new Date(value).toLocaleDateString("ko-KR");
                          } else if (col.format === "boolean") {
                            displayValue = value ? "예" : "아니오";
                          }

                          return (
                            <td
                              key={col.columnName}
                              className={cn(
                                "px-3 py-2",
                                col.align === "center" && "text-center",
                                col.align === "right" && "text-right"
                              )}
                            >
                              {displayValue ?? "-"}
                            </td>
                          );
                        })}
                      </tr>
                    );
                  })}
              </React.Fragment>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

export default TableGroupedComponent;
