"use client";

import React, { useState, useEffect } from "react";
import { DashboardElement } from "@/components/admin/dashboard/types";
import { getApiUrl } from "@/lib/utils/apiUrl";

interface CustomMetricWidgetProps {
  element?: DashboardElement;
}

// 집계 함수 실행
const calculateMetric = (rows: any[], field: string, aggregation: string): number => {
  if (rows.length === 0) return 0;

  switch (aggregation) {
    case "count":
      return rows.length;
    case "sum": {
      return rows.reduce((sum, row) => sum + (parseFloat(row[field]) || 0), 0);
    }
    case "avg": {
      const sum = rows.reduce((s, row) => s + (parseFloat(row[field]) || 0), 0);
      return rows.length > 0 ? sum / rows.length : 0;
    }
    case "min": {
      return Math.min(...rows.map((row) => parseFloat(row[field]) || 0));
    }
    case "max": {
      return Math.max(...rows.map((row) => parseFloat(row[field]) || 0));
    }
    default:
      return 0;
  }
};

// 색상 스타일 매핑
const colorMap = {
  indigo: { bg: "bg-muted", text: "text-foreground", border: "border-border" },
  green: { bg: "bg-muted", text: "text-foreground", border: "border-border" },
  blue: { bg: "bg-muted", text: "text-foreground", border: "border-border" },
  purple: { bg: "bg-muted", text: "text-foreground", border: "border-border" },
  orange: { bg: "bg-muted", text: "text-foreground", border: "border-border" },
  gray: { bg: "bg-muted", text: "text-foreground", border: "border-border" },
};

