#!/bin/bash

# When installed via pip, the structure is flat inside site-packages/ontobdc
# MODULE_ROOT is .../ontobdc
MODULE_ROOT="$(
    PYTHONPATH="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd):${PYTHONPATH:-}" \
        python3 -c "from ontobdc.cli import get_root_dir; print(get_root_dir())" 2>/dev/null
)"

SCRIPT_DIR="$(
    PYTHONPATH="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd):${PYTHONPATH:-}" \
        python3 -c "from ontobdc.cli import get_script_dir; print(get_script_dir())" 2>/dev/null
)"

MESSAGE_BOX="${SCRIPT_DIR}/cli/message_box.sh"

# Define paths
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
WHITE='\033[1;37m'
RESET='\033[0m'
FULL_HLINE="----------------------------------------"

DEFAULT_CONFIG_JSON="${SCRIPT_DIR}/check/config.json"

CONFIG_JSON="${MODULE_ROOT}/.__ontobdc__/check.json"
if [ ! -f "${CONFIG_JSON}" ]; then
    CONFIG_JSON="${DEFAULT_CONFIG_JSON}"
fi

CONFIG_VALID=$(python3 -c "import json, sys
p='${CONFIG_JSON}'
try:
    with open(p) as f:
        data = json.load(f) or {}
except Exception:
    print('0')
    sys.exit(0)
base = data.get('base', None)
print('1' if isinstance(base, dict) and len(base) > 0 else '0')" 2>/dev/null)

if [ -f "${MESSAGE_BOX}" ]; then
    source "${MESSAGE_BOX}"
else
    # Fallback if message_box is missing
    # echo "Warning: message_box.sh not found at ${MESSAGE_BOX}"
    print_message_box() {
        echo "[$1] $2: $3"
        echo -e "$4"
    }
fi

if [ -f "${MESSAGE_BOX}" ]; then
    # Define FULL_HLINE if sourced from message_box (if it's not defined there)
    # message_box.sh doesn't define FULL_HLINE, but it defines colors.
    # We should ensure colors are available or redefined here if needed, 
    # but sourcing message_box should provide them.
    # However, message_box.sh defines colors as BOLD='\033[1m', etc.
    # Let's just redefine FULL_HLINE here to be safe.
    FULL_HLINE="----------------------------------------"
fi

REPAIR_MODE=false
SCOPE="all"

while [[ "$#" -gt 0 ]]; do
    case $1 in
        --repair) REPAIR_MODE=true ;;
        --scope) SCOPE="$2"; shift ;;
        *) ;;
    esac
    shift
done

echo ""
echo -e "${GRAY}${FULL_HLINE}${RESET}"
echo -e "${CYAN}Running System Checks...${RESET}"
echo -e "${GRAY}${FULL_HLINE}${RESET}"
echo ""

ERRORS=()
WARNINGS=()

