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

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$script_dir/day_hiomrs_runtime.bash"
source "$script_dir/util/sentieon_license_endpoint.bash"

dayoa_hiomrs_error() {
    echo "ERROR: $1" >&2
}

dayoa_hiomrs_require_executable() {
    local label="$1"
    local executable="$2"

    if [[ -z "$executable" ]]; then
        dayoa_hiomrs_error "$label executable is not configured."
        return 64
    fi
    if [[ "$executable" == */* ]]; then
        if [[ ! -x "$executable" ]]; then
            dayoa_hiomrs_error "$label executable is unavailable."
            return 127
        fi
    elif ! command -v "$executable" >/dev/null 2>&1; then
        dayoa_hiomrs_error "$label executable is unavailable."
        return 127
    fi
}

dayoa_hiomrs_extract_version() {
    local output="$1"
    local pattern='[0-9]+([.][0-9]+){1,3}'

    if [[ "$output" =~ $pattern ]]; then
        printf '%s\n' "${BASH_REMATCH[0]}"
        return 0
    fi
    return 1
}

dayoa_hiomrs_capture_version() {
    local label="$1"
    shift
    local output
    local version

    if ! output="$("$@" 2>&1)"; then
        dayoa_hiomrs_error "$label version probe failed."
        return 70
    fi
    if ! version="$(dayoa_hiomrs_extract_version "$output")"; then
        dayoa_hiomrs_error "$label returned no parseable version."
        return 65
    fi
    printf '%s\n' "$version"
}

dayoa_hiomrs_version_at_least() {
    local actual="$1"
    local minimum="$2"
    local IFS=.
    local -a actual_parts
    local -a minimum_parts
    local index
    local actual_part
    local minimum_part
    local actual_number
    local minimum_number

    read -r -a actual_parts <<< "$actual"
    read -r -a minimum_parts <<< "$minimum"
    for index in 0 1 2 3; do
        actual_part="${actual_parts[$index]:-0}"
        minimum_part="${minimum_parts[$index]:-0}"
        if [[ ! "$actual_part" =~ ^[0-9]+$ || ! "$minimum_part" =~ ^[0-9]+$ ]]; then
            return 1
        fi
        actual_number=$((10#$actual_part))
        minimum_number=$((10#$minimum_part))
        if (( actual_number > minimum_number )); then
            return 0
        fi
        if (( actual_number < minimum_number )); then
            return 1
        fi
    done
    return 0
}

dayoa_hiomrs_check_exact() {
    local label="$1"
    local expected="$2"
    shift 2
    local actual

    actual="$(dayoa_hiomrs_capture_version "$label" "$@")" || return
    if [[ "$actual" != "$expected" ]]; then
        dayoa_hiomrs_error "$label version $actual does not match required $expected."
        return 65
    fi
    printf 'HIOMRS preflight: %s=%s\n' "$label" "$actual"
}

dayoa_hiomrs_check_series() {
    local label="$1"
    local expected_series="$2"
    shift 2
    local actual

    actual="$(dayoa_hiomrs_capture_version "$label" "$@")" || return
    if [[ "$actual" != "$expected_series" && "$actual" != "$expected_series".* ]]; then
        dayoa_hiomrs_error "$label version $actual is outside required $expected_series.x."
        return 65
    fi
    printf 'HIOMRS preflight: %s=%s\n' "$label" "$actual"
}

dayoa_hiomrs_check_minimum() {
    local label="$1"
    local minimum="$2"
    shift 2
    local actual

    actual="$(dayoa_hiomrs_capture_version "$label" "$@")" || return
    if ! dayoa_hiomrs_version_at_least "$actual" "$minimum"; then
        dayoa_hiomrs_error "$label version $actual is below required $minimum."
        return 65
    fi
    printf 'HIOMRS preflight: %s=%s\n' "$label" "$actual"
}

dayoa_hiomrs_check_asset() {
    local label="$1"
    local path="$2"

    if [[ ! -s "$path" ]]; then
        dayoa_hiomrs_error "$label model bundle is unavailable or empty."
        return 66
    fi
    printf 'HIOMRS preflight: model=%s status=ok\n' "$label"
}

dayoa_hiomrs_check_segdup_population_data() {
    local python_bin="$1"
    local probe

    read -r -d '' probe <<'PY' || true
from importlib.resources import files
from pathlib import Path

name = "segdup_pop-population-hprc-v2.0_gnomad-v4.1.0-20251216.vcf.gz"
base = files("genecaller").joinpath("data", "pop_vcfs")
for resource in (base.joinpath(name), base.joinpath(name + ".tbi")):
    path = Path(str(resource))
    if not path.is_file() or path.stat().st_size <= 0:
        raise SystemExit(1)
PY
    if ! "$python_bin" -c "$probe" >/dev/null 2>&1; then
        dayoa_hiomrs_error "segdup-caller pinned population VCF or index is unavailable."
        return 66
    fi
    printf 'HIOMRS preflight: segdup-population-vcf=status=ok\n'
}

dayoa_hiomrs_validate_license_endpoint() {
    if ! dayoa_validate_sentieon_license_endpoint "${SENTIEON_LICENSE:-}"; then
        return 3
    fi
    printf 'HIOMRS preflight: license=server endpoint-shape=valid\n'
}

dayoa_hiomrs_configure_runtime

sentieon_bin="$DAYOA_HIOMRS_SENTIEON_ROOT/bin/sentieon"
sentieon_cli_bin="${DAYOA_HIOMRS_SENTIEON_CLI_BIN:-sentieon-cli}"
python_bin="${DAYOA_HIOMRS_PYTHON_BIN:-python}"
bcftools_bin="${DAYOA_HIOMRS_BCFTOOLS_BIN:-bcftools}"
samtools_bin="${DAYOA_HIOMRS_SAMTOOLS_BIN:-samtools}"
bedtools_bin="${DAYOA_HIOMRS_BEDTOOLS_BIN:-bedtools}"
multiqc_bin="${DAYOA_HIOMRS_MULTIQC_BIN:-multiqc}"
mosdepth_bin="${DAYOA_HIOMRS_MOSDEPTH_BIN:-mosdepth}"
segdup_bin="${DAYOA_HIOMRS_SEGDUP_BIN:-segdup-caller}"
expansionhunter_bin="${DAYOA_HIOMRS_EXPANSIONHUNTER_BIN:-ExpansionHunter}"

dayoa_hiomrs_require_executable "Sentieon Genomics" "$sentieon_bin"
dayoa_hiomrs_require_executable "sentieon-cli" "$sentieon_cli_bin"
dayoa_hiomrs_require_executable "Python" "$python_bin"
dayoa_hiomrs_require_executable "bcftools" "$bcftools_bin"
dayoa_hiomrs_require_executable "samtools" "$samtools_bin"
dayoa_hiomrs_require_executable "bedtools" "$bedtools_bin"
dayoa_hiomrs_require_executable "MultiQC" "$multiqc_bin"
dayoa_hiomrs_require_executable "mosdepth" "$mosdepth_bin"
dayoa_hiomrs_require_executable "segdup-caller" "$segdup_bin"
dayoa_hiomrs_require_executable "ExpansionHunter" "$expansionhunter_bin"

dayoa_hiomrs_check_exact "sentieon" "202503.03" "$sentieon_bin" licsrvr --version
dayoa_hiomrs_check_exact "sentieon-cli" "1.6.3" "$sentieon_cli_bin" --version
dayoa_hiomrs_check_series "python" "3.11" "$python_bin" --version
dayoa_hiomrs_check_minimum "bcftools" "1.22" "$bcftools_bin" --version
dayoa_hiomrs_check_minimum "samtools" "1.16" "$samtools_bin" --version
bedtools_version="$(dayoa_hiomrs_capture_version "bedtools" "$bedtools_bin" --version)"
printf 'HIOMRS preflight: bedtools=%s\n' "$bedtools_version"
dayoa_hiomrs_check_minimum "multiqc" "1.18" "$multiqc_bin" --version
dayoa_hiomrs_check_minimum "mosdepth" "0.2.6" "$mosdepth_bin" --version
dayoa_hiomrs_check_exact \
    "segdup-caller" \
    "0.8.0" \
    "$python_bin" \
    -c \
    'from importlib.metadata import version; print(version("segdup-caller"))'
dayoa_hiomrs_check_exact "ExpansionHunter" "5.0.0" "$expansionhunter_bin" --version

dayoa_hiomrs_check_asset \
    "HybridIlluminaONT2.0.bundle" \
    "$DAYOA_HIOMRS_SENTIEON_ROOT/bundles/HybridIlluminaONT2.0.bundle"
dayoa_hiomrs_check_asset \
    "SentieonIlluminaWGS2.2.bundle" \
    "$DAYOA_HIOMRS_SENTIEON_ROOT/bundles/SentieonIlluminaWGS2.2.bundle"
dayoa_hiomrs_check_asset \
    "DNAscopeONT2.3.bundle" \
    "$DAYOA_HIOMRS_SENTIEON_ROOT/bundles/DNAscopeONT2.3.bundle"
dayoa_hiomrs_check_segdup_population_data "$python_bin"

dayoa_hiomrs_validate_license_endpoint
printf 'HIOMRS preflight: status=ok\n'