export default function CustomMetricWidget({ element }: CustomMetricWidgetProps) {
  const [metrics, setMetrics] = useState<any[]>([]);
  const [groupedCards, setGroupedCards] = useState<Array<{ label: string; value: number }>>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const isGroupByMode = element?.customMetricConfig?.groupByMode || false;

  useEffect(() => {
    loadData();

    // 자동 새로고침 (30초마다)
    const interval = setInterval(loadData, 30000);
    return () => clearInterval(interval);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [element]);

  const loadData = async () => {
    try {
      setLoading(true);
      setError(null);

      // 그룹별 카드 데이터 로드
      if (isGroupByMode && element?.customMetricConfig?.groupByDataSource) {
        await loadGroupByData();
      }

      // 일반 지표 데이터 로드
      if (element?.customMetricConfig?.metrics && element?.customMetricConfig.metrics.length > 0) {
        await loadMetricsData();
      }
    } catch (err) {
      console.error("데이터 로드 실패:", err);
      setError(err instanceof Error ? err.message : "데이터를 불러올 수 없습니다");
    } finally {
      setLoading(false);
    }
  };

  // 그룹별 카드 데이터 로드
  const loadGroupByData = async () => {
    const groupByDS = element?.customMetricConfig?.groupByDataSource;
    if (!groupByDS) return;

    const dataSourceType = groupByDS.type;

    // Database 타입
    if (dataSourceType === "database") {
      if (!groupByDS.query) return;

      const token = localStorage.getItem("authToken");
      const response = await fetch(getApiUrl("/api/dashboards/execute-query"), {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify({
          query: groupByDS.query,
          connectionType: groupByDS.connectionType || "current",
          connectionId: (groupByDS as any).connectionId,
        }),
      });

      if (!response.ok) throw new Error("그룹별 카드 데이터 로딩 실패");

      const result = await response.json();

      if (result.success && result.data?.rows) {
        const rows = result.data.rows;
        if (rows.length > 0) {
          const columns = result.data.columns || Object.keys(rows[0]);
          const labelColumn = columns[0];
          const valueColumn = columns[1];

          const cards = rows.map((row: any) => ({
            label: String(row[labelColumn] || ""),
            value: parseFloat(row[valueColumn]) || 0,
          }));

          setGroupedCards(cards);
        }
      }
    }
    // API 타입
    else if (dataSourceType === "api") {
      if (!groupByDS.endpoint) return;

      const token = localStorage.getItem("authToken");
      const response = await fetch(getApiUrl("/api/dashboards/fetch-external-api"), {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify({
          method: (groupByDS as any).method || "GET",
          url: groupByDS.endpoint,
          headers: (groupByDS as any).headers || {},
          body: (groupByDS as any).body,
          authType: (groupByDS as any).authType,
          authConfig: (groupByDS as any).authConfig,
        }),
      });

      if (!response.ok) throw new Error("그룹별 카드 API 호출 실패");

      const result = await response.json();

      if (result.success && result.data) {
        let rows: any[] = [];
        if (Array.isArray(result.data)) {
          rows = result.data;
        } else if (result.data.results && Array.isArray(result.data.results)) {
          rows = result.data.results;
        } else if (result.data.items && Array.isArray(result.data.items)) {
          rows = result.data.items;
        } else if (result.data.data && Array.isArray(result.data.data)) {
          rows = result.data.data;
        } else {
          rows = [result.data];
        }

        if (rows.length > 0) {
          const columns = Object.keys(rows[0]);
          const labelColumn = columns[0];
          const valueColumn = columns[1];

          const cards = rows.map((row: any) => ({
            label: String(row[labelColumn] || ""),
            value: parseFloat(row[valueColumn]) || 0,
          }));

          setGroupedCards(cards);
        }
      }
    }
  };

  // 일반 지표 데이터 로드
  const loadMetricsData = async () => {
    const dataSourceType = element?.dataSource?.type;

    // Database 타입
    if (dataSourceType === "database") {
      if (!element?.dataSource?.query) {
        setMetrics([]);
        return;
      }

      const token = localStorage.getItem("authToken");
      const response = await fetch(getApiUrl("/api/dashboards/execute-query"), {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify({
          query: element.dataSource.query,
          connectionType: element.dataSource.connectionType || "current",
          connectionId: (element.dataSource as any).connectionId,
        }),
      });

      if (!response.ok) throw new Error("데이터 로딩 실패");

      const result = await response.json();

      if (result.success && result.data?.rows) {
        const rows = result.data.rows;

        const calculatedMetrics =
          element.customMetricConfig?.metrics.map((metric) => {
            const value = calculateMetric(rows, metric.field, metric.aggregation);
            return {
              ...metric,
              calculatedValue: value,
            };
          }) || [];

        setMetrics(calculatedMetrics);
      } else {
        throw new Error(result.message || "데이터 로드 실패");
      }
    }
    // API 타입
    else if (dataSourceType === "api") {
      if (!element?.dataSource?.endpoint) {
        setMetrics([]);
        return;
      }

      const token = localStorage.getItem("authToken");
      const response = await fetch(getApiUrl("/api/dashboards/fetch-external-api"), {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify({
          method: (element.dataSource as any).method || "GET",
          url: element.dataSource.endpoint,
          headers: (element.dataSource as any).headers || {},
          body: (element.dataSource as any).body,
          authType: (element.dataSource as any).authType,
          authConfig: (element.dataSource as any).authConfig,
        }),
      });

      if (!response.ok) throw new Error("API 호출 실패");

      const result = await response.json();

      if (result.success && result.data) {
        // API 응답 데이터 구조 확인 및 처리
        let rows: any[] = [];

        // result.data가 배열인 경우
        if (Array.isArray(result.data)) {
          rows = result.data;
        }
        // result.data.results가 배열인 경우 (일반적인 API 응답 구조)
        else if (result.data.results && Array.isArray(result.data.results)) {
          rows = result.data.results;
        }
        // result.data.items가 배열인 경우
        else if (result.data.items && Array.isArray(result.data.items)) {
          rows = result.data.items;
        }
        // result.data.data가 배열인 경우
        else if (result.data.data && Array.isArray(result.data.data)) {
          rows = result.data.data;
        }
        // 그 외의 경우 단일 객체를 배열로 래핑
        else {
          rows = [result.data];
        }

        const calculatedMetrics =
          element.customMetricConfig?.metrics.map((metric) => {
            const value = calculateMetric(rows, metric.field, metric.aggregation);
            return {
              ...metric,
              calculatedValue: value,
            };
          }) || [];

        setMetrics(calculatedMetrics);
      } else {
        throw new Error("API 응답 형식 오류");
      }
    }
  };

  if (loading) {
    return (
      <div className="flex h-full items-center justify-center bg-background">
        <div className="text-center">
          <div className="border-primary mx-auto h-8 w-8 animate-spin rounded-full border-2 border-t-transparent" />
          <p className="mt-2 text-sm text-muted-foreground">데이터 로딩 중...</p>
        </div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="flex h-full items-center justify-center bg-background p-4">
        <div className="text-center">
          <p className="text-sm text-destructive">⚠️ {error}</p>
          <button
            onClick={loadData}
            className="mt-2 rounded bg-destructive/10 px-3 py-1 text-xs text-destructive hover:bg-destructive/20"
          >
            다시 시도
          </button>
        </div>
      </div>
    );
  }

  // 데이터 소스 체크
  const hasMetricsDataSource =
    (element?.dataSource?.type === "database" && element?.dataSource?.query) ||
    (element?.dataSource?.type === "api" && element?.dataSource?.endpoint);

  const hasGroupByDataSource =
    isGroupByMode &&
    element?.customMetricConfig?.groupByDataSource &&
    ((element.customMetricConfig.groupByDataSource.type === "database" &&
      element.customMetricConfig.groupByDataSource.query) ||
      (element.customMetricConfig.groupByDataSource.type === "api" &&
        element.customMetricConfig.groupByDataSource.endpoint));

  const hasMetricsConfig = element?.customMetricConfig?.metrics && element.customMetricConfig.metrics.length > 0;

  // 둘 다 없으면 빈 화면 표시
  const shouldShowEmpty =
    (!hasGroupByDataSource && !hasMetricsConfig) || (!hasGroupByDataSource && !hasMetricsDataSource);

  if (shouldShowEmpty) {
    return (
      <div className="flex h-full items-center justify-center bg-background p-4">
        <div className="max-w-xs space-y-2 text-center">
          <h3 className="text-sm font-bold text-foreground">사용자 커스텀 카드</h3>
          <div className="space-y-1.5 text-xs text-foreground">
            <p className="font-medium">📊 맞춤형 지표 위젯</p>
            <ul className="space-y-0.5 text-left">
              <li>• SQL 쿼리로 데이터를 불러옵니다</li>
              <li>• 선택한 컬럼의 데이터로 지표를 계산합니다</li>
              <li>• COUNT, SUM, AVG, MIN, MAX 등 집계 함수 지원</li>
              <li>• 사용자 정의 단위 설정 가능</li>
              <li>
                • <strong>그룹별 카드 생성 모드</strong>로 간편하게 사용 가능
              </li>
            </ul>
          </div>
          <div className="mt-2 rounded-lg bg-primary/10 p-2 text-[10px] text-primary">
            <p className="font-medium">⚙️ 설정 방법</p>
            <p className="mb-1">
              {isGroupByMode
                ? "SQL 쿼리를 입력하고 실행하세요 (지표 추가 불필요)"
                : "SQL 쿼리를 입력하고 지표를 추가하세요"}
            </p>
            {isGroupByMode && <p className="text-[9px]">💡 첫 번째 컬럼: 카드 제목, 두 번째 컬럼: 카드 값</p>}
          </div>
        </div>
      </div>
    );
  }

  // 위젯 높이에 따라 레이아웃 결정 (세로 1칸이면 가로, 2칸 이상이면 세로)
  // 실제 측정된 1칸 높이: 119px
  const isHorizontalLayout = element?.size?.height && element.size.height <= 130; // 1칸 여유 (119px + 약간의 마진)

  return (
    <div
      className={`flex h-full w-full overflow-hidden bg-background p-0.5 ${
        isHorizontalLayout ? "flex-row gap-0.5" : "flex-col gap-0.5"
      }`}
    >
      {/* 그룹별 카드 (활성화 시) */}
      {isGroupByMode &&
        groupedCards.map((card, index) => {
          // 색상 순환 (6가지 색상)
          const colorKeys = Object.keys(colorMap) as Array<keyof typeof colorMap>;
          const colorKey = colorKeys[index % colorKeys.length];
          const colors = colorMap[colorKey];

          return (
            <div
              key={`group-${index}`}
              className={`flex flex-1 flex-col items-center justify-center rounded border ${colors.bg} ${colors.border} p-0.5`}
            >
              <div className="text-[8px] leading-tight text-foreground">{card.label}</div>
              <div className={`mt-0 text-xs leading-none font-bold ${colors.text}`}>{card.value.toLocaleString()}</div>
            </div>
          );
        })}

      {/* 일반 지표 카드 (항상 표시) */}
      {metrics.map((metric) => {
        const colors = colorMap[metric.color as keyof typeof colorMap] || colorMap.gray;
        const formattedValue = metric.calculatedValue.toFixed(metric.decimals);

        return (
          <div
            key={metric.id}
            className={`flex flex-1 flex-col items-center justify-center rounded border ${colors.bg} ${colors.border} p-0.5`}
          >
            <div className="text-[8px] leading-tight text-foreground">{metric.label}</div>
            <div className={`mt-0 text-xs leading-none font-bold ${colors.text}`}>
              {formattedValue}
              <span className="ml-0 text-[8px]">{metric.unit}</span>
            </div>
          </div>
        );
      })}
    </div>
  );
}
