#!/bin/bash
set -e

# Retry helm s3 push with backoff to handle S3 PreconditionFailed 412 race conditions
helm_s3_push_with_retry() {
    local chart_file="$1"
    local repo_name="$2"
    local max_retries=5
    local attempt=1
    local wait_time=5
    while [ $attempt -le $max_retries ]; do
        if helm s3 push "${chart_file}" "${repo_name}" --force 2>&1; then
            return 0
        fi
        echo "helm s3 push failed (attempt ${attempt}/${max_retries}), retrying in ${wait_time}s..."
        sleep $wait_time
        wait_time=$((wait_time * 2))
        attempt=$((attempt + 1))
    done
    echo "ERROR: helm s3 push failed after ${max_retries} attempts"
    return 1
}

# Retry git push with rebase to handle concurrent pipeline race conditions
git_push_with_retry() {
    local branch="${1:-master}"
    local max_retries=5
    local attempt=1
    while [ $attempt -le $max_retries ]; do
        if git push origin "$branch" 2>&1; then
            return 0
        fi
        echo "Push failed (attempt ${attempt}/${max_retries}), rebasing and retrying..."
        git pull --rebase origin "$branch"
        attempt=$((attempt + 1))
    done
    echo "ERROR: Failed to push after ${max_retries} attempts"
    return 1
}
echo "=== Starting deployment of Blue Rewards ==="

# Configuration
SERVICE_NAME="tbi-redtag-bluerewards"
CHART_NAME="tbi-redtag-bluerewards"
NAMESPACE="${DEPLOY_NAMESPACE:-redtagbluerewards}"
ENVIRONMENT="uat"
AWS_REGION="${AWS_REGION:-ca-central-1}"
TBI_ENVIRONMENTS_BRANCH="${TBI_ENVIRONMENTS_BRANCH:-master}"
HELM_S3_BUCKET="${HELM_S3_BUCKET:-tbi-charts}"

if [ -z "${CLUSTER_NAME}" ]; then
    echo "ERROR: CLUSTER_NAME environment variable is not set!"
    exit 1
fi

if [ -z "${AWS_ACCOUNT_ID}" ]; then
    echo "ERROR: AWS_ACCOUNT_ID environment variable is not set!"
    exit 1
fi

if [ -z "${GITHUB_TOKEN}" ]; then
    echo "ERROR: GITHUB_TOKEN environment variable is not set!"
    exit 1
fi

# Clean URL - no inline token (credential helper supplies it at request time)
TBI_ENVIRONMENTS_REPO="https://github.com/redlabelvacations/tbi-environments.git"

# Read image tag from workspace
if [ -f "IMAGE_TAG" ]; then
    CHART_VERSION=$(cat IMAGE_TAG | tr -d '[:space:]')
    echo "Using image tag from build job: ${CHART_VERSION}"
else
    echo "ERROR: IMAGE_TAG file not found!"
    exit 1
fi

echo "Chart Version: ${CHART_VERSION}"
echo "Environment: ${ENVIRONMENT}"
echo "Namespace: ${NAMESPACE}"
echo "Cluster: ${CLUSTER_NAME}"

package_helm_chart() {
    echo ""
    echo "=== Packaging Helm chart ==="
    local chart_path="tbi-devops-environments/${ENVIRONMENT}/${SERVICE_NAME}/charts/${CHART_NAME}"

    if [ ! -d "${chart_path}" ]; then
        echo "ERROR: Chart directory not found: ${chart_path}"
        return 1
    fi

    sed -i.bak "s|version:.*|version: ${CHART_VERSION}|g" ${chart_path}/Chart.yaml
    sed -i.bak "s|appVersion:.*|appVersion: \"${CHART_VERSION}\"|g" ${chart_path}/Chart.yaml
    rm -f ${chart_path}/Chart.yaml.bak

    mkdir -p /tmp/helm-charts
    helm package ${chart_path} -d /tmp/helm-charts
    echo "✓ Chart packaged"
}

push_chart_to_s3_repo() {
    echo ""
    echo "=== Pushing chart to S3 Helm repository ==="
    local chart_file="/tmp/helm-charts/${CHART_NAME}-${CHART_VERSION}.tgz"

    if [ ! -f "${chart_file}" ]; then
        echo "ERROR: Chart file not found: ${chart_file}"
        return 1
    fi

    helm_s3_push_with_retry ${chart_file} tbi-charts
    echo "✓ Chart pushed to S3"
}

clone_tbi_environments() {
    echo ""
    echo "=== Cloning tbi-environments repository ==="
    rm -rf /tmp/tbi-environments
    git -c credential.helper= \
        -c credential.helper='!f() { echo "username=x-access-token"; echo "password=${GITHUB_TOKEN}"; }; f' \
        clone "${TBI_ENVIRONMENTS_REPO}" /tmp/tbi-environments
    # Persist the helper so the later git push also authenticates
    git -C /tmp/tbi-environments config credential.helper '!f() { echo "username=x-access-token"; echo "password=${GITHUB_TOKEN}"; }; f'
    cd /tmp/tbi-environments
    git checkout ${TBI_ENVIRONMENTS_BRANCH}
    echo "✓ tbi-environments cloned"
}

