#!/usr/bin/env bash

set -u

ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
VENV_DIR="${HOME}/.local/share/ffx.venv"
VENV_BIN_DIR="${VENV_DIR}/bin"
VENV_PYTHON="${VENV_BIN_DIR}/python"
VENV_PIP="${VENV_BIN_DIR}/pip"
VENV_FFX="${VENV_BIN_DIR}/ffx"
BASHRC_FILE="${HOME}/.bashrc"
ALIAS_BLOCK_BEGIN="# >>> ffx alias >>>"
ALIAS_BLOCK_END="# <<< ffx alias <<<"
ALIAS_LINE="alias ffx=\"${VENV_FFX}\""

CHECK_ONLY=0
WITH_TESTS=0
READINESS_FAILURES=0
INSTALL_FAILURES=0

COLOR_RESET=""
COLOR_GREEN=""
COLOR_YELLOW=""
COLOR_RED=""

if [ -t 1 ]; then
    COLOR_RESET="$(printf '\033[0m')"
    COLOR_GREEN="$(printf '\033[32m')"
    COLOR_YELLOW="$(printf '\033[33m')"
    COLOR_RED="$(printf '\033[31m')"
fi

usage() {
    cat <<EOF
Usage: $(basename "$0") [--check] [--with-tests] [--help]

Prepare the persistent FFX bundle installation at:
  ${VENV_DIR}

Actions:
  - create or reuse ${VENV_DIR}
  - install this repository into the venv with pip --editable
  - ensure ${BASHRC_FILE} exposes alias ffx -> ${VENV_FFX}
  - optionally install Python packages required for modern tests

Options:
  --check       Report readiness only. Do not create or modify anything.
  --with-tests  Also install and verify Python packages required for modern tests.
  --help        Show this help text.

Notes:
  - This is the first installation step.
  - After the bundle is installed, the aligned CLI wrapper is: ffx setup
  - tools/configure_workstation.sh is the second step and configures system dependencies plus local user files.
EOF
}

status_ok() {
    printf '%sok%s' "${COLOR_GREEN}" "${COLOR_RESET}"
}

status_warn() {
    printf '%swarn%s' "${COLOR_YELLOW}" "${COLOR_RESET}"
}

status_fail() {
    printf '%sfailed%s' "${COLOR_RED}" "${COLOR_RESET}"
}

report_component() {
    local level="$1"
    local label="$2"
    local detail="$3"
    local rendered_status=""

    case "${level}" in
        ok)
            rendered_status="$(status_ok)"
            ;;
        warn)
            rendered_status="$(status_warn)"
            ;;
        *)
            rendered_status="$(status_fail)"
            ;;
    esac

    printf '[%s] %s%s\n' "${rendered_status}" "${label}" "${detail:+: $detail}"
}

command_exists() {
    command -v "$1" >/dev/null 2>&1
}

check_python3() {
    command_exists python3
}

check_venv_dir() {
    [ -x "${VENV_PYTHON}" ]
}

check_venv_pip() {
    check_venv_dir && "${VENV_PIP}" --version >/dev/null 2>&1
}

check_venv_ffx() {
    [ -x "${VENV_FFX}" ]
}

check_venv_pytest() {
    check_venv_dir && "${VENV_PYTHON}" -m pytest --version >/dev/null 2>&1
}

check_bashrc_file() {
    [ -f "${BASHRC_FILE}" ]
}

check_bashrc_alias() {
    check_bashrc_file && grep -Fqx "${ALIAS_LINE}" "${BASHRC_FILE}"
}

detail_python3() {
    command -v python3 || printf "command 'python3' not found"
}

detail_venv_dir() {
    if check_venv_dir; then
        printf '%s' "${VENV_DIR}"
    else
        printf 'missing %s' "${VENV_DIR}"
    fi
}

detail_venv_pip() {
    if check_venv_pip; then
        "${VENV_PIP}" --version
    else
        printf 'missing pip in %s' "${VENV_DIR}"
    fi
}

