#!/usr/bin/env bash
set -euo pipefail

# Default options
APPLY=false
DRY_RUN=true

while [[ $# -gt 0 ]]; do
  case $1 in
    --apply)
      APPLY=true
      DRY_RUN=false
      shift
      ;;
    --dry-run)
      APPLY=false
      DRY_RUN=true
      shift
      ;;
    *)
      echo "Unknown option: $1" >&2
      exit 1
      ;;
  esac
done

AGE_KEY="${APPSOK_SOPS_AGE_KEY_FILE:-$HOME/.config/sops/age/appsok-ci-key.txt}"
SECRET_FILE="${APPSOK_CI_SECRET_FILE:-secrets/appsok.ci.sops.json}"

export PATH="$HOME/SDK/flutter/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"

cd "$(git rev-parse --show-toplevel 2>/dev/null || pwd)"

# SCM URL extraction
SCM_URL="${APPSOK_SCM_URL:-$(git config --get remote.origin.url 2>/dev/null || git remote get-url origin 2>/dev/null || echo "https://github.com/toki-labs/appsok.git")}"

# Reject HTTP(S) SCM URLs with userinfo (credential injection prevention)
reject_http_scm_userinfo() {
  local url="$1"
  if [[ "$url" =~ ^https?://[^/]*@ ]]; then
    echo "Error: SCM remote URL must be credential-free for Jenkins job XML. Configure a credential-free remote and store credentials in Jenkins." >&2
    exit 1
  fi
}

# XML text escaping helper
xml_escape() {
  python3 -c 'import html, sys; print(html.escape(sys.stdin.read(), quote=True), end="")'
}

reject_http_scm_userinfo "$SCM_URL"
SCM_URL_XML="$(printf '%s' "$SCM_URL" | xml_escape)"

# Prepare XML template
# Make sure to exactly match the XML template in the PLAN
XML_CONTENT=$(cat <<EOF
<project>
  <actions/>
  <description>AppSok certified macOS artifact thin launcher (appsok-macos-certified).</description>
  <keepDependencies>false</keepDependencies>
  <properties/>
  <scm class="hudson.plugins.git.GitSCM" plugin="git">
    <branches>
      <hudson.plugins.git.BranchSpec>
        <name>*/main</name>
      </hudson.plugins.git.BranchSpec>
    </branches>
    <userRemoteConfigs>
      <hudson.plugins.git.UserRemoteConfig>
        <url>${SCM_URL_XML}</url>
      </hudson.plugins.git.UserRemoteConfig>
    </userRemoteConfigs>
  </scm>
  <assignedNode>macbook-ultra</assignedNode>
  <canRoam>false</canRoam>
  <logRotator class="hudson.tasks.LogRotator">
    <daysToKeep>-1</daysToKeep>
    <numToKeep>10</numToKeep>
    <artifactDaysToKeep>-1</artifactDaysToKeep>
    <artifactNumToKeep>10</artifactNumToKeep>
  </logRotator>
  <triggers>
    <com.cloudbees.jenkins.GitHubPushTrigger plugin="github">
      <spec></spec>
    </com.cloudbees.jenkins.GitHubPushTrigger>
  </triggers>
  <builders>
    <hudson.tasks.Shell>
      <command>set -euo pipefail
./scripts/build-certified-macos.sh</command>
    </hudson.tasks.Shell>
  </builders>
  <publishers>
    <hudson.tasks.ArtifactArchiver>
      <artifacts>build/macos/Build/Products/Release/AppSok-certified.zip,build/macos/Build/Products/Release/AppSok-certified.zip.sha256</artifacts>
      <allowEmptyArchive>false</allowEmptyArchive>
      <onlyIfSuccessful>true</onlyIfSuccessful>
    </hudson.tasks.ArtifactArchiver>
  </publishers>
  <buildWrappers/>
</project>
EOF
)

if [ "$DRY_RUN" = "true" ]; then
  echo "$XML_CONTENT"
  exit 0
fi

# Apply logic
if [ ! -f "$AGE_KEY" ]; then
  echo "Error: missing SOPS age key at $AGE_KEY" >&2
  exit 1
fi

if [ ! -f "$SECRET_FILE" ]; then
  echo "Error: missing encrypted CI secret file at $SECRET_FILE" >&2
  exit 1
fi

export SOPS_AGE_KEY_FILE="$AGE_KEY"

read_secret() {
  local key="$1"
  sops -d "$SECRET_FILE" | python3 -c "import json, sys; print(json.load(sys.stdin).get('$key', ''))"
}

JENKINS_URL="$(read_secret jenkins_url)"
JENKINS_USER="$(read_secret jenkins_username)"
JENKINS_TOKEN="$(read_secret jenkins_api_token)"

if [ -z "$JENKINS_URL" ] || [ -z "$JENKINS_USER" ] || [ -z "$JENKINS_TOKEN" ]; then
  echo "Error: Missing Jenkins configurations in secrets." >&2
  exit 1
fi

# Remove trailing slash if present in JENKINS_URL
JENKINS_URL="${JENKINS_URL%/}"

CURL_CONFIG="$(mktemp)"
chmod 600 "$CURL_CONFIG"
trap 'rm -f "$CURL_CONFIG"' EXIT
curl_config_escape() {
  local value="$1"
  value="${value//\\/\\\\}"
  value="${value//\"/\\\"}"
  printf '%s' "$value"
}

{
  printf 'user = "'
  curl_config_escape "$JENKINS_USER"
  printf ':'
  curl_config_escape "$JENKINS_TOKEN"
  printf '"\n'
} >"$CURL_CONFIG"

# 1. Fetch Crumb
CRUMB_HEADER=""
CRUMB_RESPONSE=$(curl -s --config "$CURL_CONFIG" "${JENKINS_URL}/crumbIssuer/api/json" || true)

if [ -n "$CRUMB_RESPONSE" ] && echo "$CRUMB_RESPONSE" | grep -q "crumb"; then
  CRUMB_FIELD=$(echo "$CRUMB_RESPONSE" | python3 -c "import json, sys; print(json.load(sys.stdin)['crumbRequestField'])")
  CRUMB_VALUE=$(echo "$CRUMB_RESPONSE" | python3 -c "import json, sys; print(json.load(sys.stdin)['crumb'])")
  CRUMB_HEADER="${CRUMB_FIELD}:${CRUMB_VALUE}"
fi

# 2. Check if job exists
CHECK_URL="${JENKINS_URL}/job/appsok-macos-certified/config.xml"
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --config "$CURL_CONFIG" "$CHECK_URL" || echo "500")

CURL_OPTS=(-s -w "%{http_code}" -o /dev/null)
if [ -n "$CRUMB_HEADER" ]; then
  CURL_OPTS+=(-H "$CRUMB_HEADER")
fi

if [ "$HTTP_STATUS" = "200" ]; then
  echo "Updating existing job appsok-macos-certified..."
  UPDATE_URL="${JENKINS_URL}/job/appsok-macos-certified/config.xml"
  STATUS=$(curl "${CURL_OPTS[@]}" --config "$CURL_CONFIG" -H "Content-Type: application/xml" --data-binary "$XML_CONTENT" "$UPDATE_URL" || echo "500")
  if [ "$STATUS" = "200" ] || [ "$STATUS" = "201" ] || [ "$STATUS" = "302" ]; then
    echo "Successfully updated job configuration."
  else
    echo "Failed to update job. HTTP status: $STATUS" >&2
    exit 1
  fi
elif [ "$HTTP_STATUS" = "404" ]; then
  echo "Creating new job appsok-macos-certified..."
  CREATE_URL="${JENKINS_URL}/createItem?name=appsok-macos-certified"
  STATUS=$(curl "${CURL_OPTS[@]}" --config "$CURL_CONFIG" -H "Content-Type: application/xml" --data-binary "$XML_CONTENT" "$CREATE_URL" || echo "500")
  if [ "$STATUS" = "200" ] || [ "$STATUS" = "201" ] || [ "$STATUS" = "302" ]; then
    echo "Successfully created job."
  else
    echo "Failed to create job. HTTP status: $STATUS" >&2
    exit 1
  fi
else
  echo "Failed to query job status. HTTP status: $HTTP_STATUS" >&2
  exit 1
fi
