/**
 * 🔥 버튼 제어관리 성능 테스트
 *
 * 목표 성능:
 * - 즉시 응답: 50-200ms
 * - 캐시 히트: 1-10ms
 * - 백그라운드 작업: 사용자 체감 없음
 */

import { optimizedButtonDataflowService } from "../optimizedButtonDataflowService";
import { dataflowConfigCache } from "../dataflowCache";
import { dataflowJobQueue } from "../dataflowJobQueue";
import { ButtonActionType, ButtonTypeConfig } from "@/types/screen";

// Mock API client
jest.mock("@/lib/api/client", () => ({
  apiClient: {
    get: jest.fn(),
    post: jest.fn(),
    put: jest.fn(),
  },
}));

describe("🔥 Button Dataflow Performance Tests", () => {
  beforeEach(() => {
    // 캐시 초기화
    dataflowConfigCache.clearAllCache();
    dataflowJobQueue.clearQueue();
  });

  describe("📊 Cache Performance", () => {
    it("should load config from server on first request", async () => {
      const startTime = performance.now();

      const config = await dataflowConfigCache.getConfig("test-button-1");

      const endTime = performance.now();
      const responseTime = endTime - startTime;

      // 첫 번째 요청은 서버 로딩으로 인해 더 오래 걸릴 수 있음
      expect(responseTime).toBeLessThan(1000); // 1초 이내

      const metrics = dataflowConfigCache.getMetrics();
      expect(metrics.totalRequests).toBe(1);
      expect(metrics.cacheMisses).toBe(1);
    });

    it("should return cached config in under 10ms", async () => {
      // 먼저 캐시에 로드
      await dataflowConfigCache.getConfig("test-button-2");

      // 두 번째 요청 시간 측정
      const startTime = performance.now();
      const config = await dataflowConfigCache.getConfig("test-button-2");
      const endTime = performance.now();

      const responseTime = endTime - startTime;

      // 🔥 캐시 히트는 10ms 이내여야 함
      expect(responseTime).toBeLessThan(10);

      const metrics = dataflowConfigCache.getMetrics();
      expect(metrics.cacheHits).toBeGreaterThan(0);
      expect(metrics.hitRate).toBeGreaterThan(0);
    });

    it("should maintain cache performance under load", async () => {
      const buttonIds = Array.from({ length: 50 }, (_, i) => `test-button-${i}`);

      // 첫 번째 로드 (캐시 채우기)
      await Promise.all(buttonIds.map((id) => dataflowConfigCache.getConfig(id)));

      // 캐시된 데이터 성능 테스트
      const startTime = performance.now();

      await Promise.all(buttonIds.map((id) => dataflowConfigCache.getConfig(id)));

      const endTime = performance.now();
      const totalTime = endTime - startTime;
      const averageTime = totalTime / buttonIds.length;

      // 🔥 평균 캐시 응답 시간 5ms 이내
      expect(averageTime).toBeLessThan(5);

      const metrics = dataflowConfigCache.getMetrics();
      expect(metrics.hitRate).toBeGreaterThan(80); // 80% 이상 히트율
    });
  });

  describe("⚡ Button Execution Performance", () => {
    const mockButtonConfig: ButtonTypeConfig = {
      actionType: "save" as ButtonActionType,
      enableDataflowControl: true,
      dataflowTiming: "after",
      dataflowConfig: {
        controlMode: "simple",
        selectedDiagramId: 1,
        selectedRelationshipId: "rel-123",
      },
    };

    it("should execute button action in under 200ms", async () => {
      const startTime = performance.now();

      const result = await optimizedButtonDataflowService.executeButtonWithDataflow(
        "test-button-3",
        "save",
        mockButtonConfig,
        { testData: "value" },
        "DEFAULT",
      );

      const endTime = performance.now();
      const responseTime = endTime - startTime;

      // 🔥 즉시 응답 목표: 200ms 이내
      expect(responseTime).toBeLessThan(200);
      expect(result.jobId).toBeDefined();
    });

    it("should handle after timing with immediate response", async () => {
      const config = { ...mockButtonConfig, dataflowTiming: "after" as const };

      const startTime = performance.now();

      const result = await optimizedButtonDataflowService.executeButtonWithDataflow(
        "test-button-4",
        "save",
        config,
        { testData: "value" },
        "DEFAULT",
      );

      const endTime = performance.now();
      const responseTime = endTime - startTime;

      // After 타이밍은 기존 액션 즉시 실행이므로 빠름
      expect(responseTime).toBeLessThan(150);
      expect(result.immediateResult).toBeDefined();
      expect(result.timing).toBe("after");
    });

    it("should handle simple validation quickly", async () => {
      const config = {
        ...mockButtonConfig,
        dataflowTiming: "before" as const,
        dataflowConfig: {
          controlMode: "advanced" as const,
          directControl: {
            sourceTable: "test_table",
            triggerType: "insert" as const,
            conditions: [
              {
                id: "cond1",
                type: "condition" as const,
                field: "status",
                operator: "=" as const,
                value: "active",
              },
            ],
            actions: [],
          },
        },
      };

      const startTime = performance.now();

      const result = await optimizedButtonDataflowService.executeButtonWithDataflow(
        "test-button-5",
        "save",
        config,
        { status: "active" },
        "DEFAULT",
      );

      const endTime = performance.now();
      const responseTime = endTime - startTime;

      // 🔥 간단한 검증은 50ms 이내
      expect(responseTime).toBeLessThan(50);
      expect(result.immediateResult).toBeDefined();
    });
  });

  describe("🚀 Job Queue Performance", () => {
    it("should enqueue jobs instantly", () => {
      const startTime = performance.now();

      const jobId = dataflowJobQueue.enqueue(
        "test-button-6",
        "save",
        mockButtonConfig,
        { testData: "value" },
        "DEFAULT",
        "normal",
      );

      const endTime = performance.now();
      const responseTime = endTime - startTime;

      // 🔥 큐잉은 즉시 (5ms 이내)
      expect(responseTime).toBeLessThan(5);
      expect(jobId).toBeDefined();
      expect(jobId).toMatch(/^job_/);
    });

    it("should handle multiple concurrent jobs", () => {
      const jobCount = 20;
      const startTime = performance.now();

      const jobIds = Array.from({ length: jobCount }, (_, i) =>
        dataflowJobQueue.enqueue(
          `test-button-${i}`,
          "save",
          mockButtonConfig,
          { testData: `value-${i}` },
          "DEFAULT",
          "normal",
        ),
      );

      const endTime = performance.now();
      const totalTime = endTime - startTime;
      const averageTime = totalTime / jobCount;

      // 🔥 평균 큐잉 시간 1ms 이내
      expect(averageTime).toBeLessThan(1);
      expect(jobIds).toHaveLength(jobCount);

      const metrics = dataflowJobQueue.getMetrics();
      expect(metrics.totalJobs).toBe(jobCount);
    });

    it("should prioritize high priority jobs", () => {
      // 일반 우선순위 작업들 추가
      const normalJobs = Array.from({ length: 5 }, (_, i) =>
        dataflowJobQueue.enqueue(`normal-button-${i}`, "save", mockButtonConfig, {}, "DEFAULT", "normal"),
      );

      // 높은 우선순위 작업 추가
      const highJob = dataflowJobQueue.enqueue("high-priority-button", "save", mockButtonConfig, {}, "DEFAULT", "high");

      const queueInfo = dataflowJobQueue.getQueueInfo();

      // 높은 우선순위 작업이 큐의 맨 앞에 있어야 함
      expect(queueInfo.pending[0].id).toBe(highJob);
      expect(queueInfo.pending[0].priority).toBe("high");
    });
  });

  describe("📈 Performance Metrics", () => {
    it("should track cache metrics accurately", async () => {
      // 캐시 미스 발생
      await dataflowConfigCache.getConfig("metrics-test-1");
      await dataflowConfigCache.getConfig("metrics-test-2");

      // 캐시 히트 발생
      await dataflowConfigCache.getConfig("metrics-test-1");
      await dataflowConfigCache.getConfig("metrics-test-1");

      const metrics = dataflowConfigCache.getMetrics();

      expect(metrics.totalRequests).toBe(4);
      expect(metrics.cacheHits).toBe(2);
      expect(metrics.cacheMisses).toBe(2);
      expect(metrics.hitRate).toBe(50);
      expect(metrics.averageResponseTime).toBeGreaterThan(0);
    });

    it("should track queue metrics accurately", () => {
      // 작업 추가
      dataflowJobQueue.enqueue("metrics-button-1", "save", mockButtonConfig, {}, "DEFAULT");
      dataflowJobQueue.enqueue("metrics-button-2", "delete", mockButtonConfig, {}, "DEFAULT");

      const metrics = dataflowJobQueue.getMetrics();

      expect(metrics.totalJobs).toBe(2);
      expect(metrics.pendingJobs).toBe(2);
      expect(metrics.processingJobs).toBe(0);
    });

    it("should provide performance recommendations", () => {
      // 느린 응답 시뮬레이션
      const slowCache = dataflowConfigCache as any;
      slowCache.metrics.averageResponseTime = 500; // 500ms

      const metrics = dataflowConfigCache.getMetrics();
      expect(metrics.averageResponseTime).toBe(500);

      // 성능 개선 권장사항 확인 (실제 구현에서)
      // expect(recommendations).toContain('캐싱 설정을 확인하세요');
    });
  });

  describe("🔧 Integration Performance", () => {
    it("should maintain performance under realistic load", async () => {
      const testScenarios = [
        { timing: "after", count: 10 },
        { timing: "before", count: 5 },
        { timing: "replace", count: 3 },
      ];

      const startTime = performance.now();

      for (const scenario of testScenarios) {
        const promises = Array.from({ length: scenario.count }, (_, i) =>
          optimizedButtonDataflowService.executeButtonWithDataflow(
            `load-test-${scenario.timing}-${i}`,
            "save",
            { ...mockButtonConfig, dataflowTiming: scenario.timing as any },
            { testData: `value-${i}` },
            "DEFAULT",
          ),
        );

        await Promise.all(promises);
      }

      const endTime = performance.now();
      const totalTime = endTime - startTime;
      const totalRequests = testScenarios.reduce((sum, s) => sum + s.count, 0);
      const averageTime = totalTime / totalRequests;

      // 🔥 실제 환경에서 평균 응답 시간 300ms 이내
      expect(averageTime).toBeLessThan(300);

      console.log(`Performance Test Results:`);
      console.log(`  Total requests: ${totalRequests}`);
      console.log(`  Total time: ${totalTime.toFixed(2)}ms`);
      console.log(`  Average time: ${averageTime.toFixed(2)}ms`);
    });
  });
});

