resource "aws_ecs_cluster" "this" {
  name = var.name

  setting {
    name  = "containerInsights"
    value = "enabled"
  }
}

resource "aws_cloudwatch_log_group" "this" {
  name              = "/ecs/${var.name}"
  retention_in_days = var.log_retention_days
}

resource "aws_security_group" "task" {
  name        = "${var.name}-task"
  description = "ECS task ENI for ${var.name}"
  vpc_id      = var.vpc_id
}

resource "aws_vpc_security_group_ingress_rule" "task_from_alb" {
  security_group_id            = aws_security_group.task.id
  referenced_security_group_id = aws_security_group.alb.id
  from_port                    = var.container_port
  to_port                      = var.container_port
  ip_protocol                  = "tcp"
  description                  = "Container port from ALB"
}

resource "aws_vpc_security_group_egress_rule" "task_all_v4" {
  security_group_id = aws_security_group.task.id
  cidr_ipv4         = "0.0.0.0/0"
  ip_protocol       = "-1"
}

resource "aws_vpc_security_group_egress_rule" "task_all_v6" {
  security_group_id = aws_security_group.task.id
  cidr_ipv6         = "::/0"
  ip_protocol       = "-1"
}

locals {
  container_name = var.name

  # ALLOWED_MCP_CLIENTS is appended only when non-empty; an empty value would
  # override the upstream default (claude-desktop, test-mcp-client) and lock
  # everyone out.
  container_env = concat(
    [
      { name = "ENABLE_LOGIN_FLOW", value = "true" },
      { name = "ENABLE_SEMANTIC_SEARCH", value = "true" },
      { name = "ENABLE_BACKGROUND_OPERATIONS", value = "true" },
      # Explicit collection name; otherwise upstream auto-derives one from the
      # task hostname, which churns the collection on every rolling deploy.
      { name = "QDRANT_COLLECTION", value = var.qdrant_collection },
      { name = "TOKEN_STORAGE_DB", value = "/app/data/tokens.db" },
      { name = "NEXTCLOUD_MCP_SERVER_URL", value = "https://${local.fqdn}" },
      { name = "OIDC_DISCOVERY_URL", value = "${var.nextcloud_url}/.well-known/openid-configuration" },
      { name = "AWS_REGION", value = data.aws_region.current.region },
      { name = "BEDROCK_EMBEDDING_MODEL", value = var.bedrock_embedding_model },
      { name = "VECTOR_SYNC_SCAN_INTERVAL", value = tostring(var.vector_sync_scan_interval) },
      { name = "VECTOR_SYNC_PROCESSOR_WORKERS", value = tostring(var.vector_sync_processor_workers) },
    ],
    var.use_external_qdrant ? [] : [
      { name = "QDRANT_URL", value = "http://qdrant.${aws_service_discovery_private_dns_namespace.this.name}:${local.qdrant_port}" },
    ],
    length(var.allowed_mcp_clients) > 0 ? [
      { name = "ALLOWED_MCP_CLIENTS", value = join(",", var.allowed_mcp_clients) },
    ] : [],
    var.allowed_mgmt_client != "" ? [
      { name = "ALLOWED_MGMT_CLIENT", value = var.allowed_mgmt_client },
    ] : [],
  )

  container_secrets = concat(
    [
      { name = "NEXTCLOUD_HOST", valueFrom = "${var.secret_arn}:host::" },
      { name = "NEXTCLOUD_OIDC_CLIENT_ID", valueFrom = "${var.secret_arn}:client_id::" },
      { name = "NEXTCLOUD_OIDC_CLIENT_SECRET", valueFrom = "${var.secret_arn}:client_secret::" },
      { name = "TOKEN_ENCRYPTION_KEY", valueFrom = "${var.secret_arn}:token_encryption_key::" },
      { name = "WEBHOOK_SECRET", valueFrom = "${var.secret_arn}:webhook_secret::" },
    ],
    var.use_external_qdrant ? [
      { name = "QDRANT_URL", valueFrom = "${var.secret_arn}:qdrant_url::" },
      { name = "QDRANT_API_KEY", valueFrom = "${var.secret_arn}:qdrant_api_key::" },
    ] : [],
  )
}

resource "aws_ecs_task_definition" "this" {
  family                   = var.name
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = tostring(var.cpu)
  memory                   = tostring(var.memory)
  execution_role_arn       = aws_iam_role.execution.arn
  task_role_arn            = aws_iam_role.task.arn

  volume {
    name = "data"
    efs_volume_configuration {
      file_system_id     = aws_efs_file_system.this.id
      transit_encryption = "ENABLED"
      authorization_config {
        access_point_id = aws_efs_access_point.data.id
        iam             = "ENABLED"
      }
    }
  }

  volume {
    name = "oauth"
    efs_volume_configuration {
      file_system_id     = aws_efs_file_system.this.id
      transit_encryption = "ENABLED"
      authorization_config {
        access_point_id = aws_efs_access_point.oauth.id
        iam             = "ENABLED"
      }
    }
  }

  container_definitions = jsonencode([
    {
      name      = local.container_name
      image     = "${var.image}:${var.image_tag}"
      essential = true

      command = [
        "--transport", "streamable-http",
        "--oauth",
        "--port", tostring(var.container_port),
      ]

      portMappings = [
        {
          containerPort = var.container_port
          protocol      = "tcp"
        },
      ]

      environment = local.container_env
      secrets     = local.container_secrets

      mountPoints = [
        { sourceVolume = "data", containerPath = "/app/data", readOnly = false },
        { sourceVolume = "oauth", containerPath = "/app/.oauth", readOnly = false },
      ]

      healthCheck = {
        command     = ["CMD-SHELL", "curl -fsS http://localhost:${var.container_port}/health/live || exit 1"]
        interval    = 30
        timeout     = 5
        retries     = 3
        startPeriod = 60
      }

      logConfiguration = {
        logDriver = "awslogs"
        options = {
          awslogs-group         = aws_cloudwatch_log_group.this.name
          awslogs-region        = data.aws_region.current.region
          awslogs-stream-prefix = "ecs"
        }
      }
    },
  ])
}

resource "aws_ecs_service" "this" {
  name            = var.name
  cluster         = aws_ecs_cluster.this.id
  task_definition = aws_ecs_task_definition.this.arn
  desired_count   = 1
  launch_type     = "FARGATE"

  deployment_minimum_healthy_percent = 100
  deployment_maximum_percent         = 200
  availability_zone_rebalancing      = "ENABLED"

  enable_execute_command = true

  network_configuration {
    subnets          = var.public_subnet_ids
    security_groups  = [aws_security_group.task.id]
    assign_public_ip = true
  }

  load_balancer {
    target_group_arn = aws_lb_target_group.this.arn
    container_name   = local.container_name
    container_port   = var.container_port
  }

  deployment_circuit_breaker {
    enable   = true
    rollback = true
  }

  # The listener must exist before the service registers targets.
  depends_on = [
    aws_lb_listener.https,
    aws_efs_mount_target.this,
  ]
}
