"use client";

import React, { useState, useCallback, useEffect } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
  TestTube,
  Play,
  CheckCircle,
  XCircle,
  Clock,
  AlertCircle,
  Copy,
  RefreshCw,
  Zap,
  Code,
  Network,
  Timer,
} from "lucide-react";
import { toast } from "sonner";
import { showErrorToast } from "@/lib/utils/toastUtils";

// 타입 import
import {
  ExternalCallTestPanelProps,
  ApiTestResult,
  ExternalCallContext,
} from "@/types/external-call/ExternalCallTypes";
import { ExternalCallAPI } from "@/lib/api/externalCall";

/**
 * 🧪 API 테스트 전용 컴포넌트
 *
 * REST API 설정을 실제로 테스트하고 결과를 표시
 * 템플릿 변수 치환, 응답 분석, 오류 진단 등 제공
 */
const ExternalCallTestPanel: React.FC<ExternalCallTestPanelProps> = ({
  settings,
  context,
  onTestResult,
  disabled = false,
}) => {
  // 상태 관리
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [testResult, setTestResult] = useState<ApiTestResult | null>(null);
  const [activeTab, setActiveTab] = useState<string>("request");
  const [processedTemplate, setProcessedTemplate] = useState<string>("");
  const [testContext, setTestContext] = useState<ExternalCallContext>(() => ({
    relationshipId: context?.relationshipId || "test-relationship",
    diagramId: context?.diagramId || "test-diagram",
    userId: context?.userId || "test-user",
    executionId: context?.executionId || `test-${Date.now()}`,
    sourceData: context?.sourceData || {
      id: 1,
      name: "테스트 데이터",
      value: 100,
      status: "active",
    },
    targetData: context?.targetData,
    timestamp: context?.timestamp || new Date().toISOString(),
    metadata: context?.metadata,
  }));

  // 템플릿 변수 치환 함수
  const processTemplate = useCallback((template: string, context: ExternalCallContext): string => {
    let processed = template;

    // 각 템플릿 변수를 실제 값으로 치환
    const replacements = {
      "{{sourceData}}": JSON.stringify(context.sourceData, null, 2),
      "{{targetData}}": context.targetData ? JSON.stringify(context.targetData, null, 2) : "null",
      "{{timestamp}}": context.timestamp,
      "{{relationshipId}}": context.relationshipId,
      "{{diagramId}}": context.diagramId,
      "{{userId}}": context.userId,
      "{{executionId}}": context.executionId,
    };

    Object.entries(replacements).forEach(([variable, value]) => {
      processed = processed.replace(new RegExp(variable.replace(/[{}]/g, "\\$&"), "g"), value);
    });

    return processed;
  }, []);

  // 템플릿 처리 (설정이나 컨텍스트 변경 시)
  useEffect(() => {
    if (settings.bodyTemplate) {
      const processed = processTemplate(settings.bodyTemplate, testContext);
      setProcessedTemplate(processed);
    }
  }, [settings.bodyTemplate, testContext, processTemplate]);

  // API 테스트 실행
  const handleRunTest = useCallback(async () => {
    if (!settings.apiUrl) {
      toast.error("API URL을 입력해주세요.");
      return;
    }

    setIsLoading(true);
    setTestResult(null);

    try {
      // 테스트 요청 데이터 구성 (백엔드 형식에 맞춤)
      const testRequest = {
        settings: {
          callType: "rest-api" as const,
          apiType: "generic" as const,
          url: settings.apiUrl,
          method: settings.httpMethod,
          headers: settings.headers,
          body: processedTemplate,
          authentication: settings.authentication, // 인증 정보 추가
          timeout: settings.timeout,
          retryCount: settings.retryCount,
        },
        templateData: testContext,
      };

      // API 호출
      const response = await ExternalCallAPI.testExternalCall(testRequest);

      if (response.success && response.result) {
        // 백엔드 응답을 ApiTestResult 형태로 변환
        const apiTestResult: ApiTestResult = {
          success: response.result.success,
          statusCode: response.result.statusCode,
          responseTime: response.result.executionTime || 0,
          response: response.result.response,
          error: response.result.error,
          timestamp: new Date().toISOString(),
        };

        setTestResult(apiTestResult);
        onTestResult(apiTestResult);

        if (apiTestResult.success) {
          toast.success("API 테스트가 성공했습니다!");
          setActiveTab("response");
        } else {
          showErrorToast("API 호출이 실패했습니다", null, { guidance: "URL과 요청 설정을 확인해 주세요." });
          setActiveTab("response");
        }
      } else {
        const errorResult: ApiTestResult = {
          success: false,
          responseTime: 0,
          error: response.error || "알 수 없는 오류가 발생했습니다.",
          timestamp: new Date().toISOString(),
        };
        setTestResult(errorResult);
        onTestResult(errorResult);
        showErrorToast("API 테스트 실행에 실패했습니다", response.error, { guidance: "URL과 요청 설정을 확인해 주세요." });
      }
    } catch (error) {
      const errorResult: ApiTestResult = {
        success: false,
        responseTime: 0,
        error: error instanceof Error ? error.message : "네트워크 오류가 발생했습니다.",
        timestamp: new Date().toISOString(),
      };
      setTestResult(errorResult);
      onTestResult(errorResult);
      showErrorToast("API 테스트 실행에 실패했습니다", error, { guidance: "네트워크 연결과 URL을 확인해 주세요." });
    } finally {
      setIsLoading(false);
    }
  }, [settings, processedTemplate, testContext, onTestResult]);

  // 테스트 데이터 복사
  const handleCopyToClipboard = useCallback(async (text: string) => {
    try {
      await navigator.clipboard.writeText(text);
      toast.success("클립보드에 복사되었습니다.");
    } catch (error) {
      showErrorToast("클립보드 복사에 실패했습니다", error, { guidance: "브라우저 권한을 확인해 주세요." });
    }
  }, []);

  // 테스트 컨텍스트 리셋
  const handleResetContext = useCallback(() => {
    setTestContext({
      relationshipId: "test-relationship",
      diagramId: "test-diagram",
      userId: "test-user",
      executionId: `test-${Date.now()}`,
      sourceData: {
        id: 1,
        name: "테스트 데이터",
        value: 100,
        status: "active",
      },
      timestamp: new Date().toISOString(),
    });
  }, []);

  return (
    <div className="space-y-4">
      {/* 테스트 실행 헤더 */}
      <Card>
        <CardHeader className="pb-3">
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-2">
              <TestTube className="h-5 w-5 text-primary" />
              <CardTitle className="text-lg">API 테스트</CardTitle>
              {testResult && (
                <Badge variant={testResult.success ? "default" : "destructive"}>
                  {testResult.success ? "성공" : "실패"}
                </Badge>
              )}
            </div>

            <div className="flex gap-2">
              <Button variant="outline" size="sm" onClick={handleResetContext} disabled={disabled || isLoading}>
                <RefreshCw className="mr-1 h-4 w-4" />
                리셋
              </Button>

              <Button
                onClick={handleRunTest}
                disabled={disabled || isLoading || !settings.apiUrl}
                className="min-w-[100px]"
              >
                {isLoading ? (
                  <>
                    <RefreshCw className="mr-2 h-4 w-4 animate-spin" />
                    테스트 중...
                  </>
                ) : (
                  <>
                    <Play className="mr-2 h-4 w-4" />
                    테스트 실행
                  </>
                )}
              </Button>
            </div>
          </div>
        </CardHeader>
      </Card>

      {/* 테스트 결과 요약 */}
      {testResult && (
        <Card>
          <CardContent className="pt-6">
            <div className="grid grid-cols-4 gap-4 text-center">
              <div className="space-y-1">
                <div className="flex items-center justify-center gap-1">
                  {testResult.success ? (
                    <CheckCircle className="h-4 w-4 text-emerald-500" />
                  ) : (
                    <XCircle className="h-4 w-4 text-destructive" />
                  )}
                  <span className="text-sm font-medium">상태</span>
                </div>
                <div className="text-muted-foreground text-xs">{testResult.success ? "성공" : "실패"}</div>
              </div>

              <div className="space-y-1">
                <div className="flex items-center justify-center gap-1">
                  <Network className="h-4 w-4 text-primary" />
                  <span className="text-sm font-medium">상태 코드</span>
                </div>
                <div className="text-muted-foreground text-xs">{testResult.statusCode || "N/A"}</div>
              </div>

              <div className="space-y-1">
                <div className="flex items-center justify-center gap-1">
                  <Timer className="h-4 w-4 text-amber-500" />
                  <span className="text-sm font-medium">응답 시간</span>
                </div>
                <div className="text-muted-foreground text-xs">{testResult.responseTime}ms</div>
              </div>

              <div className="space-y-1">
                <div className="flex items-center justify-center gap-1">
                  <Clock className="h-4 w-4 text-purple-500" />
                  <span className="text-sm font-medium">실행 시간</span>
                </div>
                <div className="text-muted-foreground text-xs">
                  {new Date(testResult.timestamp).toLocaleTimeString()}
                </div>
              </div>
            </div>
          </CardContent>
        </Card>
      )}

      {/* 상세 정보 탭 */}
      <Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
        <TabsList className="grid w-full grid-cols-3">
          <TabsTrigger value="request" className="flex items-center gap-2">
            <Zap className="h-4 w-4" />
            요청 정보
          </TabsTrigger>
          <TabsTrigger value="response" className="flex items-center gap-2">
            <Code className="h-4 w-4" />
            응답 정보
          </TabsTrigger>
          <TabsTrigger value="context" className="flex items-center gap-2">
            <AlertCircle className="h-4 w-4" />
            테스트 데이터
          </TabsTrigger>
        </TabsList>

        {/* 요청 정보 탭 */}
        <TabsContent value="request" className="space-y-4">
          <Card>
            <CardHeader>
              <div className="flex items-center justify-between">
                <CardTitle className="text-base">요청 정보</CardTitle>
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() =>
                    handleCopyToClipboard(
                      JSON.stringify(
                        {
                          url: settings.apiUrl,
                          method: settings.httpMethod,
                          headers: settings.headers,
                          body: processedTemplate,
                        },
                        null,
                        2,
                      ),
                    )
                  }
                >
                  <Copy className="mr-1 h-4 w-4" />
                  복사
                </Button>
              </div>
            </CardHeader>
            <CardContent className="space-y-4">
              {/* URL과 메서드 */}
              <div className="grid grid-cols-4 gap-4">
                <div className="col-span-1">
                  <Label className="text-muted-foreground text-xs">HTTP 메서드</Label>
                  <Badge variant="outline" className="mt-1">
                    {settings.httpMethod}
                  </Badge>
                </div>
                <div className="col-span-3">
                  <Label className="text-muted-foreground text-xs">URL</Label>
                  <div className="bg-muted mt-1 rounded p-2 font-mono text-sm break-all">{settings.apiUrl}</div>
                </div>
              </div>

              {/* 헤더 */}
              <div>
                <Label className="text-muted-foreground text-xs">헤더</Label>
                <ScrollArea className="mt-1 h-32 w-full rounded border">
                  <div className="p-3">
                    <pre className="text-xs">{JSON.stringify(settings.headers, null, 2)}</pre>
                  </div>
                </ScrollArea>
              </div>

              {/* 요청 바디 (POST/PUT/PATCH인 경우) */}
              {["POST", "PUT", "PATCH"].includes(settings.httpMethod) && (
                <div>
                  <Label className="text-muted-foreground text-xs">요청 바디 (템플릿 변수 치환됨)</Label>
                  <ScrollArea className="mt-1 h-40 w-full rounded border">
                    <div className="p-3">
                      <pre className="text-xs whitespace-pre-wrap">{processedTemplate}</pre>
                    </div>
                  </ScrollArea>
                </div>
              )}
            </CardContent>
          </Card>
        </TabsContent>

        {/* 응답 정보 탭 */}
        <TabsContent value="response" className="space-y-4">
          {testResult ? (
            <Card>
              <CardHeader>
                <div className="flex items-center justify-between">
                  <CardTitle className="text-base">응답 정보</CardTitle>
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={() => handleCopyToClipboard(JSON.stringify(testResult, null, 2))}
                  >
                    <Copy className="mr-1 h-4 w-4" />
                    복사
                  </Button>
                </div>
              </CardHeader>
              <CardContent className="space-y-4">
                {testResult.success ? (
                  <>
                    {/* 상태 코드 */}
                    {testResult.statusCode && (
                      <div>
                        <Label className="text-muted-foreground text-xs">상태 코드</Label>
                        <div className="mt-1 rounded border bg-emerald-50 p-2">
                          <span className="font-mono text-sm text-emerald-700">{testResult.statusCode}</span>
                        </div>
                      </div>
                    )}

                    {/* 응답 시간 */}
                    {testResult.responseTime !== undefined && (
                      <div>
                        <Label className="text-muted-foreground text-xs">응답 시간</Label>
                        <div className="mt-1 rounded border bg-accent p-2">
                          <span className="font-mono text-sm text-primary">{testResult.responseTime}ms</span>
                        </div>
                      </div>
                    )}

                    {/* 응답 데이터 */}
                    {testResult.response && (
                      <div>
                        <Label className="text-muted-foreground text-xs">응답 데이터</Label>
                        <ScrollArea className="mt-1 h-40 w-full rounded border">
                          <div className="p-3">
                            <pre className="text-xs whitespace-pre-wrap">{testResult.response}</pre>
                          </div>
                        </ScrollArea>
                      </div>
                    )}
                  </>
                ) : (
                  <Alert variant="destructive">
                    <XCircle className="h-4 w-4" />
                    <AlertDescription>
                      <div className="space-y-2">
                        <div className="font-medium">오류 발생</div>
                        <div className="text-sm">{testResult.error}</div>
                        {testResult.statusCode && <div className="text-sm">상태 코드: {testResult.statusCode}</div>}
                      </div>
                    </AlertDescription>
                  </Alert>
                )}
              </CardContent>
            </Card>
          ) : (
            <Card>
              <CardContent className="pt-6">
                <div className="text-muted-foreground py-8 text-center">
                  <TestTube className="mx-auto mb-2 h-8 w-8 opacity-50" />
                  <p>테스트를 실행하면 응답 정보가 여기에 표시됩니다.</p>
                </div>
              </CardContent>
            </Card>
          )}
        </TabsContent>

        {/* 테스트 데이터 탭 */}
        <TabsContent value="context" className="space-y-4">
          <Card>
            <CardHeader>
              <div className="flex items-center justify-between">
                <CardTitle className="text-base">테스트 컨텍스트</CardTitle>
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => handleCopyToClipboard(JSON.stringify(testContext, null, 2))}
                >
                  <Copy className="mr-1 h-4 w-4" />
                  복사
                </Button>
              </div>
            </CardHeader>
            <CardContent className="space-y-4">
              <div className="text-muted-foreground text-sm">템플릿 변수 치환에 사용되는 테스트 데이터입니다.</div>

              <ScrollArea className="h-60 w-full rounded border">
                <div className="p-3">
                  <pre className="text-xs whitespace-pre-wrap">{JSON.stringify(testContext, null, 2)}</pre>
                </div>
              </ScrollArea>

              <Alert>
                <AlertCircle className="h-4 w-4" />
                <AlertDescription className="text-sm">
                  실제 실행 시에는 관계의 실제 데이터가 사용됩니다. 이 데이터는 테스트 목적으로만 사용됩니다.
                </AlertDescription>
              </Alert>
            </CardContent>
          </Card>
        </TabsContent>
      </Tabs>
    </div>
  );
};

export default ExternalCallTestPanel;
