"use client";

import { useState, useCallback, useMemo, useEffect } from "react";
import {
  TableGroupedConfig,
  GroupState,
  GroupSummary,
  UseGroupedDataResult,
} from "../types";
import { apiClient } from "@/lib/api/client";

/**
 * 그룹 요약 데이터 계산
 */
function calculateSummary(
  items: any[],
  config: TableGroupedConfig
): GroupSummary {
  const summary: GroupSummary = {
    count: items.length,
  };

  const summaryConfig = config.groupConfig?.summary;
  if (!summaryConfig) return summary;

  // 합계 계산
  if (summaryConfig.sumColumns && summaryConfig.sumColumns.length > 0) {
    summary.sum = {};
    for (const col of summaryConfig.sumColumns) {
      summary.sum[col] = items.reduce((acc, item) => {
        const val = parseFloat(item[col]);
        return acc + (isNaN(val) ? 0 : val);
      }, 0);
    }
  }

  // 평균 계산
  if (summaryConfig.avgColumns && summaryConfig.avgColumns.length > 0) {
    summary.avg = {};
    for (const col of summaryConfig.avgColumns) {
      const validItems = items.filter(
        (item) => item[col] !== null && item[col] !== undefined
      );
      const sum = validItems.reduce((acc, item) => {
        const val = parseFloat(item[col]);
        return acc + (isNaN(val) ? 0 : val);
      }, 0);
      summary.avg[col] = validItems.length > 0 ? sum / validItems.length : 0;
    }
  }

  // 최대값 계산
  if (summaryConfig.maxColumns && summaryConfig.maxColumns.length > 0) {
    summary.max = {};
    for (const col of summaryConfig.maxColumns) {
      const values = items
        .map((item) => parseFloat(item[col]))
        .filter((v) => !isNaN(v));
      summary.max[col] = values.length > 0 ? Math.max(...values) : 0;
    }
  }

  // 최소값 계산
  if (summaryConfig.minColumns && summaryConfig.minColumns.length > 0) {
    summary.min = {};
    for (const col of summaryConfig.minColumns) {
      const values = items
        .map((item) => parseFloat(item[col]))
        .filter((v) => !isNaN(v));
      summary.min[col] = values.length > 0 ? Math.min(...values) : 0;
    }
  }

  return summary;
}

/**
 * 그룹 라벨 포맷팅
 */
function formatGroupLabel(
  groupValue: any,
  item: any,
  format?: string
): string {
  if (!format) {
    return String(groupValue ?? "(빈 값)");
  }

  // {value}를 그룹 값으로 치환
  let label = format.replace("{value}", String(groupValue ?? "(빈 값)"));

  // {컬럼명} 패턴을 해당 컬럼 값으로 치환
  const columnPattern = /\{([^}]+)\}/g;
  label = label.replace(columnPattern, (match, columnName) => {
    if (columnName === "value") return String(groupValue ?? "");
    return String(item?.[columnName] ?? "");
  });

  return label;
}

/**
 * 데이터를 그룹화하는 훅
 */
