import {
  EnvironmentConfig,
  EnvironmentType,
  SSLConfig,
  CDNConfig,
  DatabaseConfig,
  MonitoringConfig,
} from "./types";

/**
 * Environment Configuration Manager
 * Handles configuration for different deployment environments
 */
export class EnvironmentConfigManager {
  private configs: Map<string, EnvironmentConfig> = new Map();
  private templates: Map<string, Partial<EnvironmentConfig>> = new Map();

  constructor() {
    this.loadDefaultTemplates();
  }

  /**
   * Load default environment templates
   */
  private loadDefaultTemplates(): void {
    // Development environment template
    this.templates.set("development", {
      type: "development",
      provider: "docker",
      region: "local",
      instances: [
        {
          id: "dev-instance-1",
          name: "Development Instance",
          type: "development",
          count: 1,
          cpu: 1,
          memory: 2,
          storage: {
            type: "gp2",
            size: 20,
            encrypted: false,
            backupRetention: 1,
          },
          subnet: "dev-subnet",
          securityGroups: ["dev-sg"],
          tags: {
            Environment: "development",
            Project: "AgentC",
          },
        },
      ],
      variables: {
        NODE_ENV: "development",
        LOG_LEVEL: "debug",
        API_TIMEOUT: "5000",
        CACHE_TTL: "300",
      },
      secrets: {
        DATABASE_URL: "postgresql://dev:dev@localhost:5432/agentc_dev",
        JWT_SECRET: "dev-jwt-secret",
        API_KEY: "dev-api-key",
      },
      features: [
        {
          id: "debug-mode",
          name: "Debug Mode",
          enabled: true,
        },
        {
          id: "hot-reload",
          name: "Hot Reload",
          enabled: true,
        },
      ],
      deploymentStrategy: "immediate",
      autoScale: {
        enabled: false,
        minInstances: 1,
        maxInstances: 1,
        cpuThreshold: 80,
        memoryThreshold: 80,
        requestThreshold: 100,
        scaleUpCooldown: 300,
        scaleDownCooldown: 300,
      },
      healthCheck: {
        enabled: true,
        path: "/health",
        protocol: "http",
        port: 3000,
        interval: 30,
        timeout: 5,
        healthyThreshold: 2,
        unhealthyThreshold: 3,
        expectedStatus: 200,
      },
      protected: false,
    });

    // Testing environment template
    this.templates.set("testing", {
      type: "testing",
      provider: "docker",
      region: "us-east-1",
      instances: [
        {
          id: "test-instance-1",
          name: "Testing Instance",
          type: "t3.small",
          count: 1,
          cpu: 1,
          memory: 2,
          storage: {
            type: "gp3",
            size: 30,
            encrypted: true,
            backupRetention: 3,
          },
          subnet: "test-subnet",
          securityGroups: ["test-sg"],
          tags: {
            Environment: "testing",
            Project: "AgentC",
          },
        },
      ],
      variables: {
        NODE_ENV: "test",
        LOG_LEVEL: "info",
        API_TIMEOUT: "10000",
        CACHE_TTL: "600",
      },
      secrets: {
        DATABASE_URL: "postgresql://test:test@test-db:5432/agentc_test",
        JWT_SECRET: "test-jwt-secret",
        API_KEY: "test-api-key",
      },
      features: [
        {
          id: "test-data",
          name: "Test Data",
          enabled: true,
        },
        {
          id: "performance-monitoring",
          name: "Performance Monitoring",
          enabled: true,
        },
      ],
      deploymentStrategy: "blue_green",
      autoScale: {
        enabled: false,
        minInstances: 1,
        maxInstances: 2,
        cpuThreshold: 70,
        memoryThreshold: 70,
        requestThreshold: 200,
        scaleUpCooldown: 300,
        scaleDownCooldown: 600,
      },
      healthCheck: {
        enabled: true,
        path: "/health",
        protocol: "https",
        port: 443,
        interval: 30,
        timeout: 10,
        healthyThreshold: 2,
        unhealthyThreshold: 2,
        expectedStatus: 200,
      },
      protected: false,
    });

    // Staging environment template
    this.templates.set("staging", {
      type: "staging",
      provider: "aws",
      region: "us-east-1",
      instances: [
        {
          id: "staging-instance-1",
          name: "Staging Instance",
          type: "t3.medium",
          count: 1,
          cpu: 2,
          memory: 4,
          storage: {
            type: "gp3",
            size: 50,
            encrypted: true,
            backupRetention: 7,
          },
          subnet: "staging-subnet",
          securityGroups: ["staging-sg"],
          tags: {
            Environment: "staging",
            Project: "AgentC",
          },
        },
      ],
      variables: {
        NODE_ENV: "staging",
        LOG_LEVEL: "info",
        API_TIMEOUT: "15000",
        CACHE_TTL: "1800",
      },
      secrets: {
        DATABASE_URL:
          "postgresql://staging:staging@staging-db:5432/agentc_staging",
        JWT_SECRET: "staging-jwt-secret",
        API_KEY: "staging-api-key",
      },
      features: [
        {
          id: "analytics",
          name: "Analytics",
          enabled: true,
        },
        {
          id: "rate-limiting",
          name: "Rate Limiting",
          enabled: true,
        },
      ],
      deploymentStrategy: "blue_green",
      autoScale: {
        enabled: true,
        minInstances: 1,
        maxInstances: 3,
        cpuThreshold: 70,
        memoryThreshold: 70,
        requestThreshold: 500,
        scaleUpCooldown: 300,
        scaleDownCooldown: 600,
      },
      healthCheck: {
        enabled: true,
        path: "/health",
        protocol: "https",
        port: 443,
        interval: 15,
        timeout: 10,
        healthyThreshold: 2,
        unhealthyThreshold: 2,
        expectedStatus: 200,
      },
      protected: true,
    });

    // Production environment template
    this.templates.set("production", {
      type: "production",
      provider: "aws",
      region: "us-east-1",
      instances: [
        {
          id: "prod-instance-1",
          name: "Production Instance",
          type: "t3.large",
          count: 2,
          cpu: 2,
          memory: 8,
          storage: {
            type: "gp3",
            size: 100,
            encrypted: true,
            backupRetention: 30,
          },
          subnet: "prod-subnet",
          securityGroups: ["prod-sg"],
          tags: {
            Environment: "production",
            Project: "AgentC",
          },
        },
      ],
      variables: {
        NODE_ENV: "production",
        LOG_LEVEL: "warn",
        API_TIMEOUT: "30000",
        CACHE_TTL: "3600",
      },
      secrets: {
        DATABASE_URL: "postgresql://prod:prod@prod-db:5432/agentc_prod",
        JWT_SECRET: "prod-jwt-secret",
        API_KEY: "prod-api-key",
      },
      features: [
        {
          id: "analytics",
          name: "Analytics",
          enabled: true,
        },
        {
          id: "rate-limiting",
          name: "Rate Limiting",
          enabled: true,
        },
        {
          id: "security-monitoring",
          name: "Security Monitoring",
          enabled: true,
        },
      ],
      deploymentStrategy: "blue_green",
      autoScale: {
        enabled: true,
        minInstances: 2,
        maxInstances: 10,
        cpuThreshold: 60,
        memoryThreshold: 60,
        requestThreshold: 1000,
        scaleUpCooldown: 300,
        scaleDownCooldown: 900,
      },
      healthCheck: {
        enabled: true,
        path: "/health",
        protocol: "https",
        port: 443,
        interval: 10,
        timeout: 5,
        healthyThreshold: 2,
        unhealthyThreshold: 2,
        expectedStatus: 200,
      },
      protected: true,
    });
  }