// 🔥 성능 벤치마크 유틸리티
export class PerformanceBenchmark {
  private results: Array<{
    name: string;
    time: number;
    success: boolean;
  }> = [];

  async measure<T>(name: string, fn: () => Promise<T>): Promise<T> {
    const startTime = performance.now();
    let success = true;
    let result: T;

    try {
      result = await fn();
    } catch (error) {
      success = false;
      throw error;
    } finally {
      const endTime = performance.now();
      this.results.push({
        name,
        time: endTime - startTime,
        success,
      });
    }

    return result!;
  }

  getResults() {
    return {
      total: this.results.length,
      successful: this.results.filter((r) => r.success).length,
      failed: this.results.filter((r) => r.success === false).length,
      averageTime: this.results.reduce((sum, r) => sum + r.time, 0) / this.results.length,
      fastest: Math.min(...this.results.map((r) => r.time)),
      slowest: Math.max(...this.results.map((r) => r.time)),
      details: this.results,
    };
  }

  printReport() {
    const results = this.getResults();

    console.log("\n🔥 Performance Benchmark Report");
    console.log("================================");
    console.log(`Total tests: ${results.total}`);
    console.log(`Successful: ${results.successful} (${((results.successful / results.total) * 100).toFixed(1)}%)`);
    console.log(`Failed: ${results.failed}`);
    console.log(`Average time: ${results.averageTime.toFixed(2)}ms`);
    console.log(`Fastest: ${results.fastest.toFixed(2)}ms`);
    console.log(`Slowest: ${results.slowest.toFixed(2)}ms`);

    console.log("\nDetailed Results:");
    results.details.forEach((r) => {
      const status = r.success ? "✅" : "❌";
      console.log(`  ${status} ${r.name}: ${r.time.toFixed(2)}ms`);
    });
  }
}
