#!/bin/bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
. "$SCRIPT_DIR/common.sh"

usage() {
  cat >&2 <<'USAGE'
Usage:
  aws_plan.sh

Prints the read-only canonical TiDB X AWS approval block.
USAGE
}

case "${1:-}" in
  "") ;;
  --help) usage; exit 0 ;;
  *) usage; exit 1 ;;
esac

need_cmd aws
require_env \
  PROFILE EXPECTED_AWS_ACCOUNT_ID REGION AZ VPC_ID SUBNET_ID AMI KEY_NAME \
  RUN_DIR STATE_FILE RUN_LOG_DIR \
  CLUSTER_NAME PROVISION_TOKEN OWNER CREATED_BY CLEANUP_OWNER EXPIRES_AT COST_CEILING_USD \
  ESTIMATED_BURN_RATE_USD_PER_HOUR ESTIMATED_BURN_RATE_USD_PER_DAY ESTIMATED_TOTAL_COST_USD \
  CONTROL_HOST_ID CONTROL_TYPE CONTROL_SG \
  PD_COUNT PD_TYPE PD_ROOT_GB TIDB_COUNT TIDB_TYPE TIDB_ROOT_GB \
  TIKV_COUNT TIKV_TYPE TIKV_ROOT_GB MONITOR_COUNT MONITOR_TYPE MONITOR_ROOT_GB \
  S3_BUCKET S3_PREFIX TIKV_IAM_ROLE TIKV_IAM_POLICY OPERATOR_CIDR ASSOCIATE_PUBLIC_IP \
  SSH_PORT TIDB_PORT GRAFANA_PORT PROMETHEUS_PORT \
  S3_NETWORK_MODE S3_NETWORK_RESOURCE_ID S3_NETWORK_POLICY_APPROVED NETWORK_EXTRAS

PRESSURE_COUNT="${PRESSURE_COUNT:-0}"
[ "${#PROVISION_TOKEN}" -le 48 ] || die "PROVISION_TOKEN must be at most 48 characters"
case "$PROVISION_TOKEN" in
  ""|*[!A-Za-z0-9._-]*) die "PROVISION_TOKEN must contain only letters, digits, dot, underscore, or hyphen" ;;
esac
case "$S3_PREFIX" in
  ""|/*|*/|*//*|*[!A-Za-z0-9._/-]*) die "S3_PREFIX must be a safe non-empty relative path without trailing slash" ;;