  /**
   * Get environment configuration by ID
   */
  getEnvironment(id: string): EnvironmentConfig | undefined {
    return this.configs.get(id);
  }

  /**
   * Get all environment configurations
   */
  getAllEnvironments(): EnvironmentConfig[] {
    return Array.from(this.configs.values());
  }

  /**
   * Get environments by type
   */
  getEnvironmentsByType(type: EnvironmentType): EnvironmentConfig[] {
    return Array.from(this.configs.values()).filter(
      (config) => config.type === type
    );
  }

  /**
   * Create environment from template
   */
  createFromTemplate(
    templateName: string,
    overrides: Partial<EnvironmentConfig>
  ): EnvironmentConfig {
    const template = this.templates.get(templateName);
    if (!template) {
      throw new Error(`Template ${templateName} not found`);
    }

    if (!template.type) {
      throw new Error(`Template ${templateName} missing required type`);
    }

    const config: EnvironmentConfig = {
      id: this.generateId(),
      name:
        overrides.name ||
        `${
          templateName.charAt(0).toUpperCase() + templateName.slice(1)
        } Environment`,
      type: template.type,
      description:
        overrides.description || `${templateName} environment for AgentC`,
      provider: template.provider || "docker",
      region: template.region || "local",
      instances: template.instances || [],
      variables: template.variables || {},
      secrets: template.secrets || {},
      features: template.features || [],
      domain: overrides.domain || this.generateDomain(templateName),
      subdomains: overrides.subdomains || [],
      ssl: overrides.ssl || this.getDefaultSSLConfig(),
      cdn: overrides.cdn || this.getDefaultCDNConfig(),
      database:
        overrides.database || this.getDefaultDatabaseConfig(templateName),
      monitoring:
        overrides.monitoring || this.getDefaultMonitoringConfig(templateName),
      deploymentStrategy: template.deploymentStrategy || "immediate",
      autoScale: template.autoScale || {
        enabled: false,
        minInstances: 1,
        maxInstances: 1,
        cpuThreshold: 80,
        memoryThreshold: 80,
        requestThreshold: 100,
        scaleUpCooldown: 300,
        scaleDownCooldown: 300,
      },
      healthCheck: template.healthCheck || {
        enabled: true,
        path: "/health",
        protocol: "http",
        port: 3000,
        interval: 30,
        timeout: 5,
        healthyThreshold: 2,
        unhealthyThreshold: 3,
        expectedStatus: 200,
      },
      active: true,
      protected: template.protected || false,
      createdBy: "system",
      createdAt: new Date(),
      updatedAt: new Date(),
      ...overrides,
    };

    this.configs.set(config.id, config);
    return config;
  }

