/**
 * Compliance Enforcer Service
 * Enforces regulatory compliance and data residency rules
 */

import { getDb } from '../db/index.js'
import { logger } from '../lib/logger.js'
import { Context } from '../types/context.js'

export interface ComplianceResult {
  compliant: boolean
  violations: string[]
  warnings: string[]
  requiredActions: string[]
}

export enum RegulatoryFramework {
  GDPR = 'GDPR',
  CCPA = 'CCPA',
  HIPAA = 'HIPAA',
  PCI_DSS = 'PCI-DSS',
  SOX = 'SOX',
  CALEA = 'CALEA',
  FERPA = 'FERPA',
  FEDRAMP = 'FEDRAMP',
}

class ComplianceEnforcer {
  /**
   * Check data residency compliance
   */
  async checkDataResidency(
    context: Context,
    data: any,
    targetRegion: string
  ): Promise<boolean> {
    const db = getDb()

    // Get data residency rules for data type
    const rulesResult = await db.query(
      `SELECT * FROM data_residency_rules 
       WHERE data_type = $1`,
      [data.type || 'default']
    )

    if (rulesResult.rows.length === 0) {
      return true // No restrictions
    }

    for (const rule of rulesResult.rows) {
      // Check if target region is prohibited
      if (
        rule.prohibited_regions &&
        rule.prohibited_regions.includes(targetRegion)
      ) {
        return false
      }

      // Check if target region is in allowed list
      if (
        rule.allowed_regions &&
        rule.allowed_regions.length > 0 &&
        !rule.allowed_regions.includes(targetRegion)
      ) {
        return false
      }
    }

    return true
  }

  /**
   * Validate regulatory compliance
   */
  async validateRegulatoryCompliance(
    context: Context,
    data: any,
    operation: 'READ' | 'WRITE' | 'REPLICATE',
    region: string,
    frameworks: RegulatoryFramework[]
  ): Promise<ComplianceResult> {
    const violations: string[] = []
    const warnings: string[] = []
    const requiredActions: string[] = []

    for (const framework of frameworks) {
      const result = await this.validateFramework(
        framework,
        data,
        operation,
        region
      )

      if (!result.compliant) {
        violations.push(...result.violations)
      }

      warnings.push(...result.warnings)
      requiredActions.push(...result.requiredActions)
    }

    return {
      compliant: violations.length === 0,
      violations,
      warnings,
      requiredActions,
    }
  }

  /**
   * Validate specific framework
   */
  private async validateFramework(
    framework: RegulatoryFramework,
    data: any,
    operation: string,
    region: string
  ): Promise<ComplianceResult> {
    const violations: string[] = []
    const warnings: string[] = []
    const requiredActions: string[] = []

    switch (framework) {
      case RegulatoryFramework.GDPR:
        // GDPR: Data must remain in EU
        if (operation === 'REPLICATE' && !this.isEURegion(region)) {
          violations.push('GDPR: Data cannot be replicated outside EU')
        }
        if (data.personalData && !data.consent) {
          violations.push('GDPR: Personal data requires consent')
        }
        break

      case RegulatoryFramework.HIPAA:
        // HIPAA: Healthcare data protection
        if (data.healthcareData && !data.encrypted) {
          violations.push('HIPAA: Healthcare data must be encrypted')
        }
        if (!data.auditLog) {
          requiredActions.push('HIPAA: Audit logging required')
        }
        break

      case RegulatoryFramework.PCI_DSS:
        // PCI-DSS: Payment card data
        if (data.cardholderData && !data.encrypted) {
          violations.push('PCI-DSS: Cardholder data must be encrypted')
        }
        if (data.cardholderData && !data.accessRestricted) {
          violations.push('PCI-DSS: Access to cardholder data must be restricted')
        }
        break

      case RegulatoryFramework.SOX:
        // SOX: Financial data integrity
        if (data.financialData && !data.immutable) {
          warnings.push('SOX: Financial data should be immutable')
        }
        if (!data.auditTrail) {
          requiredActions.push('SOX: Audit trail required')
        }
        break
    }

    return {
      compliant: violations.length === 0,
      violations,
      warnings,
      requiredActions,
    }
  }

  /**
   * Check if region is in EU
   */
  private isEURegion(region: string): boolean {
    const euRegions = [
      'eu-west-1',
      'eu-west-2',
      'eu-west-3',
      'eu-central-1',
      'eu-north-1',
      'eu-south-1',
    ]
    return euRegions.some((eu) => region.toLowerCase().includes(eu))
  }

  /**
   * Enforce retention policy
   */
  async enforceRetentionPolicy(
    context: Context,
    data: any,
    region: string
  ): Promise<void> {
    const db = getDb()

    // Get retention policy for data type
    const rulesResult = await db.query(
      `SELECT retention_policy FROM data_residency_rules 
       WHERE data_type = $1`,
      [data.type || 'default']
    )

    if (rulesResult.rows.length > 0) {
      const policy = rulesResult.rows[0].retention_policy
      const retentionDays = policy?.retentionDays || 365

      // Check if data exceeds retention period
      const dataAge = Date.now() - new Date(data.createdAt).getTime()
      const ageInDays = dataAge / (1000 * 60 * 60 * 24)

      if (ageInDays > retentionDays) {
        logger.info('Data exceeds retention policy', {
          dataId: data.id,
          ageInDays,
          retentionDays,
        })
        // In production, this would trigger data deletion
      }
    }
  }

  /**
   * Audit data access
   */
  async auditDataAccess(
    context: Context,
    data: any,
    user: any,
    operation: string
  ): Promise<void> {
    const db = getDb()

    await db.query(
      `INSERT INTO compliance_audit_logs (
        data_id, user_id, operation, region, framework,
        compliant, timestamp
      ) VALUES ($1, $2, $3, $4, $5, $6, $7)`,
      [
        data.id,
        user.id,
        operation,
        data.region,
        data.framework || 'GENERAL',
        true,
        new Date(),
      ]
    )

    logger.info('Data access audited', {
      dataId: data.id,
      userId: user.id,
      operation,
    })
  }
}

export const complianceEnforcer = new ComplianceEnforcer()

