#!/usr/bin/env python3
"""
Convert parameter-based configs to proper prod-only configs with approval workflow
"""

from pathlib import Path
import re

PARAMETER_SERVICES = [
    "tbi-acc-cron-service",
    "tbi-acc-gimmonix-automation",
    "tbi-acc-hotel-service-connector",
    "tbi-acc-hotel-service",
    "tbi-acc-mybff",
    "tbi-acc-mybooking-frontend",
    "tbi-acc-package-cron",
    "tbi-acc-package-service",
    "tbi-acc-sabreapi",
    "tbi-acc-travelbrands",
    "tbi-acc-travelbrandsagent",
]

# Template for prod-only config with approval workflow
PROD_CONFIG_TEMPLATE = '''version: 2.1

orbs:
  aws-cli: circleci/aws-cli@5.4.1
  helm: circleci/helm@3.2.0

jobs:
  lint-and-test:
    docker:
      - image: {docker_image}
    resource_class: small
    steps:
      - checkout
{lint_test_steps}
      - persist_to_workspace:
          root: .
          paths:
            - VERSION

  build-and-push-images:
    docker:
      - image: cimg/aws:2023.09
    resource_class: medium
    steps:
      - checkout
      - attach_workspace:
          at: .
      - setup_remote_docker:
          docker_layer_caching: true
      - run:
          name: Stage Dockerfile from tbi-devops-environments
          command: |
            set -x
            echo "=== Copying Dockerfile from tbi-devops-environments ==="
            repoURL="https://${{GITHUB_TOKEN}}@github.com/redlabelvacations/tbi-devops-environments"
            git clone $repoURL -b master --single-branch tbi-devops-environments
            case ${{CIRCLE_BRANCH}} in
              develop) envFolder="dev" ;;
              qa) envFolder="qa" ;;
              uat) envFolder="uat" ;;
              master|main) envFolder="prod" ;;
              *) envFolder="dev" ;;
            esac
            dockerfilePath="tbi-devops-environments/${{envFolder}}/{service_name}/docker/Dockerfile"
            if [ -f "$dockerfilePath" ]; then
              cp -v $dockerfilePath ./Dockerfile
              echo "✓ Dockerfile copied from $dockerfilePath"
            else
              echo "ERROR: Dockerfile not found at $dockerfilePath"
              exit 1
            fi
            ls -la Dockerfile
            set +x
      - run:
          name: Generate image tags
          command: |
            BASE_VERSION=$(cat VERSION | tr -d '[:space:]')
            if [ "${{CIRCLE_BRANCH}}" == "master" ] || [ "${{CIRCLE_BRANCH}}" == "main" ]; then
              IMAGE_TAG="${{BASE_VERSION}}"
              echo "🔒 PRODUCTION: Using clean version tag: ${{IMAGE_TAG}}"
            else
              IMAGE_TAG="${{BASE_VERSION}}-${{CIRCLE_BRANCH}}-${{CIRCLE_BUILD_NUM}}"
              echo "Image tag: ${{IMAGE_TAG}}"
            fi
            echo "export IMAGE_TAG=${{IMAGE_TAG}}" >> $BASH_ENV
            echo "${{IMAGE_TAG}}" > IMAGE_TAG
      - persist_to_workspace:
          root: .
          paths:
            - IMAGE_TAG
            - Dockerfile
      - run:
          name: Login to AWS ECR
          command: |
            aws ecr get-login-password --region ${{AWS_REGION}} | \\
            docker login --username AWS --password-stdin ${{AWS_ACCOUNT_ID}}.dkr.ecr.${{AWS_REGION}}.amazonaws.com
      - run:
          name: Build and push Docker image
          command: |
            SERVICE="{service_name}"
            ECR_REGISTRY="${{AWS_ACCOUNT_ID}}.dkr.ecr.${{AWS_REGION}}.amazonaws.com"
            echo "Building ${{SERVICE}}..."
            aws ecr describe-repositories --repository-names ${{SERVICE}} --region ${{AWS_REGION}} || \\
              aws ecr create-repository --repository-name ${{SERVICE}} \\
                --image-tag-mutability IMMUTABLE \\
                --region ${{AWS_REGION}}
            docker build -t ${{SERVICE}}:${{IMAGE_TAG}} .
            docker tag ${{SERVICE}}:${{IMAGE_TAG}} ${{ECR_REGISTRY}}/${{SERVICE}}:${{IMAGE_TAG}}
            docker push ${{ECR_REGISTRY}}/${{SERVICE}}:${{IMAGE_TAG}}
            echo "✓ ${{SERVICE}} pushed to ECR"

  notify-await-build-approval:
    executor: aws-cli/default
    resource_class: small
    steps:
      - checkout
      - aws-cli/setup:
          profile_name: default
      - run:
          name: Send SNS notification - Awaiting BUILD approval
          command: |
            BASE_VERSION=$(cat VERSION | tr -d '[:space:]')
            cat > /tmp/sns-approval-needed.txt \\<< EOF
            ⏳ PRODUCTION Pipeline - Awaiting BUILD Approval

            Service: {service_name}
            Environment: PRODUCTION
            Build: #${{CIRCLE_BUILD_NUM}}
            Branch: ${{CIRCLE_BRANCH}}
            Commit: ${{CIRCLE_SHA1:0:7}}
            Image Tag: ${{BASE_VERSION}}
            Triggered by: ${{CIRCLE_USERNAME}}

            ✅ Tests have passed successfully

            ⏳ MANUAL APPROVAL REQUIRED to proceed with Docker image build

            To approve:
            1. Go to: ${{CIRCLE_BUILD_URL}}
            2. Click "Approve" on the approve-build job

            Once approved, the Docker image will be built and pushed to ECR.
            EOF

            aws sns publish \\
              --region ca-central-1 \\
              --topic-arn "arn:aws:sns:ca-central-1:489176460030:DevOps-alert" \\
              --subject "🔒 PROD Approval Needed: BUILD - {service_name} #${{CIRCLE_BUILD_NUM}}" \\
              --message file:///tmp/sns-approval-needed.txt
            echo "✓ SNS notification sent - awaiting BUILD approval"

  notify-await-deploy-approval:
    executor: aws-cli/default
    resource_class: small
    steps:
      - attach_workspace:
          at: .
      - aws-cli/setup:
          profile_name: default
      - run:
          name: Send SNS notification - Awaiting DEPLOY approval
          command: |
            IMAGE_TAG=$(cat IMAGE_TAG | tr -d '[:space:]')
            cat > /tmp/sns-deploy-approval.txt \\<< EOF
            ⏳ PRODUCTION Pipeline - Awaiting DEPLOY Approval

            Service: {service_name}
            Environment: PRODUCTION
            Namespace: access
            Build: #${{CIRCLE_BUILD_NUM}}
            Branch: ${{CIRCLE_BRANCH}}
            Commit: ${{CIRCLE_SHA1:0:7}}
            Image Tag: ${{IMAGE_TAG}}
            Triggered by: ${{CIRCLE_USERNAME}}

            ✅ Tests passed
            ✅ Docker image built and pushed to ECR

            ⏳ MANUAL APPROVAL REQUIRED to deploy to PRODUCTION cluster

            To approve:
            1. Go to: ${{CIRCLE_BUILD_URL}}
            2. Click "Approve" on the approve-deploy job

            ⚠️  WARNING: This will deploy to PRODUCTION Kubernetes cluster!
            ⚠️  Ensure the image has been tested and validated.

            Once approved, the service will be deployed to production.
            EOF

            aws sns publish \\
              --region ca-central-1 \\
              --topic-arn "arn:aws:sns:ca-central-1:489176460030:DevOps-alert" \\
              --subject "🔒 PROD Approval Needed: DEPLOY - {service_name} #${{CIRCLE_BUILD_NUM}}" \\
              --message file:///tmp/sns-deploy-approval.txt
            echo "✓ SNS notification sent - awaiting DEPLOY approval"

  deploy-to-kubernetes:
    executor: aws-cli/default
    resource_class: tbi-local-runner/prod-win
    steps:
      - checkout
      - attach_workspace:
          at: .
      - aws-cli/setup:
          profile_name: default
      - helm/install_helm_client:
          version: v3.8.2
      - run:
          name: Stage deployment scripts from tbi-devops-environments
          command: |
            set -x
            echo "=== Copying deployment scripts from tbi-devops-environments ==="
            repoURL="https://${{GITHUB_TOKEN}}@github.com/redlabelvacations/tbi-devops-environments"
            git clone $repoURL -b master --single-branch tbi-devops-environments
            case ${{CIRCLE_BRANCH}} in
              develop) envFolder="dev" ;;
              qa) envFolder="qa" ;;
              uat) envFolder="uat" ;;
              master|main) envFolder="prod" ;;
              *) envFolder="dev" ;;
            esac
            scriptsPath="tbi-devops-environments/${{envFolder}}/{service_name}/scripts"
            if [ -d "$scriptsPath" ]; then
              mkdir -p scripts
              cp -v $scriptsPath/*.sh scripts/
              echo "✓ Scripts copied from $scriptsPath"
              ls -la scripts/
            else
              echo "ERROR: Scripts directory not found at $scriptsPath"
              exit 1
            fi
            set +x
      - run:
          name: Setup kubectl and helm-secrets
          command: |
            chmod +x scripts/setup-kubectl.sh
            bash scripts/setup-kubectl.sh
      - run:
          name: Package Helm chart, update requirements, and deploy
          command: |
            if [ -z "${{DEPLOY_ENV}}" ]; then
              echo "ERROR: DEPLOY_ENV not set in CircleCI context!"
              echo "Expected DEPLOY_ENV=prod from devops-mgt-prod context"
              exit 1
            fi
            echo "DEPLOY_ENV is set to: ${{DEPLOY_ENV}}"
            if [ "${{DEPLOY_ENV}}" != "prod" ]; then
              echo "WARNING: DEPLOY_ENV=${{DEPLOY_ENV}} but expected 'prod' for PRODUCTION deployment"
              echo "This will deploy to ${{DEPLOY_ENV}}/values/ instead of prod/values/"
              exit 1
            fi
            chmod +x scripts/deploy-services.sh
            bash scripts/deploy-services.sh
      - run:
          name: Send deployment success notification
          command: |
            IMAGE_TAG=$(cat IMAGE_TAG | tr -d '[:space:]')
            cat > /tmp/sns-message.txt \\<< EOF
            ✅ Deployment Successful - {service_name}

            Environment: ${{DEPLOY_ENV}}
            Namespace: access
            Image Tag: ${{IMAGE_TAG}}
            Build: #${{CIRCLE_BUILD_NUM}}
            Branch: ${{CIRCLE_BRANCH}}
            Commit: ${{CIRCLE_SHA1:0:7}}
            Triggered by: ${{CIRCLE_USERNAME}}

            View build: ${{CIRCLE_BUILD_URL}}
            EOF

            aws sns publish \\
              --region ca-central-1 \\
              --topic-arn "arn:aws:sns:ca-central-1:489176460030:DevOps-alert" \\
              --subject "DevOps CI/CD Pipeline Notification" \\
              --message file:///tmp/sns-message.txt
            echo "✓ Deployment success notification sent"
      - run:
          name: Send deployment failure notification
          when: on_fail
          command: |
            IMAGE_TAG=$(cat IMAGE_TAG 2>/dev/null | tr -d '[:space:]' || echo "unknown")
            cat > /tmp/sns-failure.txt \\<< EOF
            ❌ Deployment Failed - {service_name}

            Environment: ${{DEPLOY_ENV}}
            Namespace: access
            Image Tag: ${{IMAGE_TAG}}
            Build: #${{CIRCLE_BUILD_NUM}}
            Branch: ${{CIRCLE_BRANCH}}
            Commit: ${{CIRCLE_SHA1:0:7}}
            Triggered by: ${{CIRCLE_USERNAME}}

            View build: ${{CIRCLE_BUILD_URL}}

            Please check the build logs for error details.
            EOF

            aws sns publish \\
              --region ca-central-1 \\
              --topic-arn "arn:aws:sns:ca-central-1:489176460030:DevOps-alert" \\
              --subject "DevOps CI/CD Pipeline Notification" \\
              --message file:///tmp/sns-failure.txt
            echo "✓ Deployment failure notification sent"

workflows:
  deploy-{service_name}:
    jobs:
      - lint-and-test:
          context: devops-mgt-prod
          filters:
            branches:
              only:
                - master
      - notify-await-build-approval:
          context: devops-mgt-prod
          requires:
            - lint-and-test
          filters:
            branches:
              only:
                - master
      - approve-build:
          type: approval
          requires:
            - notify-await-build-approval
          filters:
            branches:
              only:
                - master
      - build-and-push-images:
          context: devops-mgt-prod
          requires:
            - approve-build
          filters:
            branches:
              only:
                - master
      - notify-await-deploy-approval:
          context: devops-mgt-prod
          requires:
            - build-and-push-images
          filters:
            branches:
              only:
                - master
      - approve-deploy:
          type: approval
          requires:
            - notify-await-deploy-approval
          filters:
            branches:
              only:
                - master
      - deploy-to-kubernetes:
          context: devops-mgt-prod
          requires:
            - approve-deploy
          filters:
            branches:
              only:
                - master
'''

