"use client";

import React, { useState } from "react";
import { ChartDataSource, QueryResult, KeyValuePair } from "../types";
import { Card } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Plus, X, Play, AlertCircle } from "lucide-react";

interface ApiConfigProps {
  dataSource: ChartDataSource;
  onChange: (updates: Partial<ChartDataSource>) => void;
  onTestResult?: (result: QueryResult) => void;
}

/**
 * REST API 설정 컴포넌트
 * - API 엔드포인트 설정
 * - 헤더 및 쿼리 파라미터 추가
 * - JSON Path 설정
 */
export function ApiConfig({ dataSource, onChange, onTestResult }: ApiConfigProps) {
  const [testing, setTesting] = useState(false);
  const [testResult, setTestResult] = useState<QueryResult | null>(null);
  const [testError, setTestError] = useState<string | null>(null);

  // 헤더를 배열로 정규화 (객체 형식 호환)
  const normalizeHeaders = (): KeyValuePair[] => {
    if (!dataSource.headers) return [];
    if (Array.isArray(dataSource.headers)) return dataSource.headers;
    // 객체 형식이면 배열로 변환
    return Object.entries(dataSource.headers as Record<string, string>).map(([key, value]) => ({
      id: `header_${Date.now()}_${Math.random()}`,
      key,
      value,
    }));
  };

  // 헤더 추가
  const addHeader = () => {
    const headers = normalizeHeaders();
    onChange({
      headers: [...headers, { id: `header_${Date.now()}`, key: "", value: "" }],
    });
  };

  // 헤더 제거
  const removeHeader = (id: string) => {
    const headers = normalizeHeaders();
    onChange({ headers: headers.filter((h) => h.id !== id) });
  };

  // 헤더 업데이트
  const updateHeader = (id: string, updates: Partial<KeyValuePair>) => {
    const headers = normalizeHeaders();
    onChange({
      headers: headers.map((h) => (h.id === id ? { ...h, ...updates } : h)),
    });
  };

  // 쿼리 파라미터를 배열로 정규화 (객체 형식 호환)
  const normalizeQueryParams = (): KeyValuePair[] => {
    if (!dataSource.queryParams) return [];
    if (Array.isArray(dataSource.queryParams)) return dataSource.queryParams;
    // 객체 형식이면 배열로 변환
    return Object.entries(dataSource.queryParams as Record<string, string>).map(([key, value]) => ({
      id: `param_${Date.now()}_${Math.random()}`,
      key,
      value,
    }));
  };

  // 쿼리 파라미터 추가
  const addQueryParam = () => {
    const queryParams = normalizeQueryParams();
    onChange({
      queryParams: [...queryParams, { id: `param_${Date.now()}`, key: "", value: "" }],
    });
  };

  // 쿼리 파라미터 제거
  const removeQueryParam = (id: string) => {
    const queryParams = normalizeQueryParams();
    onChange({ queryParams: queryParams.filter((p) => p.id !== id) });
  };

  // 쿼리 파라미터 업데이트
  const updateQueryParam = (id: string, updates: Partial<KeyValuePair>) => {
    const queryParams = normalizeQueryParams();
    onChange({
      queryParams: queryParams.map((p) => (p.id === id ? { ...p, ...updates } : p)),
    });
  };

  // API 테스트
  const testApi = async () => {
    if (!dataSource.endpoint) {
      setTestError("API URL을 입력하세요");
      return;
    }

    setTesting(true);
    setTestError(null);
    setTestResult(null);

    try {
      // 쿼리 파라미터 구성
      const params: Record<string, string> = {};
      const normalizedQueryParams = normalizeQueryParams();
      normalizedQueryParams.forEach(({ key, value }) => {
        if (key && value) {
          params[key] = value;
        }
      });

      // 헤더 구성
      const headers: Record<string, string> = {};
      const normalizedHeaders = normalizeHeaders();
      normalizedHeaders.forEach(({ key, value }) => {
        if (key && value) {
          headers[key] = value;
        }
      });

      // 백엔드 프록시를 통한 외부 API 호출 (CORS 우회)
      const response = await fetch("http://localhost:8080/api/dashboards/fetch-external-api", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          url: dataSource.endpoint,
          method: "GET",
          headers: headers,
          queryParams: params,
        }),
      });

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      const apiResponse = await response.json();

      if (!apiResponse.success) {
        throw new Error(apiResponse.message || "외부 API 호출 실패");
      }

      const apiData = apiResponse.data;

      // JSON Path 처리
      let data = apiData;
      if (dataSource.jsonPath) {
        const paths = dataSource.jsonPath.split(".");
        for (const path of paths) {
          if (data && typeof data === "object" && path in data) {
            data = data[path];
          } else {
            throw new Error(`JSON Path "${dataSource.jsonPath}"에서 데이터를 찾을 수 없습니다`);
          }
        }
      }

      // 배열이 아니면 배열로 변환
      const rows = Array.isArray(data) ? data : [data];

      if (rows.length === 0) {
        throw new Error("API 응답에 데이터가 없습니다");
      }

      // 컬럼 추출 및 타입 분석
      const firstRow = rows[0];
      const columns = Object.keys(firstRow);

      // 각 컬럼의 타입 분석
      const columnTypes: Record<string, string> = {};
      columns.forEach((col) => {
        const value = firstRow[col];
        if (value === null || value === undefined) {
          columnTypes[col] = "null";
        } else if (Array.isArray(value)) {
          columnTypes[col] = "array";
        } else if (typeof value === "object") {
          columnTypes[col] = "object";
        } else if (typeof value === "number") {
          columnTypes[col] = "number";
        } else if (typeof value === "boolean") {
          columnTypes[col] = "boolean";
        } else {
          columnTypes[col] = "string";
        }
      });

      const queryResult: QueryResult = {
        columns,
        rows,
        totalRows: rows.length,
        executionTime: 0,
        columnTypes, // 타입 정보 추가
      };

      setTestResult(queryResult);
      onTestResult?.(queryResult);
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : "알 수 없는 오류가 발생했습니다";
      setTestError(errorMessage);
    } finally {
      setTesting(false);
    }
  };

  return (
    <div className="space-y-4">
      <div>
        <h3 className="text-lg font-semibold text-gray-800">2단계: REST API 설정</h3>
        <p className="mt-1 text-sm text-gray-600">외부 API에서 데이터를 가져올 설정을 입력하세요</p>
      </div>

      {/* API URL */}
      <Card className="space-y-4 p-4">
        <div>
          <Label className="text-sm font-medium text-gray-700">API URL *</Label>
          <Input
            type="url"
            placeholder="https://api.example.com/data"
            value={dataSource.endpoint || ""}
            onChange={(e) => onChange({ endpoint: e.target.value })}
            className="mt-2"
          />
          <p className="mt-1 text-xs text-gray-500">GET 요청을 보낼 API 엔드포인트</p>
        </div>

        {/* HTTP 메서드 (고정) */}
        <div>
          <Label className="text-sm font-medium text-gray-700">HTTP 메서드</Label>
          <div className="mt-2 rounded border border-gray-300 bg-gray-100 p-2 text-sm text-gray-700">GET (고정)</div>
          <p className="mt-1 text-xs text-gray-500">데이터 조회는 GET 메서드만 지원합니다</p>
        </div>
      </Card>

      {/* 쿼리 파라미터 */}
      <Card className="space-y-4 p-4">
        <div className="flex items-center justify-between">
          <Label className="text-sm font-medium text-gray-700">URL 쿼리 파라미터</Label>
          <Button variant="outline" size="sm" onClick={addQueryParam}>
            <Plus className="mr-1 h-3 w-3" />
            추가
          </Button>
        </div>

        {(() => {
          const params = normalizeQueryParams();
          return params.length > 0 ? (
            <div className="space-y-2">
              {params.map((param) => (
                <div key={param.id} className="flex gap-2">
                  <Input
                    placeholder="key"
                    value={param.key}
                    onChange={(e) => updateQueryParam(param.id, { key: e.target.value })}
                    className="flex-1"
                  />
                  <Input
                    placeholder="value"
                    value={param.value}
                    onChange={(e) => updateQueryParam(param.id, { value: e.target.value })}
                    className="flex-1"
                  />
                  <Button variant="ghost" size="icon" onClick={() => removeQueryParam(param.id)}>
                    <X className="h-4 w-4" />
                  </Button>
                </div>
              ))}
            </div>
          ) : (
            <p className="py-2 text-center text-sm text-gray-500">추가된 파라미터가 없습니다</p>
          );
        })()}

        <p className="text-xs text-gray-500">예: category=electronics, limit=10</p>
      </Card>

      {/* 헤더 */}
      <Card className="space-y-4 p-4">
        <div className="flex items-center justify-between">
          <Label className="text-sm font-medium text-gray-700">요청 헤더</Label>
          <Button variant="outline" size="sm" onClick={addHeader}>
            <Plus className="mr-1 h-3 w-3" />
            추가
          </Button>
        </div>

        {/* 빠른 헤더 템플릿 */}
        <div className="flex flex-wrap gap-2">
          <Button
            variant="outline"
            size="sm"
            onClick={() => {
              const headers = normalizeHeaders();
              onChange({
                headers: [...headers, { id: `header_${Date.now()}`, key: "Authorization", value: "Bearer YOUR_TOKEN" }],
              });
            }}
          >
            + Authorization
          </Button>
          <Button
            variant="outline"
            size="sm"
            onClick={() => {
              const headers = normalizeHeaders();
              onChange({
                headers: [...headers, { id: `header_${Date.now()}`, key: "Content-Type", value: "application/json" }],
              });
            }}
          >
            + Content-Type
          </Button>
        </div>

        {(() => {
          const headers = normalizeHeaders();
          return headers.length > 0 ? (
            <div className="space-y-2">
              {headers.map((header) => (
                <div key={header.id} className="flex gap-2">
                  <Input
                    placeholder="Header Name"
                    value={header.key}
                    onChange={(e) => updateHeader(header.id, { key: e.target.value })}
                    className="flex-1"
                  />
                  <Input
                    placeholder="Header Value"
                    value={header.value}
                    onChange={(e) => updateHeader(header.id, { value: e.target.value })}
                    className="flex-1"
                    type={header.key.toLowerCase().includes("auth") ? "password" : "text"}
                  />
                  <Button variant="ghost" size="icon" onClick={() => removeHeader(header.id)}>
                    <X className="h-4 w-4" />
                  </Button>
                </div>
              ))}
            </div>
          ) : (
            <p className="py-2 text-center text-sm text-gray-500">추가된 헤더가 없습니다</p>
          );
        })()}
      </Card>

      {/* JSON Path */}
      <Card className="space-y-2 p-4">
        <Label className="text-sm font-medium text-gray-700">JSON Path (선택)</Label>
        <Input
          placeholder="data.results"
          value={dataSource.jsonPath || ""}
          onChange={(e) => onChange({ jsonPath: e.target.value })}
        />
        <p className="text-xs text-gray-500">
          JSON 응답에서 데이터 배열의 경로 (예: data.results, items, response.data)
          <br />
          비워두면 전체 응답을 사용합니다
        </p>
      </Card>

      {/* 테스트 버튼 */}
      <div className="flex justify-end">
        <Button onClick={testApi} disabled={!dataSource.endpoint || testing}>
          {testing ? (
            <>
              <div className="mr-2 h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent" />
              테스트 중...
            </>
          ) : (
            <>
              <Play className="mr-2 h-4 w-4" />
              API 테스트
            </>
          )}
        </Button>
      </div>

      {/* 테스트 오류 */}
      {testError && (
        <Card className="border-red-200 bg-red-50 p-4">
          <div className="flex items-start gap-2">
            <AlertCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-red-600" />
            <div>
              <div className="text-sm font-medium text-red-800">API 호출 실패</div>
              <div className="mt-1 text-sm text-red-700">{testError}</div>
            </div>
          </div>
        </Card>
      )}

      {/* 테스트 결과 */}
      {testResult && (
        <Card className="border-green-200 bg-green-50 p-4">
          <div className="mb-2 text-sm font-medium text-green-800">✅ API 호출 성공</div>
          <div className="space-y-1 text-xs text-green-700">
            <div>총 {testResult.rows.length}개의 데이터를 불러왔습니다</div>
            <div>컬럼: {testResult.columns.join(", ")}</div>
          </div>
        </Card>
      )}
    </div>
  );
}