export function useGroupedData(
  config: TableGroupedConfig,
  externalData?: any[],
  searchFilters?: Record<string, any>
): UseGroupedDataResult {
  // 원본 데이터
  const [rawData, setRawData] = useState<any[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // 그룹 펼침 상태 관리
  const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set());
  // 사용자가 수동으로 펼침/접기를 조작했는지 여부
  const [isManuallyControlled, setIsManuallyControlled] = useState(false);

  // 선택 상태 관리
  const [selectedItemIds, setSelectedItemIds] = useState<Set<string>>(
    new Set()
  );

  // 테이블명 결정
  const tableName = config.useCustomTable
    ? config.customTableName
    : config.selectedTable;

  // 데이터 로드
  const fetchData = useCallback(async () => {
    if (externalData) {
      setRawData(externalData);
      return;
    }

    if (!tableName) {
      setRawData([]);
      return;
    }

    setIsLoading(true);
    setError(null);

    try {
      const response = await apiClient.post(
        `/table-management/tables/${tableName}/data`,
        {
          page: 1,
          size: 10000, // 그룹화를 위해 전체 데이터 로드
          autoFilter: true,
          search: searchFilters || {},
        }
      );

      let responseData = response.data?.data?.data || response.data?.data || [];
      responseData = Array.isArray(responseData) ? responseData : [];

      // dataFilter 적용 (클라이언트 사이드 필터링)
      if (config.dataFilter && config.dataFilter.length > 0) {
        responseData = responseData.filter((item: any) => {
          return config.dataFilter!.every((f) => {
            const val = item[f.column];
            switch (f.operator) {
              case "eq": return val === f.value;
              case "ne": return f.value === null ? (val !== null && val !== undefined && val !== "") : val !== f.value;
              case "gt": return Number(val) > Number(f.value);
              case "lt": return Number(val) < Number(f.value);
              case "gte": return Number(val) >= Number(f.value);
              case "lte": return Number(val) <= Number(f.value);
              case "like": return String(val ?? "").includes(String(f.value));
              case "in": return Array.isArray(f.value) ? f.value.includes(val) : false;
              default: return true;
            }
          });
        });
      }

      setRawData(responseData);
    } catch (err: any) {
      setError(err.message || "데이터 로드 중 오류 발생");
      setRawData([]);
    } finally {
      setIsLoading(false);
    }
  }, [tableName, externalData, searchFilters, config.dataFilter]);

  // 초기 데이터 로드
  useEffect(() => {
    fetchData();
  }, [fetchData]);

  // 외부 데이터 변경 시 동기화
  useEffect(() => {
    if (externalData) {
      setRawData(externalData);
    }
  }, [externalData]);

  // 그룹화된 데이터 계산
  const groups = useMemo((): GroupState[] => {
    const groupByColumn = config.groupConfig?.groupByColumn;
    if (!groupByColumn || rawData.length === 0) {
      return [];
    }

    // 데이터를 그룹별로 분류
    const groupMap = new Map<string, any[]>();

    for (const item of rawData) {
      const groupValue = item[groupByColumn];
      const groupKey = String(groupValue ?? "__null__");

      if (!groupMap.has(groupKey)) {
        groupMap.set(groupKey, []);
      }
      groupMap.get(groupKey)!.push(item);
    }

    // 그룹 배열 생성
    const groupArray: GroupState[] = [];
    const defaultExpanded = config.groupConfig?.defaultExpanded ?? true;

    for (const [groupKey, items] of groupMap.entries()) {
      const firstItem = items[0];
      const groupValue =
        groupKey === "__null__" ? null : firstItem[groupByColumn];

      // 펼침 상태 결정: 수동 조작 전에는 defaultExpanded, 수동 조작 후에는 expandedGroups 참조
      const isExpanded = isManuallyControlled
        ? expandedGroups.has(groupKey)
        : defaultExpanded;

      groupArray.push({
        groupKey,
        groupLabel: formatGroupLabel(
          groupValue,
          firstItem,
          config.groupConfig?.groupLabelFormat
        ),
        expanded: isExpanded,
        items,
        summary: calculateSummary(items, config),
        selected: items.every((item) =>
          selectedItemIds.has(getItemId(item, config))
        ),
        selectedItemIds: items
          .filter((item) => selectedItemIds.has(getItemId(item, config)))
          .map((item) => getItemId(item, config)),
      });
    }

    // 정렬
    const sortDirection = config.groupConfig?.sortDirection ?? "asc";
    groupArray.sort((a, b) => {
      const comparison = a.groupLabel.localeCompare(b.groupLabel, "ko");
      return sortDirection === "asc" ? comparison : -comparison;
    });

    return groupArray;
  }, [rawData, config, expandedGroups, selectedItemIds, isManuallyControlled]);

  // 아이템 ID 추출
  function getItemId(item: any, cfg: TableGroupedConfig): string {
    // id 또는 첫 번째 컬럼을 ID로 사용
    if (item.id !== undefined) return String(item.id);
    const firstCol = cfg.columns?.[0]?.columnName;
    if (firstCol && item[firstCol] !== undefined) return String(item[firstCol]);
    return JSON.stringify(item);
  }

  // 그룹 토글
  const toggleGroup = useCallback((groupKey: string) => {
    setIsManuallyControlled(true);
    setExpandedGroups((prev) => {
      const next = new Set(prev);
      if (next.has(groupKey)) {
        next.delete(groupKey);
      } else {
        next.add(groupKey);
      }
      return next;
    });
  }, []);

  // 전체 펼치기
  const expandAll = useCallback(() => {
    setIsManuallyControlled(true);
    setExpandedGroups(new Set(groups.map((g) => g.groupKey)));
  }, [groups]);

  // 전체 접기
  const collapseAll = useCallback(() => {
    setIsManuallyControlled(true);
    setExpandedGroups(new Set());
  }, []);

  // 아이템 선택 토글
  const toggleItemSelection = useCallback(
    (groupKey: string, itemId: string) => {
      setSelectedItemIds((prev) => {
        const next = new Set(prev);
        if (next.has(itemId)) {
          next.delete(itemId);
        } else {
          // 단일 선택 모드
          if (config.checkboxMode === "single") {
            next.clear();
          }
          next.add(itemId);
        }
        return next;
      });
    },
    [config.checkboxMode]
  );

  // 그룹 전체 선택 토글
  const toggleGroupSelection = useCallback(
    (groupKey: string) => {
      const group = groups.find((g) => g.groupKey === groupKey);
      if (!group) return;

      setSelectedItemIds((prev) => {
        const next = new Set(prev);
        const groupItemIds = group.items.map((item) => getItemId(item, config));
        const allSelected = groupItemIds.every((id) => next.has(id));

        if (allSelected) {
          // 전체 해제
          for (const id of groupItemIds) {
            next.delete(id);
          }
        } else {
          // 전체 선택
          if (config.checkboxMode === "single") {
            next.clear();
            next.add(groupItemIds[0]);
          } else {
            for (const id of groupItemIds) {
              next.add(id);
            }
          }
        }
        return next;
      });
    },
    [groups, config]
  );

  // 전체 선택 토글
  const toggleAllSelection = useCallback(() => {
    const allItemIds = rawData.map((item) => getItemId(item, config));
    const allSelected = allItemIds.every((id) => selectedItemIds.has(id));

    if (allSelected) {
      setSelectedItemIds(new Set());
    } else {
      if (config.checkboxMode === "single" && allItemIds.length > 0) {
        setSelectedItemIds(new Set([allItemIds[0]]));
      } else {
        setSelectedItemIds(new Set(allItemIds));
      }
    }
  }, [rawData, config, selectedItemIds]);

  // 선택된 아이템 목록
  const selectedItems = useMemo(() => {
    return rawData.filter((item) =>
      selectedItemIds.has(getItemId(item, config))
    );
  }, [rawData, selectedItemIds, config]);

  // 모두 선택 여부
  const isAllSelected = useMemo(() => {
    if (rawData.length === 0) return false;
    return rawData.every((item) =>
      selectedItemIds.has(getItemId(item, config))
    );
  }, [rawData, selectedItemIds, config]);

  // 일부 선택 여부
  const isIndeterminate = useMemo(() => {
    if (rawData.length === 0) return false;
    const selectedCount = rawData.filter((item) =>
      selectedItemIds.has(getItemId(item, config))
    ).length;
    return selectedCount > 0 && selectedCount < rawData.length;
  }, [rawData, selectedItemIds, config]);

  return {
    groups,
    isLoading,
    error,
    toggleGroup,
    expandAll,
    collapseAll,
    toggleItemSelection,
    toggleGroupSelection,
    toggleAllSelection,
    selectedItems,
    isAllSelected,
    isIndeterminate,
    refresh: fetchData,
    rawData,
    totalCount: rawData.length,
    groupCount: groups.length,
  };
}

export default useGroupedData;
