#!/bin/bash
############################################################
### Helper script to build/clean/open PEM Doxygen docs   ###
############################################################
set -e
trap 'echo -e "\033[31mError: an issue occurred in the script on line $LINENO.\033[0m"' ERR

usage() {
cat << 'EOF'
Usage: ./doc/build_doc.sh [options]

Options:
  --build                Build documentation (default action).
  --clean                Remove generated documentation under doc/doxygen.
  --check-deps           Check required tools (doxygen required, dot optional).
  --open                 Open generated index in a browser after build.
    --strict-warnings      Fail if warnings exceed profile baseline counts.
    --warnings-baseline <dir>
                                                 Baseline directory (default: doc/doxygen/warnings-baseline).
    --update-warnings-baseline
                                                 Update baseline counts from current warning logs.
  --profile <name>       Build profile: mars | generic | all (default: all).
  --help                 Show this help and exit.

Examples:
    ./doc/build_doc.sh
    ./doc/build_doc.sh --clean
    ./doc/build_doc.sh --check-deps
    ./doc/build_doc.sh --profile generic
    ./doc/build_doc.sh --strict-warnings
    ./doc/build_doc.sh --update-warnings-baseline
    ./doc/build_doc.sh --profile all --open
EOF
}

check_deps() {
    if ! command -v doxygen >/dev/null 2>&1; then
        echo "Error: doxygen not found in PATH."
        return 1
    fi

    if command -v dot >/dev/null 2>&1; then
        echo "Dependency check: doxygen found, graphviz (dot) found."
    else
        echo "Dependency check: doxygen found, graphviz (dot) not found (graphs may be limited)."
    fi
}

warning_count() {
    local log_file="$1"
    if [[ ! -f "$log_file" ]]; then
        echo 0
        return 0
    fi
    grep -Eic 'warning:' "$log_file" || true
}

update_warning_baseline() {
    local profile="$1"
    local current_count="$2"
    local baseline_file="${WARNINGS_BASELINE_DIR}/${profile}.count"

    mkdir -p "$WARNINGS_BASELINE_DIR"
    printf "%s\n" "$current_count" > "$baseline_file"
    echo "Updated warning baseline: ${baseline_file} = ${current_count}"
}

check_warning_gate() {
    local profile="$1"
    local current_count="$2"
    local baseline_file="${WARNINGS_BASELINE_DIR}/${profile}.count"
    local baseline_count

    if [[ ! -f "$baseline_file" ]]; then
        echo "Error: warning baseline not found for profile '${profile}': ${baseline_file}"
        echo "Create it with: ./doc/build_doc.sh --profile ${profile} --update-warnings-baseline"
        return 1
    fi

    baseline_count="$(tr -d '[:space:]' < "$baseline_file")"
    if ! [[ "$baseline_count" =~ ^[0-9]+$ ]]; then
        echo "Error: invalid warning baseline value in '${baseline_file}': '${baseline_count}'"
        return 1
    fi

    if (( current_count > baseline_count )); then
        echo "Error: warning regression for profile '${profile}' (current=${current_count}, baseline=${baseline_count})."
        return 1
    fi

    if (( current_count < baseline_count )); then
        echo "Info: warning count improved for profile '${profile}' (current=${current_count}, baseline=${baseline_count})."
    fi

    echo "Warning gate passed for profile '${profile}' (current=${current_count}, baseline=${baseline_count})."
}

build_profile() {
    local profile="$1"
    local output_dir input_cfg exclude_cfg index_path tmp_doxy warning_log warn_count

    case "$profile" in
        mars)
            output_dir="doc/doxygen/mars"
            input_cfg="README.md doc/DOXYGEN_MAINPAGE.md src/common src/mars"
            exclude_cfg=""
            index_path="doc/doxygen/mars/html/index.html"
            ;;
        generic)
            output_dir="doc/doxygen/generic"
            input_cfg="README.md doc/DOXYGEN_MAINPAGE.md src/common src/generic"
            exclude_cfg="src/common/surf_temp.F90"
            index_path="doc/doxygen/generic/html/index.html"
            ;;
        *)
            echo "Error: unknown profile '$profile'."
            return 1
            ;;
    esac

    tmp_doxy="$(mktemp)"
    cp doc/Doxyfile "$tmp_doxy"
    sed -i "s|^INPUT .*|INPUT                  = ${input_cfg}|" "$tmp_doxy"
    sed -i "s|^EXCLUDE .*|EXCLUDE                = ${exclude_cfg}|" "$tmp_doxy"
    sed -i "s|^OUTPUT_DIRECTORY .*|OUTPUT_DIRECTORY       = ${output_dir}|" "$tmp_doxy"
    sed -i "s|^WARN_LOGFILE .*|WARN_LOGFILE           = ${output_dir}/warnings.log|" "$tmp_doxy"

    mkdir -p "$output_dir"
    rm -f "${output_dir}/warnings.log"
    doxygen "$tmp_doxy"
    rm -f "$tmp_doxy"

    warning_log="${output_dir}/warnings.log"
    warn_count="$(warning_count "$warning_log")"
    echo "Warnings for profile '${profile}': ${warn_count}"

    if [[ "$UPDATE_WARNINGS_BASELINE" -eq 1 ]]; then
        update_warning_baseline "$profile" "$warn_count"
    fi

    if [[ "$STRICT_WARNINGS" -eq 1 ]]; then
        check_warning_gate "$profile" "$warn_count"
    fi

    echo "Built profile '$profile': ${index_path}"
}