esac
for name in CLUSTER_NAME TIKV_IAM_ROLE TIKV_IAM_POLICY OWNER CREATED_BY CLEANUP_OWNER; do require_safe_name "$name"; done
case "$S3_BUCKET" in ""|*[!a-z0-9.-]*) die "S3_BUCKET contains unsupported characters" ;; esac
case "$EXPIRES_AT" in ""|*[!0-9TtZz:+._-]*) die "EXPIRES_AT contains unsupported characters" ;; esac
case "$RUN_DIR" in /*) ;; *) die "RUN_DIR must be an absolute path" ;; esac
case "$STATE_FILE" in "$RUN_DIR"/*) ;; *) die "STATE_FILE must be inside RUN_DIR" ;; esac
case "$RUN_LOG_DIR" in "$RUN_DIR"/*) ;; *) die "RUN_LOG_DIR must be inside RUN_DIR" ;; esac
[ ! -e "$STATE_FILE" ] || die "state file already exists; use cleanup/recovery instead of approving a new provision"
[ "$S3_NETWORK_POLICY_APPROVED" = "1" ] || \
  die "S3_NETWORK_POLICY_APPROVED must be 1 after reviewing the selected route and endpoint/network policy"
for name in PD_COUNT PD_ROOT_GB TIDB_COUNT TIDB_ROOT_GB TIKV_COUNT TIKV_ROOT_GB MONITOR_COUNT MONITOR_ROOT_GB; do
  require_positive_int "$name"
done
require_nonnegative_int PRESSURE_COUNT
for name in COST_CEILING_USD ESTIMATED_BURN_RATE_USD_PER_HOUR ESTIMATED_BURN_RATE_USD_PER_DAY ESTIMATED_TOTAL_COST_USD; do
  require_nonnegative_decimal "$name"
done
awk -v estimate="$ESTIMATED_TOTAL_COST_USD" -v ceiling="$COST_CEILING_USD" \
  'BEGIN { exit !(estimate <= ceiling) }' || \
  die "estimated total cost exceeds the approved ceiling"
for name in SSH_PORT TIDB_PORT GRAFANA_PORT PROMETHEUS_PORT; do
  require_port "$name"
done

account_id="$(aws --profile "$PROFILE" sts get-caller-identity --query Account --output text)"
configured_region="$(aws configure get region --profile "$PROFILE" || true)"
pressure_count="${PRESSURE_COUNT:-0}"
pressure_type="${PRESSURE_TYPE:-none}"
pressure_root_gb="${PRESSURE_ROOT_GB:-none}"
if [ "$pressure_count" -gt 0 ]; then
  require_env PRESSURE_TYPE PRESSURE_ROOT_GB
  require_positive_int PRESSURE_ROOT_GB
fi
public_ip="$ASSOCIATE_PUBLIC_IP"
approval_sha256="$(aws_approval_sha256)"

if [ "$account_id" != "$EXPECTED_AWS_ACCOUNT_ID" ]; then
  account_check="fail expected=$EXPECTED_AWS_ACCOUNT_ID"
else
  account_check="pass"
fi

network_route_table="not-checked"
ami_root_device="not-checked"
if [ "$account_check" = "pass" ]; then
  ami_root_device="$(resolve_ami_root_device "$PROFILE" "$REGION" "$AMI")"
  validate_subnet_az "$PROFILE" "$REGION" "$SUBNET_ID" "$AZ"
  network_route_table="$(validate_s3_network_path \
    "$PROFILE" "$REGION" "$VPC_ID" "$SUBNET_ID" \
    "$S3_NETWORK_MODE" "$ASSOCIATE_PUBLIC_IP" "$S3_NETWORK_RESOURCE_ID")"
fi

cat <<EOF
AWS account: $account_id (expected-account-id check: $account_check)
Configured region: ${configured_region:-unset}
Target region/AZ: $REGION/$AZ
Cluster: $CLUSTER_NAME
Provision token: $PROVISION_TOKEN
Owner: $OWNER
Created by: $CREATED_BY
Cleanup owner: $CLEANUP_OWNER
TTL/ExpiresAt: $EXPIRES_AT
Approved cost ceiling: $COST_CEILING_USD USD
Estimated burn: $ESTIMATED_BURN_RATE_USD_PER_HOUR hourly, $ESTIMATED_BURN_RATE_USD_PER_DAY daily
Estimated total cost: $ESTIMATED_TOTAL_COST_USD USD
Resources:
  control=${CONTROL_HOST_ID}/${CONTROL_TYPE}, pd=${PD_COUNT}x${PD_TYPE}, tidb=${TIDB_COUNT}x${TIDB_TYPE},
  tikv=${TIKV_COUNT}x${TIKV_TYPE}, monitor=${MONITOR_COUNT}x${MONITOR_TYPE}, pressure=${pressure_count}x${pressure_type}
Storage:
  pd=${PD_COUNT}x${PD_ROOT_GB}GiB, tidb=${TIDB_COUNT}x${TIDB_ROOT_GB}GiB,
  tikv=${TIKV_COUNT}x${TIKV_ROOT_GB}GiB, monitor=${MONITOR_COUNT}x${MONITOR_ROOT_GB}GiB,
  pressure=${pressure_count}x${pressure_root_gb}GiB
S3/IAM:
  bucket=$S3_BUCKET, prefix=$S3_PREFIX, TiKV role/profile=$TIKV_IAM_ROLE,
  policy=$TIKV_IAM_POLICY, credentials=instance-profile
Network:
  VPC/subnet=$VPC_ID/$SUBNET_ID, public IP=$public_ip, operator CIDR=$OPERATOR_CIDR
  control SG=$CONTROL_SG, AMI=$AMI (x86_64 EBS root=$ami_root_device), key pair=$KEY_NAME
  ingress ports: ssh=$SSH_PORT, sql=$TIDB_PORT, grafana=$GRAFANA_PORT, prometheus=$PROMETHEUS_PORT
  S3 path=$S3_NETWORK_MODE/$S3_NETWORK_RESOURCE_ID, route table=$network_route_table,
  network policy approved=$S3_NETWORK_POLICY_APPROVED, extras=$NETWORK_EXTRAS
Cleanup:
  run directory=$RUN_DIR, state file=$STATE_FILE, logs=$RUN_LOG_DIR
  pause=scripts/pause_cluster.sh --apply
  destroy=scripts/cleanup_aws.sh --apply after exact inventory review
Approval SHA256: $approval_sha256
EOF

[ "$account_check" = "pass" ] || die "AWS account does not match EXPECTED_AWS_ACCOUNT_ID"

log "Read-only approval block complete; export APPROVED_PLAN_SHA256=$approval_sha256 only after approval"