  /**
   * Update environment configuration
   */
  updateEnvironment(
    id: string,
    updates: Partial<EnvironmentConfig>
  ): EnvironmentConfig {
    const config = this.configs.get(id);
    if (!config) {
      throw new Error(`Environment ${id} not found`);
    }

    const updatedConfig: EnvironmentConfig = {
      ...config,
      ...updates,
      updatedAt: new Date(),
    };

    this.configs.set(id, updatedConfig);
    return updatedConfig;
  }

  /**
   * Delete environment configuration
   */
  deleteEnvironment(id: string): boolean {
    const config = this.configs.get(id);
    if (!config) {
      return false;
    }

    if (config.protected) {
      throw new Error(`Cannot delete protected environment ${id}`);
    }

    return this.configs.delete(id);
  }

  /**
   * Validate environment configuration
   */
  validateEnvironment(config: EnvironmentConfig): string[] {
    const errors: string[] = [];

    // Basic validation
    if (!config.name || config.name.trim().length === 0) {
      errors.push("Environment name is required");
    }

    if (!config.domain || config.domain.trim().length === 0) {
      errors.push("Domain is required");
    }

    // Instance validation
    if (!config.instances || config.instances.length === 0) {
      errors.push("At least one instance is required");
    }

    config.instances?.forEach((instance, index) => {
      if (instance.count < 1) {
        errors.push(`Instance ${index + 1}: count must be at least 1`);
      }
      if (instance.cpu < 0.5) {
        errors.push(`Instance ${index + 1}: CPU must be at least 0.5`);
      }
      if (instance.memory < 1) {
        errors.push(`Instance ${index + 1}: memory must be at least 1GB`);
      }
    });

    // Auto-scale validation
    if (config.autoScale.enabled) {
      if (config.autoScale.minInstances > config.autoScale.maxInstances) {
        errors.push("Auto-scale min instances cannot exceed max instances");
      }
      if (
        config.autoScale.cpuThreshold < 10 ||
        config.autoScale.cpuThreshold > 100
      ) {
        errors.push("Auto-scale CPU threshold must be between 10-100%");
      }
    }

    // Health check validation
    if (config.healthCheck.enabled) {
      if (
        !config.healthCheck.path ||
        !config.healthCheck.path.startsWith("/")
      ) {
        errors.push("Health check path must start with '/'");
      }
      if (config.healthCheck.port < 1 || config.healthCheck.port > 65535) {
        errors.push("Health check port must be between 1-65535");
      }
    }

    return errors;
  }