detail_venv_ffx() {
    if check_venv_ffx; then
        printf '%s' "${VENV_FFX}"
    else
        printf 'missing %s' "${VENV_FFX}"
    fi
}

detail_venv_pytest() {
    if check_venv_pytest; then
        "${VENV_PYTHON}" -m pytest --version 2>/dev/null | head -n 1
    else
        printf 'missing pytest in %s' "${VENV_DIR}"
    fi
}

detail_bashrc_file() {
    if check_bashrc_file; then
        printf '%s' "${BASHRC_FILE}"
    else
        printf 'missing %s; prep can create it' "${BASHRC_FILE}"
    fi
}

detail_bashrc_alias() {
    if check_bashrc_alias; then
        printf '%s' "${ALIAS_LINE}"
    else
        printf 'missing alias line for %s' "${VENV_FFX}"
    fi
}

print_status_report() {
    READINESS_FAILURES=0

    echo "Dependency status:"
    if check_python3; then
        report_component ok "python3" "$(detail_python3)"
    else
        report_component failed "python3" "$(detail_python3)"
        READINESS_FAILURES=$((READINESS_FAILURES + 1))
    fi

    echo
    echo "Bundle venv status:"
    if check_venv_dir; then
        report_component ok "bundle virtualenv" "$(detail_venv_dir)"
    else
        report_component failed "bundle virtualenv" "$(detail_venv_dir)"
        READINESS_FAILURES=$((READINESS_FAILURES + 1))
    fi

    if check_venv_pip; then
        report_component ok "bundle pip" "$(detail_venv_pip)"
    else
        report_component failed "bundle pip" "$(detail_venv_pip)"
        READINESS_FAILURES=$((READINESS_FAILURES + 1))
    fi

    if check_venv_ffx; then
        report_component ok "bundle ffx" "$(detail_venv_ffx)"
    else
        report_component failed "bundle ffx" "$(detail_venv_ffx)"
        READINESS_FAILURES=$((READINESS_FAILURES + 1))
    fi

    if [ "${WITH_TESTS}" -eq 1 ]; then
        echo
        echo "Bundle test package status:"
        if check_venv_pytest; then
            report_component ok "bundle pytest" "$(detail_venv_pytest)"
        else
            report_component failed "bundle pytest" "$(detail_venv_pytest)"
            READINESS_FAILURES=$((READINESS_FAILURES + 1))
        fi
    fi

    echo
    echo "Shell exposure status:"
    if check_bashrc_file; then
        report_component ok ".bashrc" "$(detail_bashrc_file)"
    else
        report_component warn ".bashrc" "$(detail_bashrc_file)"
    fi

    if check_bashrc_alias; then
        report_component ok "ffx alias" "$(detail_bashrc_alias)"
    else
        report_component failed "ffx alias" "$(detail_bashrc_alias)"
        READINESS_FAILURES=$((READINESS_FAILURES + 1))
    fi
}

ensure_bundle_venv() {
    mkdir -p "${HOME}/.local/share"

    if ! check_venv_dir; then
        printf 'Creating bundle virtualenv at %s...\n' "${VENV_DIR}"
        if ! python3 -m venv "${VENV_DIR}"; then
            printf 'Failed to create virtualenv at %s.\n' "${VENV_DIR}" >&2
            INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
            return 1
        fi
    fi

    if ! check_venv_pip; then
        printf 'Missing pip in %s.\n' "${VENV_DIR}" >&2
        INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
        return 1
    fi

    if [ "${WITH_TESTS}" -eq 1 ]; then
        printf 'Installing FFX package and test extras into %s...\n' "${VENV_DIR}"
        if ! (
            cd "${ROOT_DIR}" &&
            "${VENV_PIP}" install --editable '.[test]'
        ); then
            printf 'Failed to install FFX package and test extras into %s.\n' "${VENV_DIR}" >&2
            INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
            return 1
        fi
    else
        printf 'Installing FFX package into %s...\n' "${VENV_DIR}"
        if ! "${VENV_PIP}" install --editable "${ROOT_DIR}"; then
            printf 'Failed to install FFX package into %s.\n' "${VENV_DIR}" >&2
            INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
            return 1
        fi
    fi

    return 0
}

