#!/usr/bin/env bash
# =============================================================================
#  Dextorm — AWS cost & inventory audit   (READ-ONLY)
# -----------------------------------------------------------------------------
#  Inventories your AWS resources by type/size/state, pulls last-30-day cost by
#  service (Cost Explorer), and flags common waste (stopped EC2 still billing
#  EBS, unattached volumes, unassociated Elastic IPs, old snapshots).
#  Exports CSVs you can share with Dextorm for an exact optimization estimate.
#
#  This script ONLY READS. It never creates, modifies or deletes anything.
#
#  Requirements:  awscli v2 + jq.   Credentials with read access (e.g. the
#                 AWS managed policy "ReadOnlyAccess" or "ViewOnlyAccess").
#  Usage:         aws configure         # or export AWS_PROFILE / SSO login
#                 ./dextorm-aws-audit.sh [region ...]
#  Output:        ./dextorm-audit/<timestamp>/*.csv
#
#  (c) 2026 Dextorm · team@dextorm.com
# =============================================================================
set -euo pipefail

command -v aws >/dev/null || { echo "[!] AWS CLI not found. Install awscli v2."; exit 1; }
command -v jq  >/dev/null || { echo "[!] jq not found. Install jq."; exit 1; }
aws sts get-caller-identity >/dev/null 2>&1 || { echo "[!] Not authenticated. Run 'aws configure' or SSO login (read access is enough)."; exit 1; }

TS="$(date +%Y%m%d-%H%M%S)"
OUT="./dextorm-audit/$TS"
mkdir -p "$OUT"
echo "[+] Writing reports to $OUT  (READ-ONLY run)"

# Regions: args, or all enabled regions
if [ "$#" -gt 0 ]; then REGIONS="$*"; else
  REGIONS="$(aws ec2 describe-regions --query 'Regions[].RegionName' --output text)"
fi

INV="$OUT/inventory.csv"; WASTE="$OUT/waste-findings.csv"
echo "region,type,id,size_or_type,state" > "$INV"
echo "region,severity,type,id,finding,detail" > "$WASTE"

for R in $REGIONS; do
  echo "[*] Region: $R"

  # --- EC2 instances ---
  aws ec2 describe-instances --region "$R" \
    --query 'Reservations[].Instances[].[InstanceId,InstanceType,State.Name]' --output text 2>/dev/null | \
  while read -r ID TYPE STATE; do
    [ -z "${ID:-}" ] && continue
    echo "$R,EC2,$ID,$TYPE,$STATE" >> "$INV"
    if [ "$STATE" = "stopped" ]; then
      echo "$R,medium,EC2,$ID,Stopped instance still bills attached EBS,$TYPE" >> "$WASTE"
    fi
  done

  # --- Unattached EBS volumes ---
  aws ec2 describe-volumes --region "$R" --filters Name=status,Values=available \
    --query 'Volumes[].[VolumeId,Size,VolumeType]' --output text 2>/dev/null | \
  while read -r VID SIZE VT; do
    [ -z "${VID:-}" ] && continue
    echo "$R,EBS,$VID,${SIZE}GB/$VT,available" >> "$INV"
    echo "$R,high,EBS,$VID,Unattached volume — billed but unused,${SIZE}GB $VT" >> "$WASTE"
  done

  # --- Unassociated Elastic IPs ---
  aws ec2 describe-addresses --region "$R" \
    --query 'Addresses[?AssociationId==null].[AllocationId,PublicIp]' --output text 2>/dev/null | \
  while read -r AID IP; do
    [ -z "${AID:-}" ] && continue
    echo "$R,EIP,$AID,$IP,unassociated" >> "$INV"
    echo "$R,medium,EIP,$AID,Elastic IP not associated — billed hourly,$IP" >> "$WASTE"
  done

  # --- Old self-owned snapshots (>90d) ---
  CUTOFF="$(date -u -d '90 days ago' +%Y-%m-%d 2>/dev/null || date -u -v-90d +%Y-%m-%d)"
  aws ec2 describe-snapshots --region "$R" --owner-ids self \
    --query "Snapshots[?StartTime<='${CUTOFF}'] | [].[SnapshotId,VolumeSize]" --output text 2>/dev/null | \
  while read -r SID SSIZE; do
    [ -z "${SID:-}" ] && continue
    echo "$R,medium,Snapshot,$SID,Snapshot older than 90 days — review retention,${SSIZE}GB" >> "$WASTE"
  done
done

# --- Cost by service, last 30 days (Cost Explorer is global; us-east-1) ---
START="$(date -u -d '30 days ago' +%Y-%m-%d 2>/dev/null || date -u -v-30d +%Y-%m-%d)"
END="$(date -u +%Y-%m-%d)"
if aws ce get-cost-and-usage --region us-east-1 --time-period Start="$START",End="$END" \
      --granularity MONTHLY --metrics "UnblendedCost" \
      --group-by Type=DIMENSION,Key=SERVICE --output json > "$OUT/_ce.json" 2>/dev/null; then
  echo "service,cost,currency" > "$OUT/cost-by-service.csv"
  jq -r '.ResultsByTime[].Groups[] | [.Keys[0], (.Metrics.UnblendedCost.Amount), (.Metrics.UnblendedCost.Unit)] | @csv' \
     "$OUT/_ce.json" | sort -t, -k2 -nr >> "$OUT/cost-by-service.csv"
  rm -f "$OUT/_ce.json"
  echo "[+] Cost by service exported."
else
  echo "[!] Cost Explorer unavailable (needs ce:GetCostAndUsage + Cost Explorer enabled). Inventory still captured."
fi

echo ""
echo "[+] Done. Reports in $OUT :"
ls -1 "$OUT"
echo ""
echo "Share these CSVs with Dextorm (team@dextorm.com) for an exact,"
echo "line-by-line optimization estimate. Nothing was modified."