  /**
   * Clone environment configuration
   */
  cloneEnvironment(
    sourceId: string,
    targetName: string,
    targetType?: EnvironmentType
  ): EnvironmentConfig {
    const sourceConfig = this.configs.get(sourceId);
    if (!sourceConfig) {
      throw new Error(`Source environment ${sourceId} not found`);
    }

    const clonedConfig: EnvironmentConfig = {
      ...JSON.parse(JSON.stringify(sourceConfig)), // Deep clone
      id: this.generateId(),
      name: targetName,
      type: targetType || sourceConfig.type,
      domain: this.generateDomain(targetName),
      createdAt: new Date(),
      updatedAt: new Date(),
      lastDeployment: undefined,
    };

    this.configs.set(clonedConfig.id, clonedConfig);
    return clonedConfig;
  }

  /**
   * Get environment health status
   */
  getEnvironmentHealth(id: string): {
    status: "healthy" | "degraded" | "unhealthy";
    issues: string[];
  } {
    const config = this.configs.get(id);
    if (!config) {
      return { status: "unhealthy", issues: ["Environment not found"] };
    }

    const issues: string[] = [];

    // Check if environment is active
    if (!config.active) {
      issues.push("Environment is inactive");
    }

    // Check instance health (mock implementation)
    config.instances.forEach((instance, index) => {
      if (instance.count === 0) {
        issues.push(`Instance ${index + 1} has no running instances`);
      }
    });

    // Check health check configuration
    if (!config.healthCheck.enabled) {
      issues.push("Health checks are disabled");
    }

    // Determine overall status
    let status: "healthy" | "degraded" | "unhealthy";
    if (issues.length === 0) {
      status = "healthy";
    } else if (issues.length <= 2) {
      status = "degraded";
    } else {
      status = "unhealthy";
    }

    return { status, issues };
  }

