# Fractary Cloud Storage - AWS S3
#
# This Terraform configuration creates an S3 bucket for Fractary Core
# file storage (docs and logs archival).
#
# Generated by: fractary-core config cloud-init --provider s3
#
# Usage:
#   cd infra/terraform
#   terraform init
#   terraform plan
#   terraform apply

terraform {
  required_version = ">= 1.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

# --- S3 Bucket ---

resource "aws_s3_bucket" "fractary" {
  bucket = var.bucket_name

  tags = {
    Name        = var.bucket_name
    ManagedBy   = "fractary-core"
    Project     = var.project_name
    Environment = "dev"
  }
}

# Enable versioning for data protection
resource "aws_s3_bucket_versioning" "fractary" {
  bucket = aws_s3_bucket.fractary.id

  versioning_configuration {
    status = "Enabled"
  }
}

# Server-side encryption (AES-256)
resource "aws_s3_bucket_server_side_encryption_configuration" "fractary" {
  bucket = aws_s3_bucket.fractary.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
    bucket_key_enabled = true
  }
}

# Block all public access
resource "aws_s3_bucket_public_access_block" "fractary" {
  bucket = aws_s3_bucket.fractary.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# Lifecycle rules for cost optimization
resource "aws_s3_bucket_lifecycle_configuration" "fractary" {
  bucket = aws_s3_bucket.fractary.id

  # Transition archived logs to Infrequent Access after 90 days
  rule {
    id     = "archive-logs-transition"
    status = "Enabled"

    filter {
      prefix = "logs/_archive/"
    }

    transition {
      days          = 90
      storage_class = "STANDARD_IA"
    }

    transition {
      days          = 365
      storage_class = "GLACIER"
    }
  }

  # Transition archived docs to Infrequent Access after 90 days
  rule {
    id     = "archive-docs-transition"
    status = "Enabled"

    filter {
      prefix = "docs/_archive/"
    }

    transition {
      days          = 90
      storage_class = "STANDARD_IA"
    }

    transition {
      days          = 365
      storage_class = "GLACIER"
    }
  }

  # Clean up incomplete multipart uploads
  rule {
    id     = "cleanup-multipart"
    status = "Enabled"

    filter {}

    abort_incomplete_multipart_upload {
      days_after_initiation = 7
    }
  }
}

# --- IAM Policy ---

# IAM policy document scoped to Fractary prefixes only
data "aws_iam_policy_document" "fractary_access" {
  statement {
    sid    = "FractaryListBucket"
    effect = "Allow"

    actions = [
      "s3:ListBucket",
    ]

    resources = [
      aws_s3_bucket.fractary.arn,
    ]

    condition {
      test     = "StringLike"
      variable = "s3:prefix"
      values = [
        "logs/*",
        "docs/*",
      ]
    }
  }

  statement {
    sid    = "FractaryObjectAccess"
    effect = "Allow"

    actions = [
      "s3:GetObject",
      "s3:PutObject",
      "s3:DeleteObject",
    ]

    resources = [
      "${aws_s3_bucket.fractary.arn}/logs/*",
      "${aws_s3_bucket.fractary.arn}/docs/*",
    ]
  }
}

resource "aws_iam_policy" "fractary_access" {
  name        = "fractary-${var.project_name}-storage-access"
  description = "Scoped access to Fractary storage bucket for ${var.project_name}"
  policy      = data.aws_iam_policy_document.fractary_access.json

  tags = {
    ManagedBy = "fractary-core"
    Project   = var.project_name
  }
}

# --- Outputs ---

output "bucket_name" {
  description = "The name of the Fractary S3 bucket"
  value       = aws_s3_bucket.fractary.bucket
}

output "bucket_arn" {
  description = "The ARN of the Fractary S3 bucket"
  value       = aws_s3_bucket.fractary.arn
}

output "bucket_region" {
  description = "The region of the Fractary S3 bucket"
  value       = aws_s3_bucket.fractary.region
}

output "iam_policy_arn" {
  description = "The ARN of the IAM policy for Fractary bucket access"
  value       = aws_iam_policy.fractary_access.arn
}
