"use client";

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

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-indigo-50", text: "text-indigo-600", border: "border-indigo-200" },
  green: { bg: "bg-green-50", text: "text-green-600", border: "border-green-200" },
  blue: { bg: "bg-blue-50", text: "text-blue-600", border: "border-blue-200" },
  purple: { bg: "bg-purple-50", text: "text-purple-600", border: "border-purple-200" },
  orange: { bg: "bg-orange-50", text: "text-orange-600", border: "border-orange-200" },
  gray: { bg: "bg-gray-50", text: "text-gray-600", border: "border-gray-200" },
};

export default function CustomMetricWidget({ element }: CustomMetricWidgetProps) {
  const [metrics, setMetrics] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    loadData();

    // 자동 새로고침 (30초마다)
    const interval = setInterval(loadData, 30000);
    return () => clearInterval(interval);
  }, [element]);

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

      // 데이터 소스 타입 확인
      const dataSourceType = element?.dataSource?.type;

      // 설정이 없으면 초기 상태로 반환
      if (!element?.customMetricConfig?.metrics) {
        setMetrics([]);
        setLoading(false);
        return;
      }

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

        const token = localStorage.getItem("authToken");
        const response = await fetch("/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.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([]);
          setLoading(false);
          return;
        }

        const token = localStorage.getItem("authToken");
        const response = await fetch("/api/dashboards/fetch-external-api", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${token}`,
          },
          body: JSON.stringify({
            method: element.dataSource.method || "GET",
            url: element.dataSource.endpoint,
            headers: element.dataSource.headers || {},
            body: element.dataSource.body,
            authType: element.dataSource.authType,
            authConfig: element.dataSource.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 응답 형식 오류");
        }
      } else {
        setMetrics([]);
        setLoading(false);
      }
    } catch (err) {
      console.error("메트릭 로드 실패:", err);
      setError(err instanceof Error ? err.message : "데이터를 불러올 수 없습니다");
    } finally {
      setLoading(false);
    }
  };

  if (loading) {
    return (
      <div className="flex h-full items-center justify-center bg-white">
        <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-gray-500">데이터 로딩 중...</p>
        </div>
      </div>
    );
  }

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

  // 데이터 소스가 없거나 설정이 없는 경우
  const hasDataSource =
    (element?.dataSource?.type === "database" && element?.dataSource?.query) ||
    (element?.dataSource?.type === "api" && element?.dataSource?.endpoint);

  if (!hasDataSource || !element?.customMetricConfig?.metrics || metrics.length === 0) {
    return (
      <div className="flex h-full items-center justify-center bg-white p-4">
        <div className="max-w-xs space-y-2 text-center">
          <h3 className="text-sm font-bold text-gray-900">사용자 커스텀 카드</h3>
          <div className="space-y-1.5 text-xs text-gray-600">
            <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>
            </ul>
          </div>
          <div className="mt-2 rounded-lg bg-blue-50 p-2 text-[10px] text-blue-700">
            <p className="font-medium">⚙️ 설정 방법</p>
            <p>SQL 쿼리를 입력하고 지표를 추가하세요</p>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="flex h-full w-full flex-col overflow-hidden bg-white p-4">
      {/* 스크롤 가능한 콘텐츠 영역 */}
      <div className="flex-1 overflow-y-auto">
        <div className="grid w-full gap-4" style={{ gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))" }}>
          {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={`rounded-lg border ${colors.bg} ${colors.border} p-4 text-center`}>
                <div className="text-sm text-gray-600">{metric.label}</div>
                <div className={`mt-2 text-3xl font-bold ${colors.text}`}>
                  {formattedValue}
                  <span className="ml-1 text-lg">{metric.unit}</span>
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}
