#!/usr/bin/env bash
set -euo pipefail
if [[ "${CP9_VERBOSE:-}" == "1" ]]; then
  set -x
fi

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
image_repository="385595570414.dkr.ecr.us-west-2.amazonaws.com/tidbcloud/cp9-dbaas-ui"
publish_base_image="${image_repository}@sha256:b7478f4d244eb59ec10b137ae68b575c8646bb12634e185bf25b13aafd2c253b"
aws_region="us-west-2"
publish="${DBAAS_UI_PUBLISH:-false}"
artifact_root="${DBAAS_UI_ARTIFACT_DIR:-${repo_root}/.artifacts/dbaas-ui-candidate}"
candidate_id="${DBAAS_UI_CANDIDATE_ID:-$(date -u +%Y%m%dT%H%M%SZ)-$$}"
source_input="${DBAAS_UI_SOURCE_DIR:-}"
manifest_path="${repo_root}/build/dbaas-ui/overlay/manifest.json"

if [[ ! "${candidate_id}" =~ ^[A-Za-z0-9][A-Za-z0-9_.-]{0,80}$ ]]; then
  echo "DBAAS_UI_CANDIDATE_ID must be a tag-safe identifier" >&2
  exit 1
fi
if [[ "${publish}" != "true" && "${publish}" != "false" ]]; then
  echo "DBAAS_UI_PUBLISH must be true or false" >&2
  exit 1
fi
if [[ "${publish}" == "true" && -n "${source_input}" ]]; then
  echo "DBAAS_UI_SOURCE_DIR is local-validation-only and cannot publish" >&2
  exit 1
fi
artifact_dir="${artifact_root}/${candidate_id}"
source_dir="${artifact_dir}/source"
package_dir="${artifact_dir}/package"
if [[ -e "${artifact_dir}" ]]; then
  echo "candidate artifact directory already exists: ${artifact_dir}" >&2
  exit 1
fi
mkdir -p "${artifact_dir}"

require_command() {
  if ! command -v "$1" >/dev/null 2>&1; then
    echo "required command is unavailable: $1" >&2
    exit 1
  fi
}

for command in git node corepack docker; do
  require_command "${command}"
done

reviewed_commit="$(node -p "require(process.argv[1]).upstream.reviewed_commit" "${manifest_path}")"
reviewed_lockfile_sha256="$(node -p "require(process.argv[1]).upstream.reviewed_lockfile_sha256" "${manifest_path}")"
if [[ ! "${reviewed_commit}" =~ ^[0-9a-f]{40}$ || ! "${reviewed_lockfile_sha256}" =~ ^[0-9a-f]{64}$ ]]; then
  echo "overlay manifest contains an invalid reviewed commit or lockfile digest" >&2
  exit 1
fi

if [[ -n "${source_input}" ]]; then
  upstream_commit="${DBAAS_UI_UPSTREAM_COMMIT:-$(git -C "${source_input}" rev-parse HEAD)}"
  git clone --no-checkout --no-hardlinks "${source_input}" "${source_dir}"
else
  require_command gh
  upstream_commit="${DBAAS_UI_UPSTREAM_COMMIT:-$(gh api repos/tidbcloud/dbaas-ui/commits/master --jq .sha)}"
  gh repo clone tidbcloud/dbaas-ui "${source_dir}" -- --filter=blob:none --no-checkout
  git -C "${source_dir}" fetch --depth=1 origin "${upstream_commit}"
fi
if [[ ! "${upstream_commit}" =~ ^[0-9a-f]{40}$ ]]; then
  echo "resolved upstream commit is not a full SHA-1: ${upstream_commit}" >&2
  exit 1
fi
git -C "${source_dir}" checkout --detach "${upstream_commit}"
resolved_commit="$(git -C "${source_dir}" rev-parse HEAD)"
if [[ "${resolved_commit}" != "${upstream_commit}" ]]; then
  echo "upstream checkout drift: resolved ${resolved_commit}, expected ${upstream_commit}" >&2
  exit 1
fi
if [[ "${resolved_commit}" != "${reviewed_commit}" ]]; then
  echo "upstream commit ${resolved_commit} is not the reviewed manifest commit ${reviewed_commit}" >&2
  exit 1
fi
lockfile_sha256="$(node -e "const fs=require('node:fs'),crypto=require('node:crypto'); process.stdout.write(crypto.createHash('sha256').update(fs.readFileSync(process.argv[1])).digest('hex'))" "${source_dir}/pnpm-lock.yaml")"
if [[ "${lockfile_sha256}" != "${reviewed_lockfile_sha256}" ]]; then
  echo "upstream lockfile digest ${lockfile_sha256} does not match reviewed manifest digest ${reviewed_lockfile_sha256}" >&2
  exit 1
fi
short_commit="${upstream_commit:0:12}"

