#!/usr/bin/env bash

set -euo pipefail

project_root="/home/rollschomq-rg/test-next.rollschool.pl"
expected_host="test-next.rollschool.pl"
expected_url="https://test-next.rollschool.pl/"
expected_environment="DEV"

fail() {
    echo "$1" >&2
    exit 1
}

if [[ -n "${SSH_ORIGINAL_COMMAND:-}" ]]; then
    read -r command_name requested_commit unexpected_argument <<< "${SSH_ORIGINAL_COMMAND}"
    [[ "${command_name}" == "deploy" && -n "${requested_commit:-}" && -z "${unexpected_argument:-}" ]] \
        || fail "Allowed command: deploy FULL_COMMIT_SHA"
else
    requested_commit="${1:-}"
fi

[[ "${requested_commit}" =~ ^[0-9a-f]{40}$ ]] || fail "A full 40-character lowercase commit SHA is required."
[[ -d "${project_root}/.git" ]] || fail "Git working tree is missing at ${project_root}."

cd "${project_root}"

[[ -f application/config/config.php ]] || fail "Missing server-owned application/config/config.php."
[[ -d Files ]] || fail "Missing server-owned Files directory."

if [[ -n "$(git status --porcelain --untracked-files=normal)" ]]; then
    git status --short >&2
    fail "The server working tree is not clean. Deployment stopped."
fi

git fetch --prune origin main
git cat-file -e "${requested_commit}^{commit}" 2>/dev/null \
    || fail "Commit ${requested_commit} is unavailable after fetching origin/main."
git merge-base --is-ancestor "${requested_commit}" origin/main \
    || fail "Commit ${requested_commit} is not part of origin/main."

if git ls-tree -r --name-only "${requested_commit}" -- \
    application/config/config.php .deployment.env .ovhconfig .user.ini Files \
    | grep -Eq '^(application/config/config\.php|\.deployment\.env|\.ovhconfig|\.user\.ini|Files(/|$))'; then
    fail "The selected commit attempts to track server-owned configuration or Files data."
fi

if git ls-tree -r --name-only "${requested_commit}" -- \
    application/Resources/css/bootstrap.min.css application/Resources/css/bootstrap.min.css.sha256 \
    | grep -Eq '^application/Resources/css/bootstrap\.min\.css(\.sha256)?$'; then
    fail "The selected commit must not track generated stylesheet files."
fi

previous_commit="$(git rev-parse HEAD)"
if [[ "${previous_commit}" == "${requested_commit}" ]]; then
    echo "Commit ${requested_commit} is already deployed; running verification again."
    "${project_root}/scripts/after-deployment-pull.sh" \
        "${expected_host}" "${expected_url}" "${expected_environment}"
    exit 0
fi

git checkout --detach "${requested_commit}"

if ! "${project_root}/scripts/after-deployment-pull.sh" \
    "${expected_host}" "${expected_url}" "${expected_environment}"; then
    echo "Deployment verification failed. Restoring ${previous_commit}." >&2
    if git ls-tree -r --name-only "${previous_commit}" -- \
        application/Resources/css/bootstrap.min.css \
        | grep -Fxq 'application/Resources/css/bootstrap.min.css'; then
        rm -f -- application/Resources/css/bootstrap.min.css \
            application/Resources/css/bootstrap.min.css.sha256
    fi
    git checkout --detach "${previous_commit}"
    "${project_root}/scripts/after-deployment-pull.sh" \
        "${expected_host}" "${expected_url}" "${expected_environment}" \
        || fail "Rollback code was restored, but rollback verification also failed. Manual intervention is required."
    fail "Deployment failed and code was rolled back to ${previous_commit}."
fi

echo "Successfully deployed ${requested_commit} to ${expected_url}."