def detect_docker_image_and_steps(content):
    """Extract docker image and lint/test steps from existing config"""
    # Try to find docker image from lint job
    docker_match = re.search(r'lint:.*?docker:.*?- image: ([\w:./-]+)', content, re.DOTALL)
    docker_image = docker_match.group(1) if docker_match else "cimg/base:stable"
    
    # Extract lint and test steps (simplified - just use basic steps)
    if "php" in docker_image.lower():
        lint_test_steps = '''      - run:
          name: Install dependencies
          command: composer install --no-interaction --prefer-dist
      - run:
          name: Run linting
          command: find app -name "*.php" -print0 | xargs -0 -n1 php -l || echo "Linting completed"
      - run:
          name: Run tests
          command: |
            if [ -f "phpunit.xml" ]; then
              vendor/bin/phpunit || echo "Tests completed"
            else
              echo "No tests configured"
            fi'''
    elif "node" in docker_image.lower():
        lint_test_steps = '''      - restore_cache:
          keys:
            - v2-dependencies-{{ checksum "package-lock.json" }}
            - v2-dependencies-
      - run:
          name: Install dependencies
          command: npm ci
      - save_cache:
          paths:
            - node_modules
          key: v2-dependencies-{{ checksum "package-lock.json" }}
      - run:
          name: Run linting
          command: npm run lint || echo "Linting completed"
      - run:
          name: Run tests
          command: npm run test || echo "Tests completed"
      - run:
          name: Run build validation
          command: npm run build'''
    else:
        lint_test_steps = '''      - run:
          name: Run linting
          command: echo "Linting step - configure as needed"
      - run:
          name: Run tests
          command: echo "Test step - configure as needed"'''
    
    return docker_image, lint_test_steps

