"use client";

import React, { useEffect, useState, useCallback, useMemo, useRef } from "react";
import { DashboardElement, ChartDataSource, ChartData } from "@/components/admin/dashboard/types";
import { Button } from "@/components/ui/button";
import { Loader2, RefreshCw } from "lucide-react";
import { applyColumnMapping } from "@/lib/utils/columnMapping";
import { getApiUrl } from "@/lib/utils/apiUrl";
import { Chart } from "@/components/admin/dashboard/charts/Chart";

interface ChartTestWidgetProps {
  element: DashboardElement;
}

const COLORS = ["#3b82f6", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#ec4899"];

export default function ChartTestWidget({ element }: ChartTestWidgetProps) {
  const [data, setData] = useState<any[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [lastRefreshTime, setLastRefreshTime] = useState<Date | null>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const [containerSize, setContainerSize] = useState({ width: 600, height: 400 });

  // console.log("🧪 ChartTestWidget 렌더링 (D3 기반)!", element);

  const dataSources = useMemo(() => {
    return element?.dataSources || element?.chartConfig?.dataSources;
  }, [element?.dataSources, element?.chartConfig?.dataSources]);

  // 컨테이너 크기 측정
  useEffect(() => {
    const updateSize = () => {
      if (containerRef.current) {
        const width = containerRef.current.offsetWidth || 600;
        const height = containerRef.current.offsetHeight || 400;
        setContainerSize({ width, height });
      }
    };

    updateSize();
    window.addEventListener("resize", updateSize);
    return () => window.removeEventListener("resize", updateSize);
  }, []);

  // 다중 데이터 소스 로딩
  const loadMultipleDataSources = useCallback(async () => {
    const dataSources = element?.dataSources || element?.chartConfig?.dataSources;

    if (!dataSources || dataSources.length === 0) {
      // console.log("⚠️ 데이터 소스가 없습니다.");
      return;
    }

    // console.log(`🔄 ${dataSources.length}개의 데이터 소스 로딩 시작...`);
    setLoading(true);
    setError(null);

    try {
      const results = await Promise.allSettled(
        dataSources.map(async (source) => {
          try {
            // console.log(`📡 데이터 소스 "${source.name || source.id}" 로딩 중...`);

            if (source.type === "api") {
              return await loadRestApiData(source);
            } else if (source.type === "database") {
              return await loadDatabaseData(source);
            }

            return [];
          } catch (err: any) {
            console.error(`❌ 데이터 소스 "${source.name || source.id}" 로딩 실패:`, err);
            return [];
          }
        }),
      );

      const allData: any[] = [];
      results.forEach((result, index) => {
        if (result.status === "fulfilled" && Array.isArray(result.value)) {
          const sourceData = result.value.map((item: any) => ({
            ...item,
            _source: dataSources[index].name || dataSources[index].id || `소스 ${index + 1}`,
          }));
          allData.push(...sourceData);
        }
      });

      // console.log(`✅ 총 ${allData.length}개의 데이터 로딩 완료`);
      setData(allData);
      setLastRefreshTime(new Date());
    } catch (err: any) {
      console.error("❌ 데이터 로딩 중 오류:", err);
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }, [element?.dataSources, element?.chartConfig?.dataSources]);

  // 수동 새로고침
  const handleManualRefresh = useCallback(() => {
    // console.log("🔄 수동 새로고침 버튼 클릭");
    loadMultipleDataSources();
  }, [loadMultipleDataSources]);

  // REST API 데이터 로딩
  const loadRestApiData = async (source: ChartDataSource): Promise<any[]> => {
    if (!source.endpoint) {
      throw new Error("API endpoint가 없습니다.");
    }

    const queryParams: Record<string, string> = {};
    if (source.queryParams) {
      source.queryParams.forEach((param) => {
        if (param.key && param.value) {
          queryParams[param.key] = param.value;
        }
      });
    }

    const headers: Record<string, string> = {};
    if (source.headers) {
      source.headers.forEach((header) => {
        if (header.key && header.value) {
          headers[header.key] = header.value;
        }
      });
    }

    const response = await fetch(getApiUrl("/api/dashboards/fetch-external-api"), {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      credentials: "include",
      body: JSON.stringify({
        url: source.endpoint,
        method: source.method || "GET",
        headers,
        queryParams,
      }),
    });

    if (!response.ok) {
      throw new Error(`API 호출 실패: ${response.status}`);
    }

    const result = await response.json();
    if (!result.success) {
      throw new Error(result.message || "API 호출 실패");
    }

    let apiData = result.data;
    if (source.jsonPath) {
      const pathParts = source.jsonPath.split(".");
      for (const part of pathParts) {
        apiData = apiData?.[part];
      }
    }

    const rows = Array.isArray(apiData) ? apiData : [apiData];
    return applyColumnMapping(rows, source.columnMapping);
  };

  // Database 데이터 로딩
  const loadDatabaseData = async (source: ChartDataSource): Promise<any[]> => {
    if (!source.query) {
      throw new Error("SQL 쿼리가 없습니다.");
    }

    let result;
    if (source.connectionType === "external" && source.externalConnectionId) {
      const { ExternalDbConnectionAPI } = await import("@/lib/api/externalDbConnection");
      result = await ExternalDbConnectionAPI.executeQuery(parseInt(source.externalConnectionId), source.query);
    } else {
      const { dashboardApi } = await import("@/lib/api/dashboard");

      try {
        const queryResult = await dashboardApi.executeQuery(source.query);
        result = {
          success: true,
          rows: queryResult.rows || [],
        };
      } catch (err: any) {
        console.error("❌ 내부 DB 쿼리 실패:", err);
        throw new Error(err.message || "쿼리 실패");
      }
    }

    if (!result.success) {
      throw new Error(result.message || "쿼리 실패");
    }

    const rows = result.rows || result.data || [];
    return applyColumnMapping(rows, source.columnMapping);
  };

  // 초기 로드
  useEffect(() => {
    if (dataSources && dataSources.length > 0) {
      loadMultipleDataSources();
    }
  }, [dataSources, loadMultipleDataSources]);

  // 자동 새로고침
  useEffect(() => {
    if (!dataSources || dataSources.length === 0) return;

    const intervals = dataSources
      .map((ds) => ds.refreshInterval)
      .filter((interval): interval is number => typeof interval === "number" && interval > 0);

    if (intervals.length === 0) return;

    const minInterval = Math.min(...intervals);
    // console.log(`⏱️ 자동 새로고침 설정: ${minInterval}초마다`);

    const intervalId = setInterval(() => {
      // console.log("🔄 자동 새로고침 실행");
      loadMultipleDataSources();
    }, minInterval * 1000);

    return () => {
      // console.log("⏹️ 자동 새로고침 정리");
      clearInterval(intervalId);
    };
  }, [dataSources, loadMultipleDataSources]);

  const chartConfig = element?.chartConfig || {};
  const chartType = chartConfig.chartType || "line";
  const mergeMode = chartConfig.mergeMode || false;
  const dataSourceConfigs = chartConfig.dataSourceConfigs || [];

  // 데이터를 D3 Chart 컴포넌트 형식으로 변환
  const chartData = useMemo((): ChartData | null => {
    if (data.length === 0 || dataSourceConfigs.length === 0) {
      return null;
    }

    const labels = new Set<string>();
    const datasets: any[] = [];

    // 병합 모드: 여러 데이터 소스를 하나로 합침
    if (mergeMode && dataSourceConfigs.length > 1) {
      // console.log("🔀 병합 모드 활성화");
      
      // 모든 데이터 소스의 X축 필드 수집 (첫 번째 데이터 소스의 X축 사용)
      const baseConfig = dataSourceConfigs[0];
      const xAxisField = baseConfig.xAxis;
      
      // console.log("📊 X축 필드:", xAxisField);

      // X축 값 수집 (모든 데이터 소스에서)
      dataSourceConfigs.forEach((dsConfig, idx) => {
        const sourceName = dataSources?.find((ds) => ds.id === dsConfig.dataSourceId)?.name;
        const sourceData = data.filter((item) => item._source === sourceName);
        // console.log(`  소스 ${idx + 1} (${sourceName}): ${sourceData.length}개 행`);
        
        sourceData.forEach((item) => {
          if (item[xAxisField] !== undefined) {
            labels.add(String(item[xAxisField]));
          }
        });
      });

      // console.log("📍 수집된 X축 라벨:", Array.from(labels));

      // 각 데이터 소스별로 데이터셋 생성 (병합하지 않고 각각 표시)
      dataSourceConfigs.forEach((dsConfig, idx) => {
        const sourceName = dataSources?.find((ds) => ds.id === dsConfig.dataSourceId)?.name || `소스 ${idx + 1}`;
        const sourceData = data.filter((item) => item._source === sourceName);
        
        // 각 Y축 필드마다 데이터셋 생성
        (dsConfig.yAxis || []).forEach((yAxisField, yIdx) => {
          const datasetData: number[] = [];
          
          labels.forEach((label) => {
            const matchingItem = sourceData.find((item) => String(item[xAxisField]) === label);
            const value = matchingItem && yAxisField ? parseFloat(matchingItem[yAxisField]) || 0 : 0;
            datasetData.push(value);
          });

          // console.log(`  📈 ${sourceName} - ${yAxisField}: [${datasetData.join(", ")}]`);

          datasets.push({
            label: `${sourceName} - ${yAxisField}`,
            data: datasetData,
            backgroundColor: COLORS[(idx * 2 + yIdx) % COLORS.length],
            borderColor: COLORS[(idx * 2 + yIdx) % COLORS.length],
            type: dsConfig.chartType || chartType, // 데이터 소스별 차트 타입
          });
        });
      });

      // console.log("✅ 병합 모드 데이터셋 생성 완료:", datasets.length, "개");
    } else {
      // 일반 모드: 각 데이터 소스를 별도로 표시
      dataSourceConfigs.forEach((dsConfig, index) => {
        const sourceName = dataSources?.find((ds) => ds.id === dsConfig.dataSourceId)?.name || `소스 ${index + 1}`;
        const sourceData = data.filter((item) => item._source === sourceName);

        // X축 값 수집
        sourceData.forEach((item) => {
          const xValue = item[dsConfig.xAxis];
          if (xValue !== undefined) {
            labels.add(String(xValue));
          }
        });

        // Y축 데이터 수집
        const yField = dsConfig.yAxis[0];
        const dataValues: number[] = [];

        labels.forEach((label) => {
          const matchingItem = sourceData.find((item) => String(item[dsConfig.xAxis]) === label);
          dataValues.push(matchingItem && yField ? parseFloat(matchingItem[yField]) || 0 : 0);
        });

        datasets.push({
          label: dsConfig.label || sourceName,
          data: dataValues,
          color: COLORS[index % COLORS.length],
        });
      });
    }

    return {
      labels: Array.from(labels),
      datasets,
    };
  }, [data, dataSourceConfigs, mergeMode, dataSources]);

  return (
    <div className="flex h-full w-full flex-col bg-white">
      {/* 차트 영역 - 전체 공간 사용 */}
      <div ref={containerRef} className="flex-1 overflow-hidden p-2">
        {error ? (
          <div className="flex h-full items-center justify-center">
            <p className="text-destructive text-sm">{error}</p>
          </div>
        ) : !dataSources || dataSources.length === 0 ? (
          <div className="flex h-full items-center justify-center">
            <p className="text-muted-foreground text-sm">데이터 소스를 연결해주세요</p>
          </div>
        ) : loading && data.length === 0 ? (
          <div className="flex h-full items-center justify-center">
            <div className="text-center">
              <Loader2 className="mx-auto h-8 w-8 animate-spin text-primary" />
              <p className="text-muted-foreground mt-2 text-xs">데이터 로딩 중...</p>
            </div>
          </div>
        ) : !chartData ? (
          <div className="flex h-full items-center justify-center">
            <p className="text-muted-foreground text-center text-sm">
              차트 설정에서 데이터 소스를 추가하고
              <br />
              X축, Y축을 설정해주세요
            </p>
          </div>
        ) : (
          <Chart
            chartType={chartType as any}
            data={chartData}
            config={chartConfig}
            width={containerSize.width - 16}
            height={containerSize.height - 16}
          />
        )}
      </div>

      {/* 푸터 - 주석 처리 (공간 확보) */}
      {/* {data.length > 0 && (
        <div className="text-muted-foreground border-t px-3 py-1.5 text-[10px]">
          총 {data.length.toLocaleString()}개 데이터 표시 중
        </div>
      )} */}
    </div>
  );
}
