pipeline {
  agent {
    label 'master'
  }

  options {
    timestamps()
    disableConcurrentBuilds()
  }

  parameters {
    choice(name: 'ENVIRONMENT', choices: ['development', 'main'], description: 'Rama a ejecutar')
    string(name: 'VERSION_MAYOR', defaultValue: '1', description: 'Componente mayor de versión')
  }

  environment {
    REGISTRY = 'dev.aduanasoft.com'
    IMAGE_NAMESPACE = 'anexo76'
  }

  stages {
    stage('Preflight tools') {
      steps {
        sh '''
          set -euo pipefail
          echo "Node: $(hostname)"
          if ! command -v docker >/dev/null 2>&1; then
            echo "ERROR: este agente no tiene docker instalado."
            echo "Usa un nodo Jenkins con label 'docker' y acceso al daemon."
            exit 1
          fi
          docker --version
        '''
      }
    }

    stage('Checkout') {
      steps {
        checkout([
          $class: 'GitSCM',
          branches: [[name: "*/${params.ENVIRONMENT}"]],
          userRemoteConfigs: [[
            url: 'https://git.aduanasoft.com/ADUANASOFT/anexo76.git',
            credentialsId: 'gitea_acazares'
          ]],
          extensions: [[$class: 'CloneOption', depth: 0, shallow: false]]
        ])
      }
    }

    stage('Test backend') {
      steps {
        sh '''
          set -euxo pipefail
          echo "== Test backend stage started =="
          echo "Workspace: $WORKSPACE"
          docker --version

          DB_CONTAINER="anexo76-test-db-${BUILD_NUMBER}"
          DB_NAME="anexo76_test"
          DB_USER="anexo76"
          DB_PASS="anexo76"
          DB_PORT="55432"
          export TEST_DATABASE_URL="postgresql://${DB_USER}:${DB_PASS}@127.0.0.1:${DB_PORT}/${DB_NAME}"
          PY_CONTAINER="anexo76-test-py-${BUILD_NUMBER}"

          cleanup() {
            docker rm -f "$PY_CONTAINER" >/dev/null 2>&1 || true
            docker rm -f "$DB_CONTAINER" >/dev/null 2>&1 || true
          }
          trap cleanup EXIT

          docker rm -f "$DB_CONTAINER" >/dev/null 2>&1 || true
          docker run -d --name "$DB_CONTAINER" \
            -e POSTGRES_DB="$DB_NAME" \
            -e POSTGRES_USER="$DB_USER" \
            -e POSTGRES_PASSWORD="$DB_PASS" \
            -p "${DB_PORT}:5432" \
            postgres:16-alpine

          # Espera a que Postgres acepte conexiones
          for i in $(seq 1 30); do
            if docker exec "$DB_CONTAINER" pg_isready -U "$DB_USER" -d "$DB_NAME" >/dev/null 2>&1; then
              break
            fi
            sleep 2
          done
          docker exec "$DB_CONTAINER" pg_isready -U "$DB_USER" -d "$DB_NAME"

          docker run --name "$PY_CONTAINER" --rm \
            --network host \
            -e TEST_DATABASE_URL="$TEST_DATABASE_URL" \
            -v "$WORKSPACE:/workspace" \
            -w /workspace \
            python:3.12-slim \
            sh -lc '
              set -euxo pipefail
              python --version
              python -m pip install --upgrade pip
              pip install -r /workspace/backend/requirements.txt
              cd /workspace/backend
              alembic upgrade head
              pytest -q tests -v -ra -s
            '
        '''
      }
    }

    stage('Generate version') {
      steps {
        script {
          def year = sh(returnStdout: true, script: 'date +%y').trim()
          def month = sh(returnStdout: true, script: 'date +%m').trim()

          if (params.ENVIRONMENT == 'development') {
            def shortHash = sh(returnStdout: true, script: 'git rev-parse --short=8 HEAD').trim()
            env.APP_VERSION = "${year}.${month}.${params.VERSION_MAYOR}.${shortHash}"
          } else {
            def lastTag = sh(returnStdout: true, script: 'git describe --tags --abbrev=0 2>/dev/null || true').trim()
            def commitCount = lastTag
              ? sh(returnStdout: true, script: "git rev-list ${lastTag}..HEAD --count").trim()
              : sh(returnStdout: true, script: 'git rev-list --count HEAD').trim()

            if (commitCount == '0') {
              commitCount = '1'
            }
            env.APP_VERSION = "${year}.${month}.${params.VERSION_MAYOR}.${commitCount}"
          }

          echo "VERSION: ${env.APP_VERSION}"
        }
      }
    }

    stage('Docker login') {
      steps {
        withCredentials([usernamePassword(credentialsId: 'harbor-credentials', usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD')]) {
          sh '''
            set -euo pipefail
            echo "$HARBOR_PASSWORD" | docker login "$REGISTRY" -u "$HARBOR_USERNAME" --password-stdin
          '''
        }
      }
    }

    stage('Build + push backend') {
      steps {
        sh '''
          set -euo pipefail
          docker build \
            --build-arg APP_VERSION="${APP_VERSION}" \
            -t "${REGISTRY}/${IMAGE_NAMESPACE}/backend:latest" \
            -f ./backend/Dockerfile \
            ./backend

          docker push "${REGISTRY}/${IMAGE_NAMESPACE}/backend:latest"
        '''
      }
    }

    stage('Build + push frontend') {
      steps {
        sh '''
          set -euo pipefail
          docker build \
            --build-arg VITE_API_URL=https://anexo76-dev.aduanasoft.com/api/ \
            --build-arg VITE_KEYCLOAK_URL=https://anexo76-dev.aduanasoft.com/kcauth/ \
            --build-arg INTERNAL_API_URL=http://backend:3467/api/ \
            -t "${REGISTRY}/${IMAGE_NAMESPACE}/frontend:latest" \
            -f ./frontend/Dockerfile.prod \
            ./frontend

          docker push "${REGISTRY}/${IMAGE_NAMESPACE}/frontend:latest"
        '''
      }
    }

    stage('Tag release (main)') {
      when {
        expression { params.ENVIRONMENT == 'main' }
      }
      steps {
        withCredentials([usernamePassword(credentialsId: 'gitea_acazares', usernameVariable: 'GIT_USERNAME', passwordVariable: 'GIT_PASSWORD')]) {
          sh '''
            set -euo pipefail
            git -c user.name='Jenkins' -c user.email='jenkins@gitea.local' \
              tag -a "v${APP_VERSION}" -m "Release version ${APP_VERSION}"
            git remote set-url origin "https://${GIT_USERNAME}:${GIT_PASSWORD}@git.aduanasoft.com/ADUANASOFT/anexo76.git"
            git push origin "v${APP_VERSION}"
          '''
        }        
      }
    }

    stage('Deploy development') {
      when {
        expression { params.ENVIRONMENT == 'development' }
      }
      steps {
        withCredentials([
          usernamePassword(credentialsId: 'harbor-credentials', usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD'),
          string(credentialsId: 'dev-server-user', variable: 'DEV_SERVER_USER'),
          string(credentialsId: 'dev-server-host', variable: 'DEV_SERVER_HOST')
        ]) {
          sshagent(credentials: ['dev-server-ssh']) {
            sh '''
              set -euo pipefail
              ssh -o StrictHostKeyChecking=accept-new "${DEV_SERVER_USER}@${DEV_SERVER_HOST}" '
                cd ~/projects/anexo76 &&
                echo '"'"'"${HARBOR_PASSWORD}"'"'"' | docker login '"${REGISTRY}"' -u '"${HARBOR_USERNAME}"' --password-stdin &&
                docker compose -f docker-compose.prod.yml pull &&
                docker compose -f docker-compose.prod.yml up -d &&
                docker image prune -f
              '
            '''
          }
        }
      }
    }
  }

}
