################################################################################
# Module: rds
# Main — AWS RDS PostgreSQL 14
#
# - Multi-AZ for HA
# - Encryption at rest (AWS-managed KMS key)
# - No public access — VPC-internal only
# - Storage autoscaling up to max_allocated_storage
# - Enhanced monitoring and Performance Insights enabled by default
# - Access restricted to explicitly allowed security groups (app only)
################################################################################

terraform {
  required_version = ">= 1.6.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 5.40.0"
    }
  }
}

locals {
  identifier = "${var.project}-${var.environment}"

  common_tags = {
    environment = var.environment
    project     = var.project
    managed_by  = "terraform"
  }
}

################################################################################
# Security Group — only the app SGs may connect on 5432
################################################################################

resource "aws_security_group" "rds" {
  name        = "${local.identifier}-rds-sg"
  description = "Controls inbound access to RDS PostgreSQL — allow only app SG on 5432"
  vpc_id      = var.vpc_id

  # No ingress rules defined here — added dynamically below to avoid circular deps.
  egress {
    description = "All outbound (RDS initiates no outbound connections; this satisfies AWS requirement)"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = merge(local.common_tags, {
    Name = "${local.identifier}-rds-sg"
  })
}

resource "aws_security_group_rule" "rds_ingress_from_app" {
  for_each = toset(var.allowed_security_group_ids)

  type                     = "ingress"
  description              = "PostgreSQL from app security group"
  from_port                = 5432
  to_port                  = 5432
  protocol                 = "tcp"
  source_security_group_id = each.value
  security_group_id        = aws_security_group.rds.id
}

################################################################################
# DB Subnet Group — must cover at least 2 AZs for Multi-AZ
################################################################################

resource "aws_db_subnet_group" "main" {
  name        = "${local.identifier}-db-subnet-group"
  description = "Private subnets for AgentIdP RDS instance"
  subnet_ids  = var.subnet_ids

  tags = merge(local.common_tags, {
    Name = "${local.identifier}-db-subnet-group"
  })
}

################################################################################
# DB Parameter Group — enforce SSL connections
################################################################################

resource "aws_db_parameter_group" "main" {
  name        = "${local.identifier}-pg14-params"
  family      = var.parameter_group_family
  description = "AgentIdP custom parameter group — enforces SSL"

  parameter {
    name         = "rds.force_ssl"
    value        = "1"
    apply_method = "immediate"
  }

  parameter {
    name         = "log_connections"
    value        = "1"
    apply_method = "immediate"
  }

  parameter {
    name         = "log_disconnections"
    value        = "1"
    apply_method = "immediate"
  }

  parameter {
    name         = "log_min_duration_statement"
    value        = "1000"
    apply_method = "immediate"
  }

  tags = local.common_tags
}

################################################################################
# RDS Instance
################################################################################

resource "aws_db_instance" "main" {
  identifier = local.identifier

  # Engine
  engine         = "postgres"
  engine_version = "14"
  instance_class = var.instance_class

  # Storage
  storage_type          = "gp3"
  allocated_storage     = var.allocated_storage
  max_allocated_storage = var.max_allocated_storage
  storage_encrypted     = true
  # kms_key_id is omitted — defaults to the AWS-managed RDS KMS key.
  # For customer-managed key, set kms_key_id to your CMK ARN.

  # Database
  db_name  = var.db_name
  username = var.db_username
  password = var.db_password

  # Network — VPC-internal only, no public endpoint
  db_subnet_group_name   = aws_db_subnet_group.main.name
  vpc_security_group_ids = [aws_security_group.rds.id]
  publicly_accessible    = false
  multi_az               = var.multi_az
  port                   = 5432

  # Parameter group
  parameter_group_name = aws_db_parameter_group.main.name

  # Backups
  backup_retention_period   = var.backup_retention_days
  backup_window             = var.backup_window
  delete_automated_backups  = false
  copy_tags_to_snapshot     = true
  skip_final_snapshot       = var.skip_final_snapshot
  final_snapshot_identifier = var.skip_final_snapshot ? null : "${local.identifier}-final-snapshot"

  # Maintenance
  maintenance_window         = var.maintenance_window
  auto_minor_version_upgrade = true
  apply_immediately          = false

  # Observability
  enabled_cloudwatch_logs_exports       = ["postgresql", "upgrade"]
  performance_insights_enabled          = var.performance_insights_enabled
  performance_insights_retention_period = var.performance_insights_enabled ? var.performance_insights_retention_period : null
  monitoring_interval                   = var.monitoring_interval
  monitoring_role_arn                   = var.monitoring_interval > 0 ? var.monitoring_role_arn : null

  # Protection
  deletion_protection = var.deletion_protection

  tags = merge(local.common_tags, {
    Name = local.identifier
  })
}