open_index() {
    local profile="$1"
    local index_path

    case "$profile" in
        mars|all)
            index_path="doc/doxygen/mars/html/index.html"
            ;;
        generic)
            index_path="doc/doxygen/generic/html/index.html"
            ;;
        *)
            echo "Error: unknown profile '$profile'."
            return 1
            ;;
    esac

    if [[ ! -f "$index_path" ]]; then
        echo "Error: cannot open missing file '$index_path'."
        return 1
    fi

    if command -v xdg-open >/dev/null 2>&1; then
        xdg-open "$index_path" >/dev/null 2>&1 || true
    elif command -v open >/dev/null 2>&1; then
        open "$index_path" >/dev/null 2>&1 || true
    else
        echo "No opener found. Open manually: $index_path"
        return 0
    fi

    echo "Opened: $index_path"
}

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
cd "$PROJECT_ROOT"

DO_BUILD=0
DO_CLEAN=0
DO_CHECK_DEPS=0
DO_OPEN=0
STRICT_WARNINGS=0
UPDATE_WARNINGS_BASELINE=0
WARNINGS_BASELINE_DIR="doc/doxygen/warnings-baseline"
PROFILE="all"

while [[ $# -gt 0 ]]; do
    case "$1" in
        --build)
            DO_BUILD=1
            ;;
        --clean)
            DO_CLEAN=1
            ;;
        --check-deps)
            DO_CHECK_DEPS=1
            ;;
        --open)
            DO_OPEN=1
            DO_BUILD=1
            ;;
        --strict-warnings)
            STRICT_WARNINGS=1
            DO_BUILD=1
            ;;
        --warnings-baseline)
            shift
            WARNINGS_BASELINE_DIR="${1:-}"
            if [[ -z "$WARNINGS_BASELINE_DIR" ]]; then
                echo "Error: --warnings-baseline requires a directory path."
                usage
                exit 1
            fi
            ;;
        --update-warnings-baseline)
            UPDATE_WARNINGS_BASELINE=1
            DO_BUILD=1
            ;;
        --profile)
            shift
            PROFILE="${1:-}"
            if [[ -z "$PROFILE" ]]; then
                echo "Error: --profile requires a value (mars, generic, or all)."
                usage
                exit 1
            fi
            ;;
        --help)
            usage
            exit 0
            ;;
        *)
            echo "Error: unknown option '$1'"
            usage
            exit 1
            ;;
    esac
    shift
done

if [[ "$PROFILE" != "mars" && "$PROFILE" != "generic" && "$PROFILE" != "all" ]]; then
    echo "Error: invalid profile '$PROFILE'. Use mars, generic, or all."
    exit 1
fi

if [[ "$DO_BUILD" -eq 0 && "$DO_CLEAN" -eq 0 && "$DO_CHECK_DEPS" -eq 0 && "$DO_OPEN" -eq 0 ]]; then
    DO_BUILD=1
fi

if [[ "$DO_CHECK_DEPS" -eq 1 ]]; then
    check_deps
fi

if [[ "$DO_CLEAN" -eq 1 ]]; then
    if [[ "$WARNINGS_BASELINE_DIR" == doc/doxygen/* && -d "$WARNINGS_BASELINE_DIR" ]]; then
        local_tmp_baseline_dir="$(mktemp -d)"
        mkdir -p "$local_tmp_baseline_dir/warnings-baseline"
        cp -a "$WARNINGS_BASELINE_DIR"/. "$local_tmp_baseline_dir/warnings-baseline/" 2>/dev/null || true
        rm -rf doc/doxygen
        mkdir -p "$WARNINGS_BASELINE_DIR"
        cp -a "$local_tmp_baseline_dir/warnings-baseline"/. "$WARNINGS_BASELINE_DIR/" 2>/dev/null || true
        rm -rf "$local_tmp_baseline_dir"
        echo "Removed generated documentation directory: doc/doxygen (preserved ${WARNINGS_BASELINE_DIR})"
    else
        rm -rf doc/doxygen
        echo "Removed generated documentation directory: doc/doxygen"
    fi
fi

if [[ "$DO_BUILD" -eq 1 ]]; then
    if [[ "$DO_CHECK_DEPS" -eq 0 ]]; then
        check_deps
    fi

    if [[ "$PROFILE" == "all" ]]; then
        build_profile mars
        build_profile generic
    else
        build_profile "$PROFILE"
    fi
fi

if [[ "$DO_OPEN" -eq 1 ]]; then
    open_index "$PROFILE"
fi
