modules/ISC.EntroAws.psm1

#Requires -Version 7
Set-StrictMode -Version Latest

$script:EntroAwsAccountId = '937217723901'

function Get-EntroAwsReadPolicyDocument {
    param([Parameter(Mandatory)][string]$TemplatePath)

    $tpl = Get-Content -LiteralPath $TemplatePath -Raw | ConvertFrom-Json
    $statements = @($tpl.Resources.EntroRole.Properties.Policies[0].PolicyDocument.Statement)
    $actions = @($statements[0].Action)
    if ($actions.Count -eq 0) { throw "No actions found in Entro template: $TemplatePath" }
    return (@{
        Version   = '2012-10-17'
        Statement = @(@{ Effect = 'Allow'; Action = $actions; Resource = '*' })
    } | ConvertTo-Json -Depth 10 -Compress)
}

function Get-EntroAwsTrustPolicyDocument {
    param(
        [Parameter(Mandatory)][string]$ExternalId,
        [string]$EntroAccountId = $script:EntroAwsAccountId
    )

    $trustRoleArn = "arn:aws:iam::${EntroAccountId}:role/EntroTrustRole-${ExternalId}"
    $userArn = "arn:aws:iam::${EntroAccountId}:user/liminal-saas-assume-role"
    return (@{
        Version   = '2012-10-17'
        Statement = @(
            @{
                Effect    = 'Allow'
                Principal = @{ AWS = $userArn }
                Action    = 'sts:AssumeRole'
                Condition = @{ StringEquals = @{ 'sts:ExternalId' = $ExternalId } }
            }
            @{
                Effect    = 'Allow'
                Principal = @{ AWS = $trustRoleArn }
                Action    = 'sts:AssumeRole'
                Condition = @{ StringEquals = @{ 'sts:ExternalId' = $ExternalId } }
            }
        )
    } | ConvertTo-Json -Depth 10 -Compress)
}

function Invoke-EntroAwsAssumeRoleSetup {
    param(
        [Parameter(Mandatory)][string]$EntroExternalId,
        [Parameter(Mandatory)][string]$RoleName,
        [Parameter(Mandatory)][string]$TemplatePath,
        [Parameter(Mandatory)][string]$WorkDirectory
    )

    if (-not (Test-Path -LiteralPath $WorkDirectory)) {
        New-Item -ItemType Directory -Path $WorkDirectory -Force | Out-Null
    }
    $trustPath = Join-Path $WorkDirectory 'entro-trust-policy.json'
    $readPath = Join-Path $WorkDirectory 'entro-read-policy.json'
    Set-Content -LiteralPath $trustPath -Value (Get-EntroAwsTrustPolicyDocument -ExternalId $EntroExternalId) -Encoding utf8
    Set-Content -LiteralPath $readPath -Value (Get-EntroAwsReadPolicyDocument -TemplatePath $TemplatePath) -Encoding utf8

    $policyName = 'EntroReadOnlyAccess'
    $policyArn = aws iam create-policy --policy-name $policyName --policy-document "file://$readPath" --query Policy.Arn --output text 2>$null
    if ($LASTEXITCODE -ne 0) {
        $policyArn = aws iam list-policies --scope Local --query "Policies[?PolicyName=='$policyName'].Arn | [0]" --output text
        if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($policyArn) -or $policyArn -eq 'None') {
            throw 'Failed to create or locate EntroReadOnlyAccess policy.'
        }
    }

    aws iam create-role --role-name $RoleName --assume-role-policy-document "file://$trustPath" | Out-Null
    if ($LASTEXITCODE -ne 0) { throw "Failed to create IAM role $RoleName" }

    aws iam attach-role-policy --role-name $RoleName --policy-arn $policyArn | Out-Null
    if ($LASTEXITCODE -ne 0) { throw "Failed to attach policy to role $RoleName" }

    $roleArn = (aws iam get-role --role-name $RoleName --query Role.Arn --output text).Trim()
    if ($roleArn -match '^\{') {
        $parsed = $roleArn | ConvertFrom-Json
        $roleArn = [string]$parsed.Role.Arn
    }
    Write-Ok "Entro role ready: $roleArn"
    return $roleArn
}

function Invoke-EntroAwsCloudFormationDeploy {
    param(
        [Parameter(Mandatory)][string]$TemplatePath,
        [Parameter(Mandatory)][string]$StackName,
        [Parameter(Mandatory)][string]$ExternalId,
        [string]$Environment = 'Entro',
        [string]$Region = 'us-east-1'
    )

    $timestamp = [DateTimeOffset]::UtcNow.ToUnixTimeSeconds().ToString()
    aws cloudformation deploy `
        --template-file $TemplatePath `
        --stack-name $StackName `
        --parameter-overrides "ExternalId=$ExternalId" "Environment=$Environment" "Timestamp=$timestamp" `
        --capabilities CAPABILITY_NAMED_IAM `
        --region $Region | Out-Null
    if ($LASTEXITCODE -ne 0) { throw "CloudFormation deploy failed for stack $StackName" }
    Write-Ok "CloudFormation stack $StackName deployed"
}

Export-ModuleMember -Function @(
    'Get-EntroAwsTrustPolicyDocument'
    'Get-EntroAwsReadPolicyDocument'
    'Invoke-EntroAwsAssumeRoleSetup'
    'Invoke-EntroAwsCloudFormationDeploy'
)