// Vault Service Configuration Service
// Configures Vault services after virtual vault provisioning

import { logger } from '@/infrastructure/monitoring/logger';
import { vaultProvisioningService } from '../provisioning/vault-provisioning.service';

export interface VaultServiceConfig {
  vaultId: string;
  vaultPath: string;
  roleId: string;
  secretId: string;
  apiEndpoint: string;
  organizationId: string;
  subscriptionId: string;
}

export interface VaultServiceConfigResult {
  success: boolean;
  vaultId: string;
  configured: boolean;
  endpoints?: {
    api: string;
    health: string;
  };
  credentials?: {
    roleId: string;
    secretId: string;
  };
  error?: string;
}

export class VaultServiceConfigService {
  /**
   * Configure Vault service for a deployment
   */
  async configureVaultService(config: VaultServiceConfig): Promise<VaultServiceConfigResult> {
    logger.info('Configuring Vault service', {
      vaultId: config.vaultId,
      subscriptionId: config.subscriptionId,
    });

    try {
      // Verify vault is accessible
      const healthCheck = await this.verifyVaultHealth(config.apiEndpoint);
      if (!healthCheck.healthy) {
        throw new Error(`Vault cluster is not healthy: ${healthCheck.error}`);
      }

      // Verify AppRole credentials work
      const authCheck = await this.verifyAppRoleAuth(config.apiEndpoint, config.roleId, config.secretId);
      if (!authCheck.valid) {
        throw new Error(`AppRole authentication failed: ${authCheck.error}`);
      }

      // Verify vault path is accessible
      const pathCheck = await this.verifyVaultPath(config.apiEndpoint, config.roleId, config.secretId, config.vaultPath);
      if (!pathCheck.accessible) {
        throw new Error(`Vault path is not accessible: ${pathCheck.error}`);
      }

      logger.info('Vault service configured successfully', {
        vaultId: config.vaultId,
        subscriptionId: config.subscriptionId,
      });

      return {
        success: true,
        vaultId: config.vaultId,
        configured: true,
        endpoints: {
          api: config.apiEndpoint,
          health: `${config.apiEndpoint}/v1/sys/health`,
        },
        credentials: {
          roleId: config.roleId,
          secretId: config.secretId,
        },
      };
    } catch (error) {
      logger.error('Failed to configure Vault service', {
        vaultId: config.vaultId,
        error: error instanceof Error ? error.message : 'Unknown error',
      });

      return {
        success: false,
        vaultId: config.vaultId,
        configured: false,
        error: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  /**
   * Verify Vault cluster health
   */
  private async verifyVaultHealth(endpoint: string): Promise<{ healthy: boolean; error?: string }> {
    try {
      const fetch = (await import('node-fetch')).default;
      const response = await fetch(`${endpoint}/v1/sys/health`, {
        method: 'GET',
      });

      if (!response.ok) {
        return { healthy: false, error: `HTTP ${response.status}` };
      }

      const data = await response.json();
      if (data.sealed) {
        return { healthy: false, error: 'Vault cluster is sealed' };
      }

      return { healthy: true };
    } catch (error) {
      return {
        healthy: false,
        error: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  /**
   * Verify AppRole authentication
   */
  private async verifyAppRoleAuth(
    endpoint: string,
    roleId: string,
    secretId: string
  ): Promise<{ valid: boolean; error?: string; token?: string }> {
    try {
      const fetch = (await import('node-fetch')).default;
      const response = await fetch(`${endpoint}/v1/auth/approle/login`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ role_id: roleId, secret_id: secretId }),
      });

      if (!response.ok) {
        return { valid: false, error: `HTTP ${response.status}` };
      }

      const data = await response.json();
      if (!data.auth || !data.auth.client_token) {
        return { valid: false, error: 'No token in response' };
      }

      return { valid: true, token: data.auth.client_token };
    } catch (error) {
      return {
        valid: false,
        error: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  /**
   * Verify vault path is accessible
   */
  private async verifyVaultPath(
    endpoint: string,
    roleId: string,
    secretId: string,
    vaultPath: string
  ): Promise<{ accessible: boolean; error?: string }> {
    try {
      // First authenticate
      const auth = await this.verifyAppRoleAuth(endpoint, roleId, secretId);
      if (!auth.valid || !auth.token) {
        return { accessible: false, error: 'Authentication failed' };
      }

      // Try to read the path
      const fetch = (await import('node-fetch')).default;
      const response = await fetch(`${endpoint}/v1/${vaultPath}`, {
        method: 'GET',
        headers: {
          'X-Vault-Token': auth.token,
        },
      });

      // 404 is acceptable (path exists but empty)
      if (response.status === 404) {
        return { accessible: true };
      }

      if (!response.ok && response.status !== 404) {
        return { accessible: false, error: `HTTP ${response.status}` };
      }

      return { accessible: true };
    } catch (error) {
      return {
        accessible: false,
        error: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }
}

export const vaultServiceConfigService = new VaultServiceConfigService();