  /**
   * Generate environment ID
   */
  private generateId(): string {
    return `env_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  /**
   * Generate domain for environment
   */
  private generateDomain(name: string): string {
    const sanitized = name.toLowerCase().replace(/[^a-z0-9]/g, "-");
    return `${sanitized}.agentc.dev`;
  }

  /**
   * Get default SSL configuration
   */
  private getDefaultSSLConfig(): SSLConfig {
    return {
      enabled: true,
      certificateProvider: "letsencrypt",
      autoRenewal: true,
    };
  }

  /**
   * Get default CDN configuration
   */
  private getDefaultCDNConfig(): CDNConfig {
    return {
      enabled: true,
      provider: "cloudflare",
      cacheRules: [
        {
          path: "/static/*",
          ttl: 86400,
          cacheHeaders: ["Cache-Control", "ETag"],
        },
        {
          path: "/api/*",
          ttl: 300,
          cacheHeaders: ["Cache-Control"],
        },
      ],
      origins: [
        {
          id: "primary",
          url: "https://api.agentc.dev",
          weight: 100,
          healthCheck: true,
        },
      ],
    };
  }

  /**
   * Get default database configuration
   */
  private getDefaultDatabaseConfig(environment: string): DatabaseConfig {
    return {
      provider: "postgresql",
      host: `${environment}-db.agentc.dev`,
      port: 5432,
      database: `agentc_${environment}`,
      username: "agentc",
      password: "encrypted_password",
      minConnections: 5,
      maxConnections: 20,
      backupSchedule: "0 2 * * *", // Daily at 2 AM
      backupRetention: environment === "production" ? 30 : 7,
      replication: environment === "production",
      readReplicas: environment === "production" ? 1 : 0,
    };
  }

  /**
   * Get default monitoring configuration
   */
  private getDefaultMonitoringConfig(environment: string): MonitoringConfig {
    return {
      enabled: true,
      provider: "prometheus",
      customMetrics: [
        {
          name: "request_duration",
          type: "histogram",
          description: "Request duration in milliseconds",
          labels: ["method", "route", "status"],
        },
        {
          name: "active_connections",
          type: "gauge",
          description: "Number of active connections",
          labels: ["type"],
        },
      ],
      alerts: [
        {
          id: "high_cpu",
          name: "High CPU Usage",
          condition: "cpu_usage > 80",
          threshold: 80,
          severity: "medium",
          channels: [
            {
              type: "email",
              target: "alerts@agentc.dev",
              enabled: true,
            },
          ],
          enabled: true,
          cooldown: 15,
        },
        {
          id: "high_error_rate",
          name: "High Error Rate",
          condition: "error_rate > 5",
          threshold: 5,
          severity: "high",
          channels: [
            {
              type: "slack",
              target: "#alerts",
              enabled: true,
            },
          ],
          enabled: true,
          cooldown: 5,
        },
      ],
      logging: {
        level: environment === "production" ? "warn" : "info",
        retention: environment === "production" ? 30 : 7,
        structured: true,
        aggregation: environment !== "development",
        aggregationProvider:
          environment !== "development" ? "elasticsearch" : undefined,
      },
      apm: {
        enabled: environment !== "development",
        provider: "datadog",
        tracing: true,
        profiling: environment === "production",
      },
    };
  }

  /**
   * Export environment configuration as YAML
   */
  exportAsYAML(id: string): string {
    const config = this.configs.get(id);
    if (!config) {
      throw new Error(`Environment ${id} not found`);
    }

    // Simple YAML export (in production, use a proper YAML library)
    return JSON.stringify(config, null, 2);
  }

  /**
   * Import environment configuration from YAML
   */
  importFromYAML(yaml: string): EnvironmentConfig {
    try {
      const config = JSON.parse(yaml) as EnvironmentConfig;

      // Validate imported config
      const errors = this.validateEnvironment(config);
      if (errors.length > 0) {
        throw new Error(`Validation errors: ${errors.join(", ")}`);
      }

      // Assign new ID and update timestamps
      config.id = this.generateId();
      config.createdAt = new Date();
      config.updatedAt = new Date();

      this.configs.set(config.id, config);
      return config;
    } catch (error) {
      throw new Error(
        `Failed to import configuration: ${
          error instanceof Error ? error.message : "Unknown error"
        }`
      );
    }
  }

  /**
   * Get configuration template names
   */
  getTemplateNames(): string[] {
    return Array.from(this.templates.keys());
  }

  /**
   * Create all default environments
   */
  createDefaultEnvironments(): EnvironmentConfig[] {
    const environments: EnvironmentConfig[] = [];

    for (const templateName of this.getTemplateNames()) {
      const config = this.createFromTemplate(templateName, {
        name: `${
          templateName.charAt(0).toUpperCase() + templateName.slice(1)
        } Environment`,
        description: `Default ${templateName} environment for AgentC Starter Kit`,
      });
      environments.push(config);
    }

    return environments;
  }
}

// Export singleton instance
export const environmentConfig = new EnvironmentConfigManager();