write_alias_block() {
    local bashrc_dir
    bashrc_dir="$(dirname "${BASHRC_FILE}")"
    mkdir -p "${bashrc_dir}"
    touch "${BASHRC_FILE}"

    if grep -Fq "${ALIAS_BLOCK_BEGIN}" "${BASHRC_FILE}" || grep -Fq "${ALIAS_BLOCK_END}" "${BASHRC_FILE}"; then
        if ! python3 - "${BASHRC_FILE}" "${ALIAS_BLOCK_BEGIN}" "${ALIAS_BLOCK_END}" "${ALIAS_LINE}" <<'PY'
import pathlib
import sys

path = pathlib.Path(sys.argv[1])
begin = sys.argv[2]
end = sys.argv[3]
alias_line = sys.argv[4]

content = path.read_text()
block = f"{begin}\n{alias_line}\n{end}\n"

start = content.find(begin)
stop = content.find(end)

if start != -1 and stop != -1 and stop >= start:
    stop += len(end)
    if stop < len(content) and content[stop] == "\n":
        stop += 1
    content = content[:start] + block + content[stop:]
else:
    if content and not content.endswith("\n"):
        content += "\n"
    content += block

path.write_text(content)
PY
        then
            printf 'Failed to update managed alias block in %s.\n' "${BASHRC_FILE}" >&2
            INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
            return 1
        fi
    elif check_bashrc_alias; then
        :
    else
        {
            if [ -s "${BASHRC_FILE}" ] && [ "$(tail -c 1 "${BASHRC_FILE}" 2>/dev/null || true)" != "" ]; then
                printf '\n'
            fi
            printf '%s\n' "${ALIAS_BLOCK_BEGIN}"
            printf '%s\n' "${ALIAS_LINE}"
            printf '%s\n' "${ALIAS_BLOCK_END}"
        } >>"${BASHRC_FILE}" || {
            printf 'Failed to append alias block to %s.\n' "${BASHRC_FILE}" >&2
            INSTALL_FAILURES=$((INSTALL_FAILURES + 1))
            return 1
        }
    fi

    return 0
}

ensure_bashrc_alias() {
    printf 'Ensuring ffx alias in %s...\n' "${BASHRC_FILE}"
    write_alias_block
}

parse_args() {
    while [ "$#" -gt 0 ]; do
        case "$1" in
            --check)
                CHECK_ONLY=1
                ;;
            --with-tests)
                WITH_TESTS=1
                ;;
            --help|-h)
                usage
                exit 0
                ;;
            *)
                printf 'Unknown option: %s\n\n' "$1" >&2
                usage >&2
                exit 2
                ;;
        esac
        shift
    done
}

main() {
    parse_args "$@"

    print_status_report

    if [ "${CHECK_ONLY}" -eq 0 ]; then
        if ! check_python3; then
            printf '\npython3 is required before the bundle venv can be prepared.\n' >&2
            exit 1
        fi

        echo
        ensure_bundle_venv
        ensure_bashrc_alias

        echo
        print_status_report
    fi

    echo
    if [ "${INSTALL_FAILURES}" -gt 0 ]; then
        echo "One or more bundle preparation steps failed; see the status checks above." >&2
        exit 1
    fi

    if [ "${READINESS_FAILURES}" -gt 0 ]; then
        echo "The FFX bundle virtualenv and/or alias setup is incomplete." >&2
        exit 1
    fi

    echo "The FFX bundle virtualenv is ready."
}

main "$@"