run_checks() {
    local DIR="$1"
    local NAME="$2"
    local ENGINE="$3"

    if [ ! -f "$CONFIG_JSON" ]; then
         echo -e "  ${RED}✗ Config file not found: ${CONFIG_JSON}${RESET}"
         ERRORS+=("Config file missing")
         return
    fi

    # Parse JSON using python
    # Get base checks
    BASE_CHECKS=$(python3 -c "import json; import sys; 
try:
    with open('$CONFIG_JSON') as f: data = json.load(f);
    print(' '.join(data.get('base', {}).get('$NAME', [])))
except Exception as e: print(e, file=sys.stderr)")

    # Get engine specific checks
    ENGINE_CHECKS=$(python3 -c "import json; import sys; 
try:
    with open('$CONFIG_JSON') as f: data = json.load(f);
    print(' '.join(data.get('engines', {}).get('$ENGINE', {}).get('$NAME', [])))
except Exception as e: print(e, file=sys.stderr)")

    if [ -z "$BASE_CHECKS" ] && [ -z "$ENGINE_CHECKS" ]; then
        echo -e "  ${GRAY}• No checks found for $NAME in $ENGINE${RESET}"
        return
    fi

    run_check_list() {
        local CHECKS="$1"
        for check_name in $CHECKS; do
            if [[ "$check_name" == *.* ]]; then
                check_path="${check_name//./\/}"
                check_path="${check_path//\\/}"
                check_script="$MODULE_ROOT/$check_path/init.sh"
            else
                check_path="$check_name"
                check_script="$DIR/$check_path/init.sh"
            fi
            
            if [ -f "$check_script" ]; then
                DESCRIPTION=""
                unset -f check
                unset -f repair
                unset -f hotfix
                
                # shellcheck disable=SC1090
                source "$check_script"
                
                if [ -z "$DESCRIPTION" ]; then
                    DESCRIPTION="$check_name"
                fi

                check
                RET_CODE=$?

                if [ $RET_CODE -eq 0 ]; then
                     echo -e "  ${GREEN}✓ ${DESCRIPTION}${RESET}"
                else
                     IS_FATAL=false
                     if [ $RET_CODE -eq 2 ]; then
                        IS_FATAL=true
                     fi

                     HOTFIXED=false
                     if type hotfix &>/dev/null; then
                         if hotfix; then
                             if check; then
                                 echo -e "  ${GREEN}✓ ${DESCRIPTION} (Hotfixed)${RESET}"
                                 WARNINGS+=("${DESCRIPTION} (Hotfixed)")
                                 HOTFIXED=true
                             fi
                         fi
                     fi

                     if [ "$HOTFIXED" = false ]; then
                         if [ "$IS_FATAL" = true ]; then
                             echo -e "  ${RED}✗ ${DESCRIPTION} (FATAL)${RESET}"
                             if type repair &>/dev/null; then
                                 repair
                             else
                                 echo -e "${RED}FATAL ERROR: ${DESCRIPTION} failed and no repair available.${RESET}"
                                 exit 1
                             fi
                         fi

                         if [ "$REPAIR_MODE" = true ]; then
                             echo -e "  ${YELLOW}⚡ Attempting repair for: ${DESCRIPTION}...${RESET}"
                             if type repair &>/dev/null; then
                                 repair
                                 
                                 check
                                 if [ $? -eq 0 ]; then
                                     echo -e "  ${GREEN}✓ ${DESCRIPTION} (Repaired)${RESET}"
                                     WARNINGS+=("${DESCRIPTION} (Repaired)")
                                 else
                                     echo -e "  ${RED}✗ ${DESCRIPTION} (Repair failed)${RESET}"
                                     ERRORS+=("${DESCRIPTION}")
                                 fi
                             else
                                 echo -e "  ${RED}✗ ${DESCRIPTION} (No repair function)${RESET}"
                                 ERRORS+=("${DESCRIPTION}")
                             fi
                         else
                             echo -e "  ${RED}✗ ${DESCRIPTION}${RESET}"
                             ERRORS+=("${DESCRIPTION}")
                         fi
                     fi
                fi
            else
                 echo -e "  ${YELLOW}Warning: Check script not found: $check_script${RESET}"
            fi
        done
    }

    if [ -n "$BASE_CHECKS" ]; then
        echo -e "${YELLOW}❯ ${WHITE}Checking ${CYAN}Base${RESET}"
        run_check_list "$BASE_CHECKS"
    fi

    if [ -n "$ENGINE_CHECKS" ]; then
        echo ""
        echo -e "${YELLOW}❯ ${WHITE}Checking ${CYAN}Engine: ${ENGINE}${RESET}"
        run_check_list "$ENGINE_CHECKS"
    fi
}

# Determine Engine
# Try to load from .__ontobdc__/config.yaml
CONFIG_YAML=".__ontobdc__/config.yaml"
ENGINE="venv" # Default fallback

if [ -f "$CONFIG_YAML" ]; then
    DETECTED_ENGINE=$(python3 -c "import re
p='$CONFIG_YAML'
engine=''
try:
    import yaml
    with open(p) as f:
        c = yaml.safe_load(f) or {}
    engine = (c or {}).get('engine', '') or ''
except Exception:
    try:
        with open(p) as f:
            for line in f:
                m = re.match(r'^\\s*engine\\s*:\\s*(\\S+)\\s*$', line)
                if m:
                    engine = m.group(1)
                    break
    except Exception:
        engine = ''
print(engine)")
    if [ ! -z "$DETECTED_ENGINE" ]; then
        ENGINE="$DETECTED_ENGINE"
    fi
elif [ -d "/content" ]; then
    # Heuristic for colab if config doesn't exist
    ENGINE="colab"
fi

if [ ! -f "$CONFIG_JSON" ]; then
    echo -e "  ${RED}✗ Config file not found: ${CONFIG_JSON}${RESET}"
    exit 1
fi

CONFIG_ENGINES=$(python3 -c "import json; 
with open('$CONFIG_JSON') as f: data = json.load(f); 
print(' '.join((data.get('config', {}) or {}).get('engines', [])))" 2>/dev/null)

if [ -n "$CONFIG_ENGINES" ]; then
    ENGINE_ALLOWED=false
    for e in $CONFIG_ENGINES; do
        if [ "$e" = "$ENGINE" ]; then
            ENGINE_ALLOWED=true
            break
        fi
    done
    if [ "$ENGINE_ALLOWED" = false ]; then
        ENGINE="$(echo "$CONFIG_ENGINES" | awk '{print $1}')"
    fi
fi

if [[ "$SCOPE" == "all" ]]; then
    SCOPES=$(python3 -c "import json; 
with open('$CONFIG_JSON') as f: data = json.load(f); 
print(' '.join((data.get('base', {}) or {}).keys()))" 2>/dev/null)
else
    SCOPES="$SCOPE"
fi

for scope_name in $SCOPES; do
    CHECK_DIR="${SCRIPT_DIR}/check/${scope_name}"
    if [[ -d "${CHECK_DIR}" ]]; then
        run_checks "${CHECK_DIR}" "${scope_name}" "$ENGINE"
    else
        ERRORS+=("Checks directory not found: ${CHECK_DIR}")
    fi
done

# if [ -z "$VIRTUAL_ENV" ] && [ -f "venv/bin/activate" ]; then
#     # shellcheck disable=SC1091
#     source "venv/bin/activate"
# fi

echo ""

if [ ${#ERRORS[@]} -eq 0 ]; then
    MSG="All checks passed."
    if [ ${#WARNINGS[@]} -gt 0 ]; then
        MSG="${MSG}\n\nWarnings:"
        for w in "${WARNINGS[@]}"; do
            MSG="${MSG}\n• $w"
        done
    fi
    if type print_message_box &>/dev/null; then
        print_message_box "GREEN" "Success" "System Operational" "$MSG"
    else
        echo -e "${GREEN}Success: System Operational${RESET}\n$MSG"
    fi
else
    MSG="The following checks failed:"
    for e in "${ERRORS[@]}"; do
        MSG="${MSG}\n• $e"
    done
    
    if [ ${#WARNINGS[@]} -gt 0 ]; then
        MSG="${MSG}\n\nWarnings:"
        for w in "${WARNINGS[@]}"; do
            MSG="${MSG}\n• $w"
        done
    fi
    
    if type print_message_box &>/dev/null; then
        print_message_box "RED" "Error" "System Check Failed" "$MSG"
    else
        echo -e "${RED}Error: System Check Failed${RESET}\n$MSG"
    fi
    exit 1
fi
