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

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

run_step() {
    local label="$1"
    shift

    printf '\n== %s ==\n' "${label}"
    "$@"
}

shell_files() {
    local path

    git -C "${REPO_ROOT}" ls-files | while IFS= read -r path; do
        case "${path}" in
            jeannie | *.sh)
                printf '%s\n' "${path}"
                ;;
            scripts/*)
                if head -n 1 "${REPO_ROOT}/${path}" | grep -Eq 'sh|bash'; then
                    printf '%s\n' "${path}"
                fi
                ;;
        esac
    done
}

validate_bash_syntax() {
    local files=()
    local file

    while IFS= read -r file; do
        files+=("${REPO_ROOT}/${file}")
    done < <(shell_files)

    if ((${#files[@]} == 0)); then
        echo "no shell files found"
        return 0
    fi
    bash -n "${files[@]}"
}

validate_shellcheck() {
    local files=()
    local file

    while IFS= read -r file; do
        files+=("${REPO_ROOT}/${file}")
    done < <(shell_files)

    if ! command -v shellcheck >/dev/null 2>&1; then
        echo "shellcheck not installed; skipping"
        return 0
    fi
    if ((${#files[@]} == 0)); then
        echo "no shell files found"
        return 0
    fi
    shellcheck "${files[@]}"
}

validate_yaml() {
    if command -v ruby >/dev/null 2>&1; then
        ruby -e 'require "yaml"; (Dir["**/*.yml"] + Dir["**/*.yaml"]).each { |path| next if path.start_with?(".git/"); YAML.load_stream(File.read(path)) }; puts "yaml parse ok"'
        return 0
    fi
    echo "ruby not installed; skipping generic YAML parse"
}

validate_tofu_fmt() {
    if ! command -v tofu >/dev/null 2>&1; then
        echo "tofu not installed; skipping fmt check"
        return 0
    fi
    tofu fmt -check -recursive "${REPO_ROOT}/bootstrap"
}

validate_go() {
    if ! command -v go >/dev/null 2>&1; then
        echo "go not installed; skipping Go checks"
        return 0
    fi
    test -z "$(gofmt -l "${REPO_ROOT}/cmd")"
    GOCACHE="${GOCACHE:-${REPO_ROOT}/.lab/go-build-cache}" go test ./...
}

validate_security_static() {
    "${REPO_ROOT}/scripts/validate-tailnet-policy"
    if command -v trivy >/dev/null 2>&1; then
        trivy config --quiet "${REPO_ROOT}"
    else
        echo "trivy not installed; skipping IaC security static scan"
    fi
}

validate_unit_tests() {
    "${REPO_ROOT}/tests/jeannie-unit"
}

main() {
    cd "${REPO_ROOT}"
    run_step "Inventory" "${REPO_ROOT}/scripts/validate-homelab-inventory" "${HOMELAB_INVENTORY_FILE:-${REPO_ROOT}/homelab.yml}"
    run_step "Unit tests" validate_unit_tests
    run_step "Generated docs" "${REPO_ROOT}/scripts/render-docs" --check
    run_step "Bash syntax" validate_bash_syntax
    run_step "Shellcheck" validate_shellcheck
    run_step "YAML parse" validate_yaml
    run_step "Go checks" validate_go
    run_step "OpenTofu formatting" validate_tofu_fmt
    run_step "Security static checks" validate_security_static
}

main "$@"
