#!/bin/bash
set -euo pipefail
ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ZARYA_DIR}/lib/common.sh"
COMMAND="${1:-help}"

parse_run_targets() {
    local raw_input="$*"
    local normalized
    normalized=$(echo "${raw_input}" | tr ',' ' ')
    local targets=()
    for item in ${normalized}; do
        if [[ "${item}" =~ ^([0-9]+)-([0-9]+)$ ]]; then
            local start="${BASH_REMATCH[1]}"
            local end="${BASH_REMATCH[2]}"
            for ((i=10#$start; i<=10#$end; i++)); do
                targets+=($(printf "%02d" "${i}"))
            done
        elif [[ "${item}" =~ ^[0-9]+$ ]]; then
            targets+=($(printf "%02d" "$((10#$item))"))
        else
            log_err "Некорректный идентификатор плейбука: '${item}'"
            exit 1
        fi
    done
    printf "%s\n" "${targets[@]}" | sort -u -n
}

resolve_playbook() {
    local id="$1"
    local found
    found=$(find "${REPO_ROOT}/ansible/playbooks" -maxdepth 1 -name "${id}_*.yml" | head -n1)
    if [[ -z "${found}" ]]; then
        log_err "Плейбук с префиксом [${id}] не найден в ansible/playbooks/"
        exit 1
    fi
    echo "${found}"
}

print_playbooks_catalog() {
    echo -e "${BLUE}=== Каталог доступных плейбуков (ansible/playbooks/) ===${NC}"
    printf "%-4s %-28s %-12s %s\n" "ID" "PLAYBOOK" "HOSTS" "DESCRIPTION"
    echo "----------------------------------------------------------------------------------"
    for pb in $(ls -1 "${REPO_ROOT}/ansible/playbooks"/[0-9][0-9]_*.yml 2>/dev/null | sort); do
        local file_name
        file_name=$(basename "${pb}")
        local id="${file_name:0:2}"
        local hosts
        hosts=$(awk '/hosts:/ {print $2; exit}' "${pb}" | tr -d '"'"'")
        local desc
        desc=$(awk '/- name:/ {print substr($0, index($0,$3)); exit}' "${pb}")
        printf "%-4s %-28s %-12s %s\n" "${id}" "${file_name%.yml}" "${hosts}" "${desc}"
    done
}

case "${COMMAND}" in
    git-credential)
        if [[ -f "${RAM_CACHE}" ]]; then
            token=$(grep '^export ATLAS_PUSH_TOKEN=' "${RAM_CACHE}" 2>/dev/null | cut -d= -f2- | tr -d '"'\'' ' || true)
            if [[ -n "${token}" ]]; then
                echo "username=atlas"
                echo "password=${token}"
            fi
        fi
        exit 0
        ;;
    start|login)
        shift || true
        hours="${1:-1}"
        if ! [[ "${hours}" =~ ^[0-9]+$ ]] || (( hours < 0 || hours > 24 )); then
            log_err "Недопустимый TTL сессии: '${hours}'. Допустимо: 0 (бессрочно) или 1-24 (часы)."
            exit 1
        fi
        ensure_prerequisites
        load_secrets_to_ram "${hours}"
        unseal_vault
        if [[ "${hours}" -eq 0 ]]; then
            log_ok "Рабочая сессия Sovereign C2 открыта (Бессрочно)."
        else
            log_ok "Рабочая сессия Sovereign C2 открыта (TTL: ${hours} ч)."
        fi
        ;;
    clean|logout)
        rm -f "${RAM_CACHE}" /dev/shm/.atlas_core
        log_ok "Секреты и SSH-ключи безопасно удалены из RAM."
        ;;
    unseal)
        ensure_prerequisites
        unseal_vault
        ;;
    up)
        shift || true
        target="${1:-all}"
        case "${target}" in
            host)  run_isolated "${ZARYA_DIR}/layers/00_host.sh" ;;
            net)   run_isolated "${ZARYA_DIR}/layers/01_net.sh" ;;
            tier0) run_isolated "${ZARYA_DIR}/layers/02_tier0.sh" ;;
            talos) run_isolated "${ZARYA_DIR}/layers/03_talos.sh" ;;
            apps)  "${ZARYA_DIR}/layers/04_apps.sh" ;;
            all)
                run_isolated "${ZARYA_DIR}/layers/00_host.sh"
                run_isolated "${ZARYA_DIR}/layers/01_net.sh"
                run_isolated "${ZARYA_DIR}/layers/02_tier0.sh"
                run_isolated "${ZARYA_DIR}/layers/03_talos.sh"
                "${ZARYA_DIR}/layers/04_apps.sh"
                log_ok "Вся инфраструктура полностью развернута."
                ;;
            *)
                log_err "Неизвестный слой: ${target}. Доступны: host, net, tier0, talos, apps, all"
                exit 1
                ;;
        esac
        ;;
    run)
        shift || true
        if [[ $# -eq 0 ]] || [[ "${1:-}" == "list" ]]; then
            print_playbooks_catalog
            exit 0
        fi
        targets=$(parse_run_targets "$*")
        log_info "Очередь выполнения плейбуков: $(echo ${targets} | tr '\n' ' ')"
        for id in ${targets}; do
            pb_path=$(resolve_playbook "${id}")
            log_info "==> [RUN ${id}] Исполнение: $(basename "${pb_path}")..."
            run_isolated ansible-playbook -i "${REPO_ROOT}/ansible/inventory.yml" "${pb_path}"
        done
        log_ok "Все выбранные плейбуки успешно выполнены."
        ;;
    exec)
        shift || true
        if [[ $# -eq 0 ]]; then
            log_err "Использование: dep exec <команда> [аргументы...]"
            exit 1
        fi
        run_isolated "$@"
        ;;
    a|apply)
        unseal_vault
        shift || true
        run_isolated bash -c "cd '${REPO_ROOT}/tofu' && tofu apply $*"
        ;;
    plan)
        shift || true
        run_isolated bash -c "cd '${REPO_ROOT}/tofu' && tofu plan $*"
        ;;
    tf)
        shift || true
        run_isolated bash -c "cd '${REPO_ROOT}/tofu' && tofu $*"
        ;;
    pods)
        shift || true
        kpods "$@"
        ;;
    sync)
        log_info "Принудительная конвергенция FluxCD..."
        flux reconcile source git atlas-repo
        flux reconcile kustomization infra-sync
        flux reconcile kustomization apps-sync
        log_ok "Синхронизация завершена."
        ;;
    gc)
        "${ZARYA_DIR}/layers/gc.sh"
        ;;
    state)
        shift || true
        target="${1:-all}"
        if [[ "${target}" == "--snapshot" ]]; then
            shift || true
            "${ZARYA_DIR}/state/collect_state.sh" "$@"
        else
            case "${target}" in
                host|pve)         bash "${ZARYA_DIR}/state/01_pve.sh" ;;
                net|vyos)         bash "${ZARYA_DIR}/state/03_vyos.sh" ;;
                vps|edge)         bash "${ZARYA_DIR}/state/02_vps.sh" ;;
                tier0)            bash "${ZARYA_DIR}/state/04_tier0.sh" ;;
                k8s|talos)        bash "${ZARYA_DIR}/state/05_k8s.sh" ;;
                workstation)      bash "${ZARYA_DIR}/state/00_workstation.sh" ;;
                all)
                    for mod in 00_workstation 01_pve 02_vps 03_vyos 04_tier0 05_k8s; do
                        bash "${ZARYA_DIR}/state/${mod}.sh"
                    done
                    ;;
                *)
                    log_err "Неизвестный таргет: ${target}. Доступны: host, net, vps, tier0, k8s, workstation, all"
                    exit 1
                    ;;
            esac
        fi
        ;;
    reset|nuke)
        "${ZARYA_DIR}/layers/reset.sh"
        ;;
    help|--help|-h)
        cat <<EOF