node "${repo_root}/build/dbaas-ui/overlay/apply.mjs" "${source_dir}"
(
  cd "${source_dir}"
  corepack pnpm install --frozen-lockfile --ignore-scripts
  corepack pnpm gen:api
  corepack pnpm exec prettier --write \
    src/config/index.ts \
    src/config/cp9-runtime.ts \
    src/common/services/prommetric.tsx \
    src/dbaas/services/endpoint.ts \
    src/dbaas/services/auth.ts \
    src/dbaas/services/useO11YQuery.ts \
    src/dbaas/screens/Cluster/OverviewV2/SpendLimitUsage/EstimationCard/helpers.ts \
    src/dbaas/screens/NextGen/my-tidb-creation/layout/TwoPaneLayout.tsx \
    src/dbaas/screens/NextGen/premium/backup/RecycleBinCard.tsx \
    src/dbaas/screens/NextGen/premium/restore/Create.tsx \
    src/dbaas/screens/OAuth/SignIn/index.tsx \
    src/dbaas/screens/User/InviteeAccepting/constants.ts \
    src/dbaas/screens/User/SignIn/enterprise.tsx \
    src/dbaas/utils/tracking/index.ts \
    src/index.tsx \
    public/index.html \
    public/config.js \
    public/dashboard/index.html \
    public/dashboard/o11y.html
  corepack pnpm typecheck
  NODE_ENV=production GENERATE_SOURCEMAP=false corepack pnpm build:app
)

mkdir -p "${package_dir}/site"
cp -R "${source_dir}/build/." "${package_dir}/site/"
cp "${repo_root}/build/dbaas-ui/Caddyfile" "${repo_root}/build/dbaas-ui/Dockerfile" "${package_dir}/"

if [[ "${publish}" == "true" ]]; then
  require_command aws
  require_command jq
  aws_profile="${DBAAS_UI_AWS_PROFILE:?DBAAS_UI_AWS_PROFILE is required when publishing}"
  publisher_account="$(aws --profile "${aws_profile}" sts get-caller-identity --query Account --output text)"
  if [[ ! "${publisher_account}" =~ ^[0-9]{12}$ ]]; then
    echo "publisher profile resolved invalid AWS account ${publisher_account}" >&2
    exit 1
  fi
  if [[ "${publisher_account}" == "385595570414" ]]; then
    echo "publisher profile must resolve a CP9 runtime account, not source account 385595570414" >&2
    exit 1
  fi
  publisher_arn="$(aws --profile "${aws_profile}" sts get-caller-identity --query Arn --output text)"
  publisher_prefix="arn:aws:sts::${publisher_account}:assumed-role/cp9-developer/"
  if [[ "${publisher_arn}" != "${publisher_prefix}"* || "${publisher_arn}" == "${publisher_prefix}" ]]; then
    echo "publisher profile must resolve its runtime account cp9-developer assumed role; got ${publisher_arn}" >&2
    exit 1
  fi

  docker_config_dir="$(mktemp -d)"
  trap 'rm -rf "${docker_config_dir}"' EXIT
  for docker_state in cli-plugins buildx contexts; do
    if [[ -e "${HOME}/.docker/${docker_state}" ]]; then
      ln -s "${HOME}/.docker/${docker_state}" "${docker_config_dir}/${docker_state}"
    fi
  done
  if [[ -f "${HOME}/.docker/config.json" ]]; then
    jq 'del(.auths, .credsStore, .credHelpers)' "${HOME}/.docker/config.json" >"${docker_config_dir}/config.json"
  else
    jq -n '{}' >"${docker_config_dir}/config.json"
  fi
  export DOCKER_CONFIG="${docker_config_dir}"

  aws --profile "${aws_profile}" ecr get-login-password --region "${aws_region}" |
    docker login --username AWS --password-stdin 385595570414.dkr.ecr.us-west-2.amazonaws.com
fi

local_image="cp9.local/dbaas-ui:${short_commit}-${candidate_id}"
if [[ "${publish}" == "true" ]]; then
  docker build \
    --build-arg "BASE_IMAGE=${publish_base_image}" \
    --tag "${local_image}" \
    "${package_dir}"
else
  docker build --tag "${local_image}" "${package_dir}"
fi

if [[ "${publish}" != "true" ]]; then
  echo "local candidate build passed: ${artifact_dir}"
  echo "publication skipped; rerun with DBAAS_UI_PUBLISH=true and an explicit cp9-developer AWS profile after approval"
  exit 0
fi

candidate_tag="${image_repository}:candidate-${short_commit}-${candidate_id}"
docker buildx build \
  --build-arg "BASE_IMAGE=${publish_base_image}" \
  --platform linux/amd64,linux/arm64 \
  --push \
  --tag "${candidate_tag}" \
  --provenance=mode=max \
  --metadata-file "${artifact_dir}/buildx-metadata.json" \
  "${package_dir}"
digest="$(jq -er '."containerimage.digest"' "${artifact_dir}/buildx-metadata.json")"
if [[ ! "${digest}" =~ ^sha256:[0-9a-f]{64}$ ]]; then
  echo "published candidate returned invalid digest: ${digest}" >&2
  exit 1
fi

docker pull "${image_repository}@${digest}"

echo "published immutable dbaas-ui candidate ${image_repository}@${digest}"
