/**
 * Integration test for performance requirements
 *
 * This test verifies that the credential manager meets all performance requirements:
 * 1. Hot reload: <100ms for configuration file changes
 * 2. Signing operations: <50ms per signature
 * 3. Memory usage: <50MB total
 * 4. Concurrent operations: Support 50+ accounts
 * 5. Throughput: Handle high-frequency operations efficiently
 *
 * Tests MUST FAIL initially until implementation is provided.
 */

import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';
import * as fs from 'fs/promises';
import * as path from 'path';
import * as os from 'os';

// Import types (this import will fail until types are implemented)
import type {
  ICredentialManager,
  SignResult,
  LoadResult,
  Account,
  Platform,
  ConfigFile
} from '@/specs/001-credential-manager/contracts/credential-manager';

describe('Performance Requirements Integration Tests', () => {
  let credentialManager: ICredentialManager;
  let tempDir: string;
  let configPath: string;

  // Performance test utilities
  const measureTime = async <T>(operation: () => Promise<T>): Promise<{ result: T; duration: number }> => {
    const startTime = Date.now();
    const result = await operation();
    const duration = Date.now() - startTime;
    return { result, duration };
  };

  const measureMemory = (): number => {
    if (process.memoryUsage) {
      return process.memoryUsage().heapUsed / (1024 * 1024); // MB
    }
    return 0;
  };

  beforeEach(async () => {
    // This will fail until CredentialManager is implemented
    const { CredentialManager } = await import('@/core/credential-manager/CredentialManager');
    credentialManager = new CredentialManager();

    // Create temporary directory
    tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'performance-test-'));
    configPath = path.join(tempDir, 'performance-config.json');
  });

  afterEach(async () => {
    // Clean up
    credentialManager.stopWatching();

    try {
      await fs.rm(tempDir, { recursive: true, force: true });
    } catch (error) {
      // Ignore cleanup errors
    }
  });

  describe('Hot Reload Performance (<100ms)', () => {
    test('should reload small configuration within 100ms', async () => {
      // Arrange
      const smallConfig: ConfigFile = {
        version: "1.0",
        accounts: [
          {
            id: "small-test-account",
            platform: Platform.PACIFICA,
            name: "Small Test Account",
            credentials: {
              type: "ed25519",
              privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
            }
          }
        ]
      };

      await fs.writeFile(configPath, JSON.stringify(smallConfig));
      await credentialManager.loadConfig(configPath);

      const reloadPromise = new Promise<{ accounts: Account[]; reloadTime: number }>((resolve) => {
        const startTime = Date.now();
        credentialManager.watchConfig(configPath, (accounts) => {
          const reloadTime = Date.now() - startTime;
          resolve({ accounts, reloadTime });
        });
      });

      // Wait for watcher to initialize
      await new Promise(resolve => setTimeout(resolve, 50));

      // Act - modify configuration
      const modifiedConfig: ConfigFile = {
        ...smallConfig,
        accounts: [
          ...smallConfig.accounts,
          {
            id: "added-account",
            platform: Platform.BINANCE,
            name: "Added Account",
            credentials: {
              type: "hmac",
              apiKey: "test-key",
              secretKey: "test-secret"
            }
          }
        ]
      };

      await fs.writeFile(configPath, JSON.stringify(modifiedConfig, null, 2));

      // Assert
      const { accounts, reloadTime } = await Promise.race([
        reloadPromise,
        new Promise<never>((_, reject) =>
          setTimeout(() => reject(new Error('Reload timeout')), 5000)
        )
      ]);

      expect(reloadTime).toBeLessThan(100); // Core requirement
      expect(accounts).toHaveLength(2);
    });

    test('should reload medium configuration (10 accounts) within 100ms', async () => {
      // Arrange - 10 accounts
      const mediumConfig: ConfigFile = {
        version: "1.0",
        accounts: Array(10).fill(null).map((_, index) => ({
          id: `medium-account-${index}`,
          platform: Platform.PACIFICA,
          name: `Medium Account ${index}`,
          credentials: {
            type: "ed25519",
            privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
          }
        }))
      };

      await fs.writeFile(configPath, JSON.stringify(mediumConfig));

      // Act & Assert
      const { result, duration } = await measureTime(() =>
        credentialManager.loadConfig(configPath)
      );

      expect(result.success).toBe(true);
      expect(duration).toBeLessThan(100);
      expect(result.loadTime).toBeLessThan(100);
    });

    test('should reload large configuration (50 accounts) within 100ms', async () => {
      // Arrange - 50 accounts (edge of requirement)
      const largeConfig: ConfigFile = {
        version: "1.0",
        accounts: Array(50).fill(null).map((_, index) => ({
          id: `large-account-${index}`,
          platform: index % 3 === 0 ? Platform.PACIFICA :
                   index % 3 === 1 ? Platform.ASTER : Platform.BINANCE,
          name: `Large Account ${index}`,
          credentials: index % 3 === 0 ? {
            type: "ed25519",
            privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
          } : index % 3 === 1 ? {
            type: "eip191",
            privateKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
          } : {
            type: "hmac",
            apiKey: `api-key-${index}`,
            secretKey: `secret-key-${index}`
          }
        }))
      };

      await fs.writeFile(configPath, JSON.stringify(largeConfig));

      // Act & Assert
      const { result, duration } = await measureTime(() =>
        credentialManager.loadConfig(configPath)
      );

      expect(result.success).toBe(true);
      expect(duration).toBeLessThan(100); // Critical requirement
      expect(result.loadTime).toBeLessThan(100);
      expect(result.accounts).toHaveLength(50);
    });

    test('should handle incremental updates efficiently', async () => {
      // Arrange - start with base configuration
      const baseConfig: ConfigFile = {
        version: "1.0",
        accounts: Array(20).fill(null).map((_, index) => ({
          id: `base-account-${index}`,
          platform: Platform.PACIFICA,
          name: `Base Account ${index}`,
          credentials: {
            type: "ed25519",
            privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
          }
        }))
      };

      await fs.writeFile(configPath, JSON.stringify(baseConfig));
      await credentialManager.loadConfig(configPath);

      const reloadTimes: number[] = [];

      // Setup reload measurement
      const reloadPromise = new Promise<void>((resolve) => {
        let reloadCount = 0;
        credentialManager.watchConfig(configPath, () => {
          reloadTimes.push(Date.now());
          reloadCount++;
          if (reloadCount === 5) resolve();
        });
      });

      // Wait for watcher
      await new Promise(resolve => setTimeout(resolve, 50));

      // Act - make incremental changes
      for (let i = 0; i < 5; i++) {
        const updatedConfig = {
          ...baseConfig,
          accounts: [
            ...baseConfig.accounts,
            {
              id: `incremental-account-${i}`,
              platform: Platform.BINANCE,
              name: `Incremental Account ${i}`,
              credentials: {
                type: "hmac",
                apiKey: `key-${i}`,
                secretKey: `secret-${i}`
              }
            }
          ]
        };

        const startTime = Date.now();
        await fs.writeFile(configPath, JSON.stringify(updatedConfig));

        // Wait for this reload to complete
        await new Promise(resolve => setTimeout(resolve, 120));
      }

      // Assert - each reload should be fast
      await reloadPromise;
      expect(reloadTimes).toHaveLength(5);
    });
  });

  describe('Signing Performance (<50ms)', () => {
    test('should sign Pacifica messages within 50ms', async () => {
      // Arrange
      const config: ConfigFile = {
        version: "1.0",
        accounts: [
          {
            id: "pacifica-perf-account",
            platform: Platform.PACIFICA,
            name: "Pacifica Performance Account",
            credentials: {
              type: "ed25519",
              privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
            }
          }
        ]
      };

      await fs.writeFile(configPath, JSON.stringify(config));
      await credentialManager.loadConfig(configPath);

      const message = new TextEncoder().encode("Performance test message");

      // Act & Assert - multiple signing operations
      for (let i = 0; i < 10; i++) {
        const { result, duration } = await measureTime(() =>
          credentialManager.sign("pacifica-perf-account", message)
        );

        expect(result.success).toBe(true);
        expect(duration).toBeLessThan(50); // Core requirement
      }
    });

    test('should sign Aster messages within 50ms', async () => {
      // Arrange
      const config: ConfigFile = {
        version: "1.0",
        accounts: [
          {
            id: "aster-perf-account",
            platform: Platform.ASTER,
            name: "Aster Performance Account",
            credentials: {
              type: "eip191",
              privateKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
            }
          }
        ]
      };

      await fs.writeFile(configPath, JSON.stringify(config));
      await credentialManager.loadConfig(configPath);

      const message = new TextEncoder().encode("Aster performance test");

      // Act & Assert
      for (let i = 0; i < 10; i++) {
        const { result, duration } = await measureTime(() =>
          credentialManager.sign("aster-perf-account", message)
        );

        expect(result.success).toBe(true);
        expect(duration).toBeLessThan(50);
      }
    });

    test('should sign Binance messages within 50ms', async () => {
      // Arrange
      const config: ConfigFile = {
        version: "1.0",
        accounts: [
          {
            id: "binance-perf-account",
            platform: Platform.BINANCE,
            name: "Binance Performance Account",
            credentials: {
              type: "hmac",
              apiKey: "performance-api-key",
              secretKey: "performance-secret-key"
            }
          }
        ]
      };

      await fs.writeFile(configPath, JSON.stringify(config));
      await credentialManager.loadConfig(configPath);

      const message = new TextEncoder().encode("symbol=BTCUSDT&side=BUY&type=MARKET&quantity=0.1");

      // Act & Assert
      for (let i = 0; i < 10; i++) {
        const { result, duration } = await measureTime(() =>
          credentialManager.sign("binance-perf-account", message)
        );

        expect(result.success).toBe(true);
        expect(duration).toBeLessThan(50);
      }
    });

    test('should handle concurrent signing requests efficiently', async () => {
      // Arrange - multiple accounts
      const config: ConfigFile = {
        version: "1.0",
        accounts: [
          {
            id: "concurrent-pacifica",
            platform: Platform.PACIFICA,
            name: "Concurrent Pacifica",
            credentials: {
              type: "ed25519",
              privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
            }
          },
          {
            id: "concurrent-aster",
            platform: Platform.ASTER,
            name: "Concurrent Aster",
            credentials: {
              type: "eip191",
              privateKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
            }
          },
          {
            id: "concurrent-binance",
            platform: Platform.BINANCE,
            name: "Concurrent Binance",
            credentials: {
              type: "hmac",
              apiKey: "concurrent-api-key",
              secretKey: "concurrent-secret-key"
            }
          }
        ]
      };

      await fs.writeFile(configPath, JSON.stringify(config));
      await credentialManager.loadConfig(configPath);

      const message = new TextEncoder().encode("Concurrent test message");

      // Act - create many concurrent signing requests
      const concurrentOperations = Array(20).fill(null).map((_, index) => {
        const accountId = index % 3 === 0 ? "concurrent-pacifica" :
                         index % 3 === 1 ? "concurrent-aster" : "concurrent-binance";
        return measureTime(() => credentialManager.sign(accountId, message));
      });

      const startTime = Date.now();
      const results = await Promise.all(concurrentOperations);
      const totalDuration = Date.now() - startTime;

      // Assert - all should complete successfully and quickly
      results.forEach(({ result, duration }) => {
        expect(result.success).toBe(true);
        expect(duration).toBeLessThan(50); // Individual operation
      });

      // Total time should be reasonable (not just sum of individual times)
      expect(totalDuration).toBeLessThan(500); // 20 operations in <500ms
    });

    test('should maintain performance under sustained load', async () => {
      // Arrange
      const config: ConfigFile = {
        version: "1.0",
        accounts: [
          {
            id: "sustained-load-account",
            platform: Platform.PACIFICA,
            name: "Sustained Load Account",
            credentials: {
              type: "ed25519",
              privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
            }
          }
        ]
      };

      await fs.writeFile(configPath, JSON.stringify(config));
      await credentialManager.loadConfig(configPath);

      const message = new TextEncoder().encode("Sustained load test");
      const durations: number[] = [];

      // Act - sustained signing operations
      for (let i = 0; i < 100; i++) {
        const { result, duration } = await measureTime(() =>
          credentialManager.sign("sustained-load-account", message)
        );

        expect(result.success).toBe(true);
        durations.push(duration);

        // Small delay to simulate real usage
        await new Promise(resolve => setTimeout(resolve, 10));
      }

      // Assert - performance should not degrade significantly
      const averageDuration = durations.reduce((a, b) => a + b, 0) / durations.length;
      const maxDuration = Math.max(...durations);

      expect(averageDuration).toBeLessThan(50);
      expect(maxDuration).toBeLessThan(100); // Allow some variance but not too much
    });
  });

  describe('Memory Usage (<50MB)', () => {
    test('should maintain memory usage under 50MB with many accounts', async () => {
      // Arrange - large configuration
      const largeConfig: ConfigFile = {
        version: "1.0",
        accounts: Array(100).fill(null).map((_, index) => ({
          id: `memory-test-account-${index}`,
          platform: index % 3 === 0 ? Platform.PACIFICA :
                   index % 3 === 1 ? Platform.ASTER : Platform.BINANCE,
          name: `Memory Test Account ${index}`,
          credentials: index % 3 === 0 ? {
            type: "ed25519",
            privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
          } : index % 3 === 1 ? {
            type: "eip191",
            privateKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
          } : {
            type: "hmac",
            apiKey: `memory-api-key-${index}`,
            secretKey: `memory-secret-key-${index}`
          }
        }))
      };

      const initialMemory = measureMemory();

      // Act
      await fs.writeFile(configPath, JSON.stringify(largeConfig));
      await credentialManager.loadConfig(configPath);

      // Perform some operations to fully load everything
      for (let i = 0; i < 10; i++) {
        const accountId = `memory-test-account-${i * 10}`;
        const message = new TextEncoder().encode(`Memory test ${i}`);
        await credentialManager.sign(accountId, message);
      }

      const finalMemory = measureMemory();
      const memoryIncrease = finalMemory - initialMemory;

      // Assert - memory increase should be reasonable
      expect(memoryIncrease).toBeLessThan(50); // Core requirement
    });

    test('should not leak memory during repeated reloads', async () => {
      // Arrange
      const baseConfig: ConfigFile = {
        version: "1.0",
        accounts: Array(20).fill(null).map((_, index) => ({
          id: `leak-test-account-${index}`,
          platform: Platform.PACIFICA,
          name: `Leak Test Account ${index}`,
          credentials: {
            type: "ed25519",
            privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
          }
        }))
      };

      await fs.writeFile(configPath, JSON.stringify(baseConfig));

      const initialMemory = measureMemory();

      // Act - repeated reloads
      for (let i = 0; i < 10; i++) {
        const modifiedConfig = {
          ...baseConfig,
          accounts: baseConfig.accounts.map(account => ({
            ...account,
            name: `${account.name} - Reload ${i}`
          }))
        };

        await fs.writeFile(configPath, JSON.stringify(modifiedConfig));
        await credentialManager.loadConfig(configPath);

        // Perform some operations
        const message = new TextEncoder().encode(`Reload test ${i}`);
        await credentialManager.sign("leak-test-account-0", message);
      }

      const finalMemory = measureMemory();
      const memoryIncrease = finalMemory - initialMemory;

      // Assert - should not accumulate significant memory
      expect(memoryIncrease).toBeLessThan(10); // Should be minimal increase
    });
  });

  describe('Scalability (50+ Accounts)', () => {
    test('should support exactly 50 accounts efficiently', async () => {
      // Arrange - exactly 50 accounts
      const fiftyAccountConfig: ConfigFile = {
        version: "1.0",
        accounts: Array(50).fill(null).map((_, index) => ({
          id: `scalability-account-${index}`,
          platform: index % 3 === 0 ? Platform.PACIFICA :
                   index % 3 === 1 ? Platform.ASTER : Platform.BINANCE,
          name: `Scalability Account ${index}`,
          credentials: index % 3 === 0 ? {
            type: "ed25519",
            privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
          } : index % 3 === 1 ? {
            type: "eip191",
            privateKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
          } : {
            type: "hmac",
            apiKey: `scalability-api-key-${index}`,
            secretKey: `scalability-secret-key-${index}`
          }
        }))
      };

      // Act & Assert
      await fs.writeFile(configPath, JSON.stringify(fiftyAccountConfig));

      const { result, duration } = await measureTime(() =>
        credentialManager.loadConfig(configPath)
      );

      expect(result.success).toBe(true);
      expect(result.accounts).toHaveLength(50);
      expect(duration).toBeLessThan(100); // Should still meet reload requirement

      // Verify all accounts are accessible
      const allAccounts = credentialManager.listAccounts();
      expect(allAccounts).toHaveLength(50);

      // Test random access performance
      for (let i = 0; i < 10; i++) {
        const randomIndex = Math.floor(Math.random() * 50);
        const accountId = `scalability-account-${randomIndex}`;
        const account = credentialManager.getAccount(accountId);
        expect(account).not.toBeNull();
      }
    });

    test('should handle concurrent operations across all 50 accounts', async () => {
      // Arrange - 50 accounts
      const manyAccountsConfig: ConfigFile = {
        version: "1.0",
        accounts: Array(50).fill(null).map((_, index) => ({
          id: `concurrent-account-${index}`,
          platform: Platform.PACIFICA, // Use single platform for simplicity
          name: `Concurrent Account ${index}`,
          credentials: {
            type: "ed25519",
            privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
          }
        }))
      };

      await fs.writeFile(configPath, JSON.stringify(manyAccountsConfig));
      await credentialManager.loadConfig(configPath);

      // Act - concurrent operations across all accounts
      const message = new TextEncoder().encode("Concurrent scalability test");
      const concurrentOperations = Array(50).fill(null).map((_, index) =>
        measureTime(() => credentialManager.sign(`concurrent-account-${index}`, message))
      );

      const startTime = Date.now();
      const results = await Promise.all(concurrentOperations);
      const totalDuration = Date.now() - startTime;

      // Assert - all operations should succeed
      results.forEach(({ result, duration }, index) => {
        expect(result.success).toBe(true);
        expect(duration).toBeLessThan(50); // Individual operation requirement
      });

      // Total time should scale reasonably
      expect(totalDuration).toBeLessThan(1000); // 50 operations in <1 second
    });

    test('should maintain performance with over 50 accounts', async () => {
      // Arrange - 75 accounts (beyond minimum requirement)
      const manyAccountsConfig: ConfigFile = {
        version: "1.0",
        accounts: Array(75).fill(null).map((_, index) => ({
          id: `beyond-fifty-account-${index}`,
          platform: index % 3 === 0 ? Platform.PACIFICA :
                   index % 3 === 1 ? Platform.ASTER : Platform.BINANCE,
          name: `Beyond Fifty Account ${index}`,
          credentials: index % 3 === 0 ? {
            type: "ed25519",
            privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
          } : index % 3 === 1 ? {
            type: "eip191",
            privateKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
          } : {
            type: "hmac",
            apiKey: `beyond-api-key-${index}`,
            secretKey: `beyond-secret-key-${index}`
          }
        }))
      };

      // Act
      await fs.writeFile(configPath, JSON.stringify(manyAccountsConfig));

      const { result, duration } = await measureTime(() =>
        credentialManager.loadConfig(configPath)
      );

      // Assert - should handle gracefully even beyond minimum
      expect(result.success).toBe(true);
      expect(result.accounts).toHaveLength(75);

      // Performance may degrade slightly but should still be reasonable
      expect(duration).toBeLessThan(200); // Allow slightly more time for 75 accounts
    });
  });

  describe('High-Frequency Operations', () => {
    test('should handle high-frequency signing requests', async () => {
      // Arrange
      const config: ConfigFile = {
        version: "1.0",
        accounts: [
          {
            id: "high-freq-account",
            platform: Platform.PACIFICA,
            name: "High Frequency Account",
            credentials: {
              type: "ed25519",
              privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
            }
          }
        ]
      };

      await fs.writeFile(configPath, JSON.stringify(config));
      await credentialManager.loadConfig(configPath);

      // Act - rapid-fire signing requests
      const operations: Promise<SignResult>[] = [];
      const startTime = Date.now();

      for (let i = 0; i < 100; i++) {
        const message = new TextEncoder().encode(`High freq message ${i}`);
        operations.push(credentialManager.sign("high-freq-account", message));
      }

      const results = await Promise.all(operations);
      const totalDuration = Date.now() - startTime;

      // Assert
      results.forEach((result, index) => {
        expect(result.success).toBe(true);
      });

      // Should handle 100 operations efficiently
      const avgTimePerOperation = totalDuration / 100;
      expect(avgTimePerOperation).toBeLessThan(50);
    });

    test('should handle mixed operation types efficiently', async () => {
      // Arrange
      const config: ConfigFile = {
        version: "1.0",
        accounts: Array(10).fill(null).map((_, index) => ({
          id: `mixed-ops-account-${index}`,
          platform: Platform.PACIFICA,
          name: `Mixed Ops Account ${index}`,
          credentials: {
            type: "ed25519",
            privateKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
          }
        }))
      };

      await fs.writeFile(configPath, JSON.stringify(config));
      await credentialManager.loadConfig(configPath);

      // Act - mix of operations: sign, verify, getAccount, listAccounts
      const operations: Promise<any>[] = [];
      const message = new TextEncoder().encode("Mixed operations test");

      for (let i = 0; i < 50; i++) {
        const accountId = `mixed-ops-account-${i % 10}`;

        if (i % 4 === 0) {
          // Sign operation
          operations.push(credentialManager.sign(accountId, message));
        } else if (i % 4 === 1) {
          // Get account operation
          operations.push(Promise.resolve(credentialManager.getAccount(accountId)));
        } else if (i % 4 === 2) {
          // List accounts operation
          operations.push(Promise.resolve(credentialManager.listAccounts()));
        } else {
          // Verify operation (with dummy signature)
          operations.push(credentialManager.verify(accountId, message, "dummy-signature"));
        }
      }

      const startTime = Date.now();
      const results = await Promise.all(operations);
      const totalDuration = Date.now() - startTime;

      // Assert - should handle mixed operations efficiently
      expect(results).toHaveLength(50);
      expect(totalDuration).toBeLessThan(1000); // 50 mixed operations in <1 second
    });
  });
});