Sovereign C2 Orchestrator (dep)
Управление сессией:
  dep start [0-24]        Открытие смены (TTL в часах, по дефолту 1ч, 0 = бессрочно)
  dep clean               Закрытие смены (уничтожение RAM-кэша и ключа SSH)
  dep unseal              Ручной ансил OpenBao + синк токена в K8s
Исполнение и деплой:
  dep up [layer]          Сквозной макро-деплой: host, net, tier0, talos, apps, all
  dep run <selector>      Точечный запуск плейбуков: 06 | 01-03 | 01,03,06
  dep run list            Каталог всех плейбуков с описанием
  dep exec <команда...>   Вызов любого бинарника строго внутри RAM-изоляции run_isolated
Инфраструктура (IaC):
  dep a [-auto-approve]   OpenTofu apply с авто-ансилом Vault
  dep plan                OpenTofu plan
  dep tf <args...>        Прямой вызов OpenTofu в изолированном контексте
Кластер и состояние:
  dep pods [args...]      Просмотр подов через kpods (включая kpods -w)
  dep sync                Принудительный синк FluxCD
  dep gc                  Сборка мусора и сброс бэкоффа подов
  dep state [target]      Живой вывод статуса в терминал (host, net, vps, tier0, k8s, all)
  dep reset               Полное уничтожение инфраструктуры (MFA через YubiKey)
EOF
        ;;
    *)
        log_err "Неизвестная команда: ${COMMAND}. Используйте 'dep help' для справки."
        exit 1
        ;;
esac
