"use client";

import React, { useEffect, useState, useCallback, useMemo } from "react";
import { DashboardElement, ChartDataSource } from "@/components/admin/dashboard/types";
import { Button } from "@/components/ui/button";
import { Loader2, RefreshCw } from "lucide-react";
import { applyColumnMapping } from "@/lib/utils/columnMapping";
import {
  LineChart,
  Line,
  BarChart,
  Bar,
  PieChart,
  Pie,
  Cell,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer,
  ComposedChart, // 🆕 바/라인/영역 혼합 차트
  Area, // 🆕 영역 차트
} from "recharts";

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);

  console.log("🧪 ChartTestWidget 렌더링!", element);

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

  // 다중 데이터 소스 로딩
  const loadMultipleDataSources = useCallback(async () => {
    // dataSources는 element.dataSources 또는 chartConfig.dataSources에서 로드
    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]);

  // 수동 새로고침 핸들러
  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("/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) {
      // 외부 DB (ExternalDbConnectionAPI 사용)
      const { ExternalDbConnectionAPI } = await import("@/lib/api/externalDbConnection");
      result = await ExternalDbConnectionAPI.executeQuery(parseInt(source.externalConnectionId), source.query);
    } else {
      // 현재 DB (dashboardApi.executeQuery 사용)
      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 || [];

    console.log("💾 내부 DB 쿼리 결과:", {
      hasRows: !!rows,
      rowCount: rows.length,
      hasColumns: rows.length > 0 && Object.keys(rows[0]).length > 0,
      columnCount: rows.length > 0 ? Object.keys(rows[0]).length : 0,
      firstRow: rows[0],
    });

    // 컬럼 매핑 적용
    const mappedRows = applyColumnMapping(rows, source.columnMapping);

    console.log("✅ 매핑 후:", {
      columns: mappedRows.length > 0 ? Object.keys(mappedRows[0]) : [],
      rowCount: mappedRows.length,
      firstMappedRow: mappedRows[0],
    });

    return mappedRows;
  };

  // 초기 로드
  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 || [];

  // 멀티 데이터 소스 차트 렌더링
  const renderChart = () => {
    if (data.length === 0) {
      return (
        <div className="flex h-full items-center justify-center">
          <p className="text-muted-foreground text-sm">데이터가 없습니다</p>
        </div>
      );
    }

    if (dataSourceConfigs.length === 0) {
      return (
        <div className="flex h-full items-center justify-center">
          <p className="text-muted-foreground text-sm">
            차트 설정에서 데이터 소스를 추가하고
            <br />
            X축, Y축을 설정해주세요
          </p>
        </div>
      );
    }

    // 병합 모드: 여러 데이터 소스를 하나의 라인/바로 합침
    if (mergeMode && dataSourceConfigs.length > 1) {
      const chartData: any[] = [];
      const allXValues = new Set<string>();

      // 첫 번째 데이터 소스의 설정을 기준으로 사용
      const baseConfig = dataSourceConfigs[0];
      const xAxisField = baseConfig.xAxis;
      const yAxisField = baseConfig.yAxis[0];

      // 모든 데이터 소스에서 데이터 수집 (X축 값 기준)
      dataSourceConfigs.forEach((dsConfig) => {
        const sourceName = dataSources.find((ds) => ds.id === dsConfig.dataSourceId)?.name;
        const sourceData = data.filter((item) => item._source === sourceName);

        sourceData.forEach((item) => {
          const xValue = item[xAxisField];
          if (xValue !== undefined) {
            allXValues.add(String(xValue));
          }
        });
      });

      // X축 값별로 Y축 값 합산
      allXValues.forEach((xValue) => {
        const dataPoint: any = { _xValue: xValue };
        let totalYValue = 0;

        dataSourceConfigs.forEach((dsConfig) => {
          const sourceName = dataSources.find((ds) => ds.id === dsConfig.dataSourceId)?.name;
          const sourceData = data.filter((item) => item._source === sourceName);
          const matchingItem = sourceData.find((item) => String(item[xAxisField]) === xValue);

          if (matchingItem && yAxisField) {
            const yValue = parseFloat(matchingItem[yAxisField]) || 0;
            totalYValue += yValue;
          }
        });

        dataPoint[yAxisField] = totalYValue;
        chartData.push(dataPoint);
      });

      console.log("🔗 병합 모드 차트 데이터:", chartData);

      // 병합 모드 차트 렌더링
      switch (chartType) {
        case "line":
          return (
            <ResponsiveContainer width="100%" height="100%">
              <LineChart data={chartData}>
                <CartesianGrid strokeDasharray="3 3" />
                <XAxis dataKey="_xValue" />
                <YAxis />
                <Tooltip />
                <Legend />
                <Line type="monotone" dataKey={yAxisField} name={yAxisField} stroke={COLORS[0]} strokeWidth={2} />
              </LineChart>
            </ResponsiveContainer>
          );

        case "bar":
          return (
            <ResponsiveContainer width="100%" height="100%">
              <BarChart data={chartData}>
                <CartesianGrid strokeDasharray="3 3" />
                <XAxis dataKey="_xValue" />
                <YAxis />
                <Tooltip />
                <Legend />
                <Bar dataKey={yAxisField} name={yAxisField} fill={COLORS[0]} />
              </BarChart>
            </ResponsiveContainer>
          );

        case "area":
          return (
            <ResponsiveContainer width="100%" height="100%">
              <LineChart data={chartData}>
                <CartesianGrid strokeDasharray="3 3" />
                <XAxis dataKey="_xValue" />
                <YAxis />
                <Tooltip />
                <Legend />
                <Line
                  type="monotone"
                  dataKey={yAxisField}
                  name={yAxisField}
                  stroke={COLORS[0]}
                  fill={COLORS[0]}
                  fillOpacity={0.3}
                  strokeWidth={2}
                />
              </LineChart>
            </ResponsiveContainer>
          );

        default:
          return (
            <div className="flex h-full items-center justify-center">
              <p className="text-muted-foreground text-sm">병합 모드는 라인, 바, 영역 차트만 지원합니다</p>
            </div>
          );
      }
    }

    // 일반 모드: 각 데이터 소스를 별도의 라인/바로 표시
    const chartData: any[] = [];
    const allXValues = new Set<string>();

    // 1단계: 모든 X축 값 수집
    dataSourceConfigs.forEach((dsConfig) => {
      const sourceData = data.filter((item) => {
        const sourceName = dataSources.find((ds) => ds.id === dsConfig.dataSourceId)?.name;
        return item._source === sourceName;
      });

      sourceData.forEach((item) => {
        const xValue = item[dsConfig.xAxis];
        if (xValue !== undefined) {
          allXValues.add(String(xValue));
        }
      });
    });

    // 2단계: X축 값별로 데이터 병합
    allXValues.forEach((xValue) => {
      const dataPoint: any = { _xValue: xValue };

      dataSourceConfigs.forEach((dsConfig, index) => {
        const sourceName = dataSources.find((ds) => ds.id === dsConfig.dataSourceId)?.name || `소스 ${index + 1}`;
        const sourceData = data.filter((item) => item._source === sourceName);
        const matchingItem = sourceData.find((item) => String(item[dsConfig.xAxis]) === xValue);

        if (matchingItem && dsConfig.yAxis.length > 0) {
          const yField = dsConfig.yAxis[0];
          dataPoint[`${sourceName}_${yField}`] = matchingItem[yField];
        }
      });

      chartData.push(dataPoint);
    });

    console.log("📊 일반 모드 차트 데이터:", chartData);
    console.log("📊 데이터 소스 설정:", dataSourceConfigs);

    // 🆕 혼합 차트 타입 감지 (각 데이터 소스마다 다른 차트 타입이 설정된 경우)
    const isMixedChart = dataSourceConfigs.some((dsConfig) => dsConfig.chartType);
    const effectiveChartType = isMixedChart ? "mixed" : chartType;

    // 차트 타입별 렌더링
    switch (effectiveChartType) {
      case "mixed":
      case "line":
      case "bar":
      case "area":
        // 🆕 ComposedChart 사용 (바/라인/영역 혼합 가능)
        return (
          <ResponsiveContainer width="100%" height="100%">
            <ComposedChart data={chartData}>
              <CartesianGrid strokeDasharray="3 3" />
              <XAxis dataKey="_xValue" />
              <YAxis />
              <Tooltip />
              <Legend />
              {dataSourceConfigs.map((dsConfig, index) => {
                const sourceName =
                  dataSources.find((ds) => ds.id === dsConfig.dataSourceId)?.name || `소스 ${index + 1}`;
                const yField = dsConfig.yAxis[0];
                const dataKey = `${sourceName}_${yField}`;
                const label = dsConfig.label || sourceName;
                const color = COLORS[index % COLORS.length];

                // 개별 차트 타입 또는 전역 차트 타입 사용
                const individualChartType = dsConfig.chartType || chartType;

                // 차트 타입에 따라 다른 컴포넌트 렌더링
                switch (individualChartType) {
                  case "bar":
                    return <Bar key={dsConfig.dataSourceId} dataKey={dataKey} name={label} fill={color} />;
                  case "area":
                    return (
                      <Area
                        key={dsConfig.dataSourceId}
                        type="monotone"
                        dataKey={dataKey}
                        name={label}
                        stroke={color}
                        fill={color}
                        fillOpacity={0.3}
                        strokeWidth={2}
                      />
                    );
                  case "line":
                  default:
                    return (
                      <Line
                        key={dsConfig.dataSourceId}
                        type="monotone"
                        dataKey={dataKey}
                        name={label}
                        stroke={color}
                        strokeWidth={2}
                      />
                    );
                }
              })}
            </ComposedChart>
          </ResponsiveContainer>
        );

      case "pie":
      case "donut":
        // 파이 차트는 첫 번째 데이터 소스만 사용
        if (dataSourceConfigs.length > 0) {
          const firstConfig = dataSourceConfigs[0];
          const sourceName = dataSources.find((ds) => ds.id === firstConfig.dataSourceId)?.name;

          // 해당 데이터 소스의 데이터만 필터링
          const sourceData = data.filter((item) => item._source === sourceName);

          console.log("🍩 도넛/파이 차트 데이터:", {
            sourceName,
            totalData: data.length,
            filteredData: sourceData.length,
            firstConfig,
            sampleItem: sourceData[0],
          });

          // 파이 차트용 데이터 변환
          const pieData = sourceData.map((item) => ({
            name: String(item[firstConfig.xAxis] || "Unknown"),
            value: Number(item[firstConfig.yAxis[0]]) || 0,
          }));

          console.log("🍩 변환된 파이 데이터:", pieData);
          console.log("🍩 첫 번째 데이터:", pieData[0]);
          console.log("🍩 데이터 타입 체크:", {
            firstValue: pieData[0]?.value,
            valueType: typeof pieData[0]?.value,
            isNumber: typeof pieData[0]?.value === "number",
          });

          if (pieData.length === 0) {
            return (
              <div className="flex h-full items-center justify-center">
                <p className="text-muted-foreground text-sm">파이 차트에 표시할 데이터가 없습니다.</p>
              </div>
            );
          }

          // value가 모두 0인지 체크
          const totalValue = pieData.reduce((sum, item) => sum + (item.value || 0), 0);
          if (totalValue === 0) {
            return (
              <div className="flex h-full items-center justify-center">
                <p className="text-muted-foreground text-sm">모든 값이 0입니다. Y축 필드를 확인해주세요.</p>
              </div>
            );
          }

          return (
            <ResponsiveContainer width="100%" height="100%">
              <PieChart>
                <Pie
                  data={pieData}
                  dataKey="value"
                  nameKey="name"
                  cx="50%"
                  cy="50%"
                  outerRadius="70%"
                  innerRadius={chartType === "donut" ? "45%" : 0}
                  label={(entry) => `${entry.name}: ${entry.value}`}
                  labelLine={true}
                  fill="#8884d8"
                >
                  {pieData.map((entry, index) => (
                    <Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
                  ))}
                </Pie>
                <Tooltip />
                <Legend verticalAlign="bottom" height={36} />
              </PieChart>
            </ResponsiveContainer>
          );
        }
        return (
          <div className="flex h-full items-center justify-center">
            <p className="text-muted-foreground text-sm">파이 차트를 표시하려면 데이터 소스를 설정하세요.</p>
          </div>
        );

      default:
        return (
          <div className="flex h-full items-center justify-center">
            <p className="text-muted-foreground text-sm">지원하지 않는 차트 타입: {chartType}</p>
          </div>
        );
    }
  };

  return (
    <div className="bg-background flex h-full w-full flex-col">
      <div className="flex items-center justify-between border-b p-4">
        <div>
          <h3 className="text-lg font-semibold">{element?.customTitle || "차트"}</h3>
          <p className="text-muted-foreground text-xs">
            {dataSources?.length || 0}개 데이터 소스 • {data.length}개 데이터
            {lastRefreshTime && <span className="ml-2">• {lastRefreshTime.toLocaleTimeString("ko-KR")}</span>}
          </p>
        </div>
        <div className="flex items-center gap-2">
          <Button
            variant="outline"
            size="sm"
            onClick={handleManualRefresh}
            disabled={loading}
            className="h-8 gap-2 text-xs"
          >
            <RefreshCw className={`h-3 w-3 ${loading ? "animate-spin" : ""}`} />
            새로고침
          </Button>
          {loading && <Loader2 className="h-4 w-4 animate-spin" />}
        </div>
      </div>

      <div className="flex-1 p-4">
        {error ? (
          <div className="flex h-full items-center justify-center">
            <p className="text-destructive text-sm">{error}</p>
          </div>
        ) : !(element?.dataSources || element?.chartConfig?.dataSources) ||
          (element?.dataSources || element?.chartConfig?.dataSources)?.length === 0 ? (
          <div className="flex h-full items-center justify-center">
            <p className="text-muted-foreground text-sm">데이터 소스를 연결해주세요</p>
          </div>
        ) : (
          renderChart()
        )}
      </div>

      {data.length > 0 && (
        <div className="text-muted-foreground border-t p-2 text-xs">총 {data.length}개 데이터 표시 중</div>
      )}
    </div>
  );
}