def convert_config(service_name):
    """Convert a parameter-based config to prod-only with approval workflow"""
    config_path = Path(f"prod/{service_name}/.circleci/config.yml")
    
    if not config_path.exists():
        print(f"❌ Config not found: {config_path}")
        return False
    
    content = config_path.read_text()
    
    # Check if already converted (has notify-await-build-approval)
    if "notify-await-build-approval" in content:
        print(f"✓ {service_name} already converted")
        return True
    
    print(f"→ Converting {service_name}...")
    
    # Detect docker image and steps from existing config
    docker_image, lint_test_steps = detect_docker_image_and_steps(content)
    
    # Generate new config from template
    new_config = PROD_CONFIG_TEMPLATE.format(
        service_name=service_name,
        docker_image=docker_image,
        lint_test_steps=lint_test_steps
    )
    
    # Write new config
    config_path.write_text(new_config)
    print(f"✓ {service_name} converted successfully")
    return True

def main():
    print(f"Converting {len(PARAMETER_SERVICES)} parameter-based configs to prod-only with approval workflow...")
    print()
    
    success_count = 0
    for service in PARAMETER_SERVICES:
        if convert_config(service):
            success_count += 1
        print()
    
    print(f"✓ Converted {success_count}/{len(PARAMETER_SERVICES)} configs")

if __name__ == "__main__":
    main()