update_requirements() {
    echo ""
    echo "=== Updating requirements.yaml ==="
    local req_file="/tmp/tbi-environments/${ENVIRONMENT}/requirements.yaml"

    if [ ! -f "${req_file}" ]; then
        echo "ERROR: Requirements file not found: ${req_file}"
        return 1
    fi

    sed -i.bak "/name: ${CHART_NAME}/,/version:/ s|version:.*|version: ${CHART_VERSION}|" ${req_file}
    rm -f ${req_file}.bak
    echo "Updated ${CHART_NAME} to version ${CHART_VERSION}"
}

update_values_file() {
    echo ""
    echo "=== Updating values file with image URL ==="
    local values_file="/tmp/tbi-environments/${ENVIRONMENT}/values/${SERVICE_NAME}.yaml"

    if [ ! -f "${values_file}" ]; then
        echo "ERROR: Values file not found: ${values_file}"
        return 1
    fi

    local image_url="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${SERVICE_NAME}:${CHART_VERSION}"

    if grep -q "^image:" "${values_file}"; then
        sed -i.bak "s|^image:.*|image: ${image_url}|" ${values_file}
    else
        sed -i.bak "1 a\\
image: ${image_url}" ${values_file}
    fi
    rm -f ${values_file}.bak
    echo "Updated image to ${image_url}"
}

push_values_update() {
    echo ""
    echo "=== Pushing values file updates ==="
    cd /tmp/tbi-environments

    git config user.name "CircleCI Bot"
    git config user.email "circleci@tbidevelopment.ca"

    git add ${ENVIRONMENT}/values/${SERVICE_NAME}.yaml
    git add ${ENVIRONMENT}/requirements.yaml

    if git diff --cached --quiet; then
        echo "ℹ️  No changes detected - already up to date"
    else
        git commit -m "Update Blue Rewards to ${CHART_VERSION}

Deployed by CircleCI build #${CIRCLE_BUILD_NUM}
Branch: ${CIRCLE_BRANCH}
Service: ${SERVICE_NAME}
Image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${SERVICE_NAME}:${CHART_VERSION}"
        git_push_with_retry "${TBI_ENVIRONMENTS_BRANCH}"
        echo "✓ Values and requirements updated and pushed"
    fi
}

adopt_existing_resources() {
    echo ""
    echo "=== Adopting existing resources for Helm management ==="
    local resources=("secret/tbi-redtag-bluerewards-tls")
    for res in "${resources[@]}"; do
        if kubectl -n ${NAMESPACE} get ${res} &>/dev/null; then
            kubectl -n ${NAMESPACE} annotate ${res} \
                meta.helm.sh/release-name=${SERVICE_NAME} \
                meta.helm.sh/release-namespace=${NAMESPACE} \
                --overwrite
            kubectl -n ${NAMESPACE} label ${res} \
                app.kubernetes.io/managed-by=Helm \
                --overwrite
            echo "✓ Adopted ${res}"
        fi
    done
}

deploy_service() {
    echo ""
    echo "=== Deploying ${SERVICE_NAME} using helm secrets ==="
    cd /tmp/tbi-environments

    adopt_existing_resources

    # Install from the chart object directly. The Helm repo index often
    # does not contain the version that was just pushed.
    helm secrets upgrade --install \
        --namespace ${NAMESPACE} ${SERVICE_NAME} \
        s3://${HELM_S3_BUCKET}/${CHART_NAME}-${CHART_VERSION}.tgz \
        --set cluster="${CLUSTER_NAME}" \
        --create-namespace \
        -f ./${ENVIRONMENT}/common.yaml \
        -f ./${ENVIRONMENT}/secrets.common.yaml \
        -f ./${ENVIRONMENT}/values/${SERVICE_NAME}.yaml \
        -f ./${ENVIRONMENT}/secrets/secrets.${SERVICE_NAME}.yaml

    echo "✓ Helm upgrade complete"

    echo ""
    echo "=== Verifying deployment ==="
    kubectl rollout status deployment/${SERVICE_NAME} -n ${NAMESPACE} --timeout=5m
    kubectl get pods -n ${NAMESPACE}
    kubectl get svc -n ${NAMESPACE}
    kubectl get ingress -n ${NAMESPACE}
    kubectl get endpoints -n ${NAMESPACE}
    echo "✓ ${SERVICE_NAME} deployed and verified"
}

# Main flow
echo "=== Step 1: Package Helm chart ==="
package_helm_chart

echo "=== Step 2: Initialize Helm S3 repository ==="
helm repo add tbi-charts s3://${HELM_S3_BUCKET}/ || true

echo "=== Step 3: Push chart to S3 ==="
push_chart_to_s3_repo

echo "=== Step 4: Clone tbi-environments ==="
clone_tbi_environments

echo "=== Step 5: Update values file ==="
update_values_file

echo "=== Step 6: Update requirements.yaml ==="
update_requirements

echo "=== Step 7: Push updates ==="
push_values_update

echo "=== Step 8: Update Helm repository ==="
helm repo update

echo "=== Step 9: Deploy to Kubernetes ==="
deploy_service

echo ""
echo "=== Deployment Complete ==="
echo "Service: ${SERVICE_NAME} @ ${CHART_VERSION}"
