terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
  }
  backend "s3" {
    bucket  = "assessment-model-terraform-state"
    region  = "eu-west-2"
    profile = "DevAdmin"
    key     = "terraform.tfstate"
  }

  required_version = ">= 1.2.0"
}

provider "aws" {
  profile = var.profile
  region  = var.region
}

# Additional provider for resources that need to be in us-east-1, specifically the SSL certificate
provider "aws" {
  alias  = "aws_use1"
  region = "us-east-1"
}

# Assuming the secret is already created and the name is "<stage>/assessment_model/db_credentials"
data "aws_secretsmanager_secret" "db_credentials" {
  name = "${var.stage}/assessment_model/db_credentials"
}

data "aws_secretsmanager_secret_version" "db_credentials" {
  secret_id = data.aws_secretsmanager_secret.db_credentials.id
}

# Default VPC
data "aws_vpc" "default" {
  default = true
}

# For MVP, we allow all inbound traffic to the DB - this will need to be changed later; we'll likely
# need to re-deploy the frontend to AWS so that it's within the same VPC as the DB
resource "aws_security_group" "allow_db" {
  name        = "allow_tls"
  description = "Allow TLS inbound traffic"
  vpc_id      = data.aws_vpc.default.id

  ingress {
    # TLS (change to whatever ports you need)
    from_port   = 5432
    to_port     = 5432
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_db_instance" "default" {
  allocated_storage      = var.allocated_storage
  engine                 = "postgres"
  engine_version         = "14.10"
  instance_class         = var.instance_class
  db_name                = var.database_name
  username               = jsondecode(data.aws_secretsmanager_secret_version.db_credentials.secret_string)["db_assessment_model_username"]
  password               = jsondecode(data.aws_secretsmanager_secret_version.db_credentials.secret_string)["db_assessment_model_password"]
  parameter_group_name   = "default.postgres14"
  skip_final_snapshot    = true
  vpc_security_group_ids = [aws_security_group.allow_db.id]
  lifecycle {
    prevent_destroy = true
  }
  # For the moment, we make the database publically accessible so that we can connect to it from the frontend.
  # We will look to change this in the future but as we are pre-MVP at the time of setting this, we don't
  # have major security demand and don't want to set this up now
  publicly_accessible = true
  # Specify the CA certificate with the default RDS CA certificate
  ca_cert_identifier = "rds-ca-rsa2048-g1"
  # Temporary to enfore immediate change
  apply_immediately = true
}

# Set up the bucket that recieve the csv uploads of epc to be retrofit
module "s3_presignable_bucket" {
  source          = "./modules/s3_presignable_bucket"
  bucketname      = "retrofit-plan-inputs-${var.stage}"
  environment     = var.stage
  allowed_origins = var.allowed_origins
}

module "s3_due_considerations_bucket" {
  source          = "./modules/s3_presignable_bucket"
  bucketname      = "retrofit-due-considerations-${var.stage}"
  environment     = var.stage
  allowed_origins = var.allowed_origins
}

module "s3_eco_spreadseet_bucket" {
  source          = "./modules/s3_presignable_bucket"
  bucketname      = "retrofit-eco-spreadsheet-${var.stage}"
  environment     = var.stage
  allowed_origins = var.allowed_origins
}

module "s3" {
  source          = "./modules/s3"
  bucketname      = "retrofit-datalake-${var.stage}"
  allowed_origins = var.allowed_origins
}

module "model_directory" {
  source          = "./modules/s3"
  bucketname      = "retrofit-model-directory-${var.stage}"
  allowed_origins = var.allowed_origins
}

module "retrofit_sap_predictions" {
  source          = "./modules/s3"
  bucketname      = "retrofit-sap-predictions-${var.stage}"
  allowed_origins = var.allowed_origins
}

module "retrofit_sap_data" {
  source          = "./modules/s3"
  bucketname      = "retrofit-data-${var.stage}"
  allowed_origins = var.allowed_origins
}

module "retrofit_carbon_predictions" {
  source          = "./modules/s3"
  bucketname      = "retrofit-carbon-predictions-${var.stage}"
  allowed_origins = var.allowed_origins
}

module "retrofit_heat_predictions" {
  source          = "./modules/s3"
  bucketname      = "retrofit-heat-predictions-${var.stage}"
  allowed_origins = var.allowed_origins
}


# Set up the route53 record for the API
module "route53" {
  source         = "./modules/route53"
  domain_name    = var.domain_name
  api_url_prefix = var.api_url_prefix
  providers = {
    aws.aws_use1 = aws.aws_use1
  }
}

# Create an ECR repository for storage of the lambda's docker images
module "ecr" {
  ecr_name = "fastapi-repository-${var.stage}"
  source   = "./modules/ecr"
}

module "lambda_sap_prediction_ecr" {
  ecr_name = "lambda-sap-prediction-${var.stage}"
  source   = "./modules/ecr"
}

module "due_considerations_ecr" {
  ecr_name = "due-considerations-${var.stage}"
  source   = "./modules/ecr"
}

module "eco_spreadsheet_ecr" {
  ecr_name = "eco-spreadsheet-${var.stage}"
  source   = "./modules/ecr"
}

module "lambda_carbon_prediction_ecr" {
  ecr_name = "lambda-carbon-prediction-${var.stage}"
  source   = "./modules/ecr"
}

module "lambda_heat_prediction_ecr" {
  ecr_name = "lambda-heat-prediction-${var.stage}"
  source   = "./modules/ecr"
}

##############################################
# CDN - Cloudfront
##############################################
module "cloudfront_distribution" {
  source             = "./modules/cloudfront"
  bucket_name        = module.s3.bucket_name
  bucket_id          = module.s3.bucket_id
  bucket_arn         = module.s3.bucket_arn
  bucket_domain_name = module.s3.bucket_domain_name
  stage              = var.stage
}