#!/bin/bash

# Exit immediately if a command exits with a non-zero status.
set -e

# Define variables
export AWS_REGION="us-east-1"
export ECR_REPOSITORY_NAME="eks-api-gateway-demo"
export EKS_CLUSTER_NAME="eks-api-gateway-cluster"
export K8S_NAMESPACE="default"
export APP_NAME="eks-api-gateway-demo"

echo "Starting the setup process..."

# 1. Create ECR Repository
echo "Creating ECR repository..."
aws ecr create-repository \
    --repository-name ${ECR_REPOSITORY_NAME} \
    --image-tag-mutability IMMUTABLE \
    --image-scanning-configuration scanOnPush=true \
    --region ${AWS_REGION} || echo "ECR repository already exists."

# 2. Get AWS Account ID and ECR URI
echo "Getting AWS Account ID and ECR URI..."
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export ECR_URI="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPOSITORY_NAME}"

# 3. Build and Push Docker Image
echo "Building and pushing the Docker image to ECR..."
aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com
docker build -t ${APP_NAME} .
docker tag ${APP_NAME}:latest ${ECR_URI}:latest
docker push ${ECR_URI}:latest

echo "Docker image pushed to ECR successfully."

# 4. Create EKS Cluster
echo "Creating EKS cluster... This might take a while."
eksctl create cluster \
    --name ${EKS_CLUSTER_NAME} \
    --region ${AWS_REGION} \
    --nodegroup-name standard-workers \
    --node-type t3.medium \
    --nodes 2 \
    --nodes-min 1 \
    --nodes-max 3 \
    --with-oidc \
    --managed

echo "EKS cluster created successfully."

# 5. Associate IAM OIDC provider
echo "Associating IAM OIDC provider..."
eksctl utils associate-iam-oidc-provider --cluster ${EKS_CLUSTER_NAME} --approve --region ${AWS_REGION}

# 6. Download IAM policy for AWS Load Balancer Controller
echo "Downloading IAM policy for AWS Load Balancer Controller..."
curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.7/docs/install/iam_policy.json

# 7. Create IAM policy
echo "Creating IAM policy..."
aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document file://iam_policy.json || echo "IAM policy already exists."

# 8. Create IAM service account for the AWS Load Balancer Controller
echo "Creating IAM service account for the AWS Load Balancer Controller..."
eksctl create iamserviceaccount \
    --cluster=${EKS_CLUSTER_NAME} \
    --namespace=kube-system \
    --name=aws-load-balancer-controller \
    --attach-policy-arn=arn:aws:iam::${AWS_ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy \
    --override-existing-serviceaccounts \
    --approve \
    --region ${AWS_REGION}

# 9. Add the EKS chart repo for the AWS Load Balancer Controller
echo "Adding EKS chart repo..."
helm repo add eks https://aws.github.io/eks-charts

# 10. Install the AWS Load Balancer Controller using Helm
echo "Installing AWS Load Balancer Controller..."
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
    -n kube-system \
    --set clusterName=${EKS_CLUSTER_NAME} \
    --set serviceAccount.create=false \
    --set serviceAccount.name=aws-load-balancer-controller

echo "AWS Load Balancer Controller installed successfully."

# 11. Update Kubernetes Manifest with ECR Image URI
echo "Updating Kubernetes manifest with ECR image URI..."
sed -i.bak "s|YOUR_ECR_REPOSITORY_URI.*|${ECR_URI}:latest|g" kubernetes-manifests.yaml

# 12. Deploy Application to EKS
echo "Deploying application to EKS..."
kubectl apply -f kubernetes-manifests.yaml

echo "Application deployed to EKS successfully."

# 13. Create Ingress Resource
echo "Creating Ingress resource..."
cat <<EOF > ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ${APP_NAME}-ingress
  namespace: ${K8S_NAMESPACE}
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: ${APP_NAME}-service
                port:
                  number: 80
EOF

kubectl apply -f ingress.yaml

echo "Ingress resource created successfully."

# 14. Get ALB Hostname
echo "Waiting for ALB to be provisioned..."
sleep 60
ALB_HOSTNAME=$(kubectl get ingress ${APP_NAME}-ingress -n ${K8S_NAMESPACE} -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')

while [ -z "$ALB_HOSTNAME" ]; do
    echo "Waiting for ALB hostname..."
    sleep 30
    ALB_HOSTNAME=$(kubectl get ingress ${APP_NAME}-ingress -n ${K8S_NAMESPACE} -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
done

echo "ALB Hostname: ${ALB_HOSTNAME}"

# 15. Create API Gateway
echo "Creating API Gateway..."
API_GATEWAY_NAME="EKS-App-API"
API_ID=$(aws apigateway create-rest-api --name "${API_GATEWAY_NAME}" --query 'id' --output text)
PARENT_ID=$(aws apigateway get-resources --rest-api-id ${API_ID} --query 'items[?path==`/`].id' --output text)

# Create a proxy resource
PROXY_RESOURCE_ID=$(aws apigateway create-resource --rest-api-id ${API_ID} --parent-id ${PARENT_ID} --path-part "{proxy+}" --query 'id' --output text)

# Create a method for the proxy resource
aws apigateway put-method \
    --rest-api-id ${API_ID} \
    --resource-id ${PROXY_RESOURCE_ID} \
    --http-method ANY \
    --authorization-type "NONE"

# Create the integration
aws apigateway put-integration \
    --rest-api-id ${API_ID} \
    --resource-id ${PROXY_RESOURCE_ID} \
    --http-method ANY \
    --type HTTP_PROXY \
    --integration-http-method ANY \
    --uri "http://${ALB_HOSTNAME}/{proxy}" \
    --passthrough-behavior WHEN_NO_MATCH

# Deploy the API
aws apigateway create-deployment --rest-api-id ${API_ID} --stage-name dev

# 16. Output API Gateway URL
API_GATEWAY_URL="https://${API_ID}.execute-api.${AWS_REGION}.amazonaws.com/dev"
echo "API Gateway Invoke URL: ${API_GATEWAY_URL}"

echo "Setup complete!"
