#!/usr/bin/env bash
# =============================================================================
# Phase 11: Dependency Installation, Cluster Creation & Quickstart Tests
# =============================================================================
# Tests the first-time user experience: tool detection, cluster lifecycle,
# init wizard, and quickstart flow.
# =============================================================================

print_phase "Phase 11: Dependency Detection, Cluster Lifecycle & Quickstart"

# Save original kubecontext to restore later
ORIGINAL_CONTEXT=$(kubectl config current-context 2>/dev/null || echo "")

# =========================================================================
# Section A: Doctor Binary Checks (7 tests)
# =========================================================================
log_info "Section A: Doctor Binary Checks"

# P11-001: Doctor detects helm
run_test "P11-001" "Doctor detects helm binary" "$ILUM" doctor
assert_contains "helm" || true

# P11-002: Doctor detects kubectl
run_test "P11-002" "Doctor detects kubectl binary" "$ILUM" doctor
assert_contains "kubectl" || true

# P11-003: Doctor detects docker
run_test "P11-003" "Doctor detects docker binary" "$ILUM" doctor
assert_contains "docker" || true

# P11-004: Doctor JSON reports binary status
run_test "P11-004" "Doctor JSON output has binary checks" "$ILUM" --output json doctor
if [[ "$LAST_EXIT_CODE" -eq 0 ]] || [[ "$LAST_EXIT_CODE" -eq 1 ]]; then
    # Doctor may exit 1 if some checks fail (e.g. repo), but JSON should be valid
    assert_json_valid || true
else
    assert_exit_code 0 || true
fi

# P11-005: Doctor --failures-only hides passing binary checks
run_test "P11-005" "Doctor --failures-only hides passing checks" "$ILUM" doctor --failures-only
# helm/kubectl/docker should pass and thus NOT appear when --failures-only is set
# Note: they may still appear if version is too low, so we just check the flag works
assert_exit_code 0 || {
    # Exit code 1 means some checks failed (expected — e.g. repo/release)
    # That's fine, we just want the flag to be accepted
    if [[ "$LAST_EXIT_CODE" -eq 1 ]]; then
        PASSED_TESTS=$((PASSED_TESTS + 1))
        TOTAL_TESTS=$((TOTAL_TESTS - 1))  # undo the run_test increment since we handle manually
        print_pass "P11-005 — Doctor --failures-only flag accepted (exit 1 = some checks failed)"
    fi
    true
}

# P11-006: Doctor detects cluster connectivity
run_test "P11-006" "Doctor detects cluster connectivity" "$ILUM" doctor
assert_contains "cluster" || true

# P11-007: Doctor detects helm repo
run_test "P11-007" "Doctor shows helm repo check" "$ILUM" doctor
assert_contains_regex "repo|repository" || true

# =========================================================================
# Section B: Cluster Create & Delete (10 tests)
# =========================================================================
log_info "Section B: Cluster Create & Delete"

# P11-008: Cluster list discovers existing minikube cluster
run_test "P11-008" "Cluster list detects minikube cluster" "$ILUM" cluster list
assert_exit_code 0 || true
# The ilum-dev minikube cluster should be detected automatically
assert_contains "ilum-dev" || true
assert_contains "detected" || true

# P11-009: Cluster create with kind (not installed) — should fail
run_test "P11-009" "Cluster create kind fails (not installed)" "$ILUM" cluster create --provider kind --name test-p11-kind
if [[ "$LAST_EXIT_CODE" -ne 0 ]]; then
    PASSED_TESTS=$((PASSED_TESTS + 1))
    print_pass "P11-009 — Cluster create kind fails as expected (exit $LAST_EXIT_CODE)"
    echo "PASS" > "$TEST_LOG_DIR/P11-009/result.txt"
else
    FAILED_TESTS=$((FAILED_TESTS + 1))
    print_fail "P11-009 — Cluster create kind should fail (kind not installed)"
    echo "FAIL: expected non-zero exit" > "$TEST_LOG_DIR/P11-009/result.txt"
    FAILURES+=("P11-009 — Cluster create kind should fail: got exit 0")
    # Clean up if it somehow succeeded
    "$ILUM" cluster delete test-p11-kind 2>/dev/null || true
fi

# P11-010: Cluster create with k3d (not installed) — should fail
run_test "P11-010" "Cluster create k3d fails (not installed)" "$ILUM" cluster create --provider k3d --name test-p11-k3d
if [[ "$LAST_EXIT_CODE" -ne 0 ]]; then
    PASSED_TESTS=$((PASSED_TESTS + 1))
    print_pass "P11-010 — Cluster create k3d fails as expected (exit $LAST_EXIT_CODE)"
    echo "PASS" > "$TEST_LOG_DIR/P11-010/result.txt"
else
    FAILED_TESTS=$((FAILED_TESTS + 1))
    print_fail "P11-010 — Cluster create k3d should fail (k3d not installed)"
    echo "FAIL: expected non-zero exit" > "$TEST_LOG_DIR/P11-010/result.txt"
    FAILURES+=("P11-010 — Cluster create k3d should fail: got exit 0")
    "$ILUM" cluster delete test-p11-k3d 2>/dev/null || true
fi

# P11-011: Cluster create with invalid provider
run_test "P11-011" "Cluster create with invalid provider fails" "$ILUM" cluster create --provider invalid_provider
assert_exit_code_not 0 || true

# P11-012: Cluster create with minikube (dev preset)
run_test "P11-012" "Cluster create minikube (dev preset)" "$ILUM" cluster create --provider minikube --preset dev --name test-p11-mk
assert_exit_code 0 || {
    log_issue "BUG" "high" "P11-012" "Cluster create minikube failed with exit $LAST_EXIT_CODE: $(echo "$LAST_STDERR" | head -3)"
    true
}

# P11-013: Cluster list shows new cluster
run_test "P11-013" "Cluster list shows test-p11-mk" "$ILUM" cluster list
if [[ "$LAST_EXIT_CODE" -eq 0 ]]; then
    assert_contains "test-p11-mk" || true
else
    FAILED_TESTS=$((FAILED_TESTS + 1))
    print_fail "P11-013 — Cluster list failed (exit $LAST_EXIT_CODE)"
    echo "FAIL: cluster list failed" > "$TEST_LOG_DIR/P11-013/result.txt"
    FAILURES+=("P11-013 — Cluster list after create failed")
fi

# P11-014: Cluster delete the test cluster
run_test "P11-014" "Cluster delete test-p11-mk" "$ILUM" cluster delete test-p11-mk
assert_exit_code 0 || {
    log_issue "BUG" "high" "P11-014" "Cluster delete failed with exit $LAST_EXIT_CODE"
    # Force cleanup
    minikube delete --profile test-p11-mk 2>/dev/null || true
    true
}

# P11-015: Cluster list after delete — should not show test-p11-mk
run_test "P11-015" "Cluster list after delete" "$ILUM" cluster list
assert_not_contains "test-p11-mk" || true

# P11-016: Cluster delete nonexistent
run_test "P11-016" "Cluster delete nonexistent fails" "$ILUM" cluster delete nonexistent_xyz_999
assert_exit_code_not 0 || true

# P11-017: Cluster create with custom name
run_test "P11-017" "Cluster create minikube custom name" "$ILUM" cluster create --provider minikube --preset dev --name custom-e2e-test
assert_exit_code 0 || {
    log_issue "BUG" "medium" "P11-017" "Cluster create custom name failed with exit $LAST_EXIT_CODE"
    true
}

# Cleanup: delete custom cluster
log_info "Cleaning up custom-e2e-test cluster..."
"$ILUM" cluster delete custom-e2e-test 2>/dev/null || minikube delete --profile custom-e2e-test 2>/dev/null || true

# Restore original kubecontext
if [[ -n "$ORIGINAL_CONTEXT" ]]; then
    kubectl config use-context "$ORIGINAL_CONTEXT" 2>/dev/null || true
fi

# =========================================================================
# Section C: Init Wizard Non-Interactive (5 tests)
# =========================================================================
log_info "Section C: Init Wizard Non-Interactive"

# Back up config before init tests
backup_config

# P11-018: Init --yes runs non-interactively
run_test "P11-018" "Init --yes completes non-interactively" "$ILUM" init --yes
assert_exit_code 0 || {
    log_issue "BUG" "high" "P11-018" "Init --yes failed with exit $LAST_EXIT_CODE"
    true
}

# P11-019: Config show works after init
run_test "P11-019" "Config show works after init" "$ILUM" config show
assert_exit_code 0 || true

# P11-020: Init --yes with custom profile
run_test "P11-020" "Init --yes with custom profile" "$ILUM" init --yes --profile test-profile
assert_exit_code 0 || {
    log_issue "BUG" "medium" "P11-020" "Init --yes --profile test-profile failed"
    true
}

# P11-021: Config shows test-profile
run_test "P11-021" "Config contains test-profile" "$ILUM" config show
assert_contains "test-profile" || true

# P11-022: Init --yes is idempotent
run_test "P11-022" "Init --yes is idempotent" "$ILUM" init --yes
assert_exit_code 0 || true

# Restore config
restore_config

# =========================================================================
# Section D: Quickstart Command (8 tests)
# =========================================================================
log_info "Section D: Quickstart Command"

# P11-023: Quickstart --help
run_test "P11-023" "Quickstart --help shows options" "$ILUM" quickstart --help
assert_exit_code 0 || true
assert_contains "provider" || true

# P11-024: Quickstart with invalid provider
# The quickstart creates a ClusterProvider enum, which should fail for unknown values.
# But it only triggers if no cluster is reachable — since our cluster IS reachable,
# the provider is never used. We test that the option is accepted at least.
run_test "P11-024" "Quickstart with invalid provider" timeout 30 "$ILUM" quickstart --provider invalid_xyz
# With a reachable cluster, quickstart may proceed past provider selection.
# Without a reachable cluster, it should fail on ClusterProvider("invalid_xyz").
# Either outcome is acceptable — the key is it doesn't hang.
if [[ "$LAST_EXIT_CODE" -ne 0 ]]; then
    PASSED_TESTS=$((PASSED_TESTS + 1))
    print_pass "P11-024 — Quickstart with invalid provider errored as expected"
    echo "PASS" > "$TEST_LOG_DIR/P11-024/result.txt"
else
    # Exit 0 means it detected existing cluster and ignored the provider
    PASSED_TESTS=$((PASSED_TESTS + 1))
    print_pass "P11-024 — Quickstart with invalid provider (cluster detected, provider skipped)"
    echo "PASS" > "$TEST_LOG_DIR/P11-024/result.txt"
fi

# P11-025: Quickstart with invalid preset
run_test "P11-025" "Quickstart with invalid preset fails" timeout 30 "$ILUM" quickstart --preset nonexistent_preset
assert_exit_code_not 0 || {
    # If it somehow passed, it means the preset was ignored or default was used
    log_issue "UX" "medium" "P11-025" "Quickstart accepted invalid preset without error"
    true
}

# P11-026: Quickstart detects existing cluster
# Use timeout to prevent long-running helm install
run_test "P11-026" "Quickstart detects existing cluster" timeout 45 "$ILUM" quickstart --provider minikube
# Quickstart should get to at least step 2 (cluster detection) before timeout or install
COMBINED_OUTPUT="$LAST_STDOUT$LAST_STDERR"
if echo "$COMBINED_OUTPUT" | grep -qiE "cluster|preflight|prerequisite|step|reachable|install"; then
    PASSED_TESTS=$((PASSED_TESTS + 1))
    print_pass "P11-026 — Quickstart showed cluster detection output"
    echo "PASS" > "$TEST_LOG_DIR/P11-026/result.txt"
else
    FAILED_TESTS=$((FAILED_TESTS + 1))
    print_fail "P11-026 — Quickstart output missing cluster/preflight detection"
    echo "FAIL: output missing cluster detection" > "$TEST_LOG_DIR/P11-026/result.txt"
    FAILURES+=("P11-026 — Quickstart output missing cluster detection keywords")
fi

# P11-027: Quickstart with valid preset name
run_test "P11-027" "Quickstart with development preset" timeout 45 "$ILUM" quickstart --preset development
COMBINED_OUTPUT="$LAST_STDOUT$LAST_STDERR"
if echo "$COMBINED_OUTPUT" | grep -qiE "development|preset|module|profile|step|install"; then
    PASSED_TESTS=$((PASSED_TESTS + 1))
    print_pass "P11-027 — Quickstart with development preset produced expected output"
    echo "PASS" > "$TEST_LOG_DIR/P11-027/result.txt"
else
    FAILED_TESTS=$((FAILED_TESTS + 1))
    print_fail "P11-027 — Quickstart with development preset: unexpected output"
    echo "FAIL: missing expected keywords in output" > "$TEST_LOG_DIR/P11-027/result.txt"
    FAILURES+=("P11-027 — Quickstart development preset output missing keywords")
fi

# P11-028: Quickstart with --module flag
run_test "P11-028" "Quickstart with --module airflow" timeout 45 "$ILUM" quickstart --module airflow
COMBINED_OUTPUT="$LAST_STDOUT$LAST_STDERR"
if echo "$COMBINED_OUTPUT" | grep -qiE "airflow|module|step|install|prerequisite"; then
    PASSED_TESTS=$((PASSED_TESTS + 1))
    print_pass "P11-028 — Quickstart with --module airflow acknowledged extra module"
    echo "PASS" > "$TEST_LOG_DIR/P11-028/result.txt"
else
    FAILED_TESTS=$((FAILED_TESTS + 1))
    print_fail "P11-028 — Quickstart --module airflow: no acknowledgment in output"
    echo "FAIL: missing module acknowledgment" > "$TEST_LOG_DIR/P11-028/result.txt"
    FAILURES+=("P11-028 — Quickstart --module airflow: no module-related output")
fi

# P11-029: Quickstart with --timeout flag
run_test "P11-029" "Quickstart accepts --timeout flag" timeout 45 "$ILUM" quickstart --timeout 30m
# Just verify it doesn't error on the flag itself
COMBINED_OUTPUT="$LAST_STDOUT$LAST_STDERR"
if echo "$COMBINED_OUTPUT" | grep -qiE "step|install|cluster|prerequisite|quickstart"; then
    PASSED_TESTS=$((PASSED_TESTS + 1))
    print_pass "P11-029 — Quickstart accepted --timeout 30m"
    echo "PASS" > "$TEST_LOG_DIR/P11-029/result.txt"
else
    # Even if timeout killed it, if it started running that's fine
    if [[ "$LAST_EXIT_CODE" -eq 124 ]]; then
        PASSED_TESTS=$((PASSED_TESTS + 1))
        print_pass "P11-029 — Quickstart accepted --timeout 30m (killed by test timeout)"
        echo "PASS" > "$TEST_LOG_DIR/P11-029/result.txt"
    else
        FAILED_TESTS=$((FAILED_TESTS + 1))
        print_fail "P11-029 — Quickstart --timeout flag: unexpected behavior"
        echo "FAIL: unexpected output" > "$TEST_LOG_DIR/P11-029/result.txt"
        FAILURES+=("P11-029 — Quickstart --timeout flag: unexpected behavior (exit $LAST_EXIT_CODE)")
    fi
fi

# P11-030: Quickstart when release exists
run_test "P11-030" "Quickstart with existing release" timeout 60 "$ILUM" quickstart
COMBINED_OUTPUT="$LAST_STDOUT$LAST_STDERR"
if echo "$COMBINED_OUTPUT" | grep -qiE "install|upgrade|exist|release|step|quickstart|cluster"; then
    PASSED_TESTS=$((PASSED_TESTS + 1))
    print_pass "P11-030 — Quickstart handled existing release scenario"
    echo "PASS" > "$TEST_LOG_DIR/P11-030/result.txt"
else
    if [[ "$LAST_EXIT_CODE" -eq 124 ]]; then
        PASSED_TESTS=$((PASSED_TESTS + 1))
        print_pass "P11-030 — Quickstart ran (killed by test timeout after starting)"
        echo "PASS" > "$TEST_LOG_DIR/P11-030/result.txt"
    else
        FAILED_TESTS=$((FAILED_TESTS + 1))
        print_fail "P11-030 — Quickstart with existing release: no relevant output"
        echo "FAIL: no relevant output" > "$TEST_LOG_DIR/P11-030/result.txt"
        FAILURES+=("P11-030 — Quickstart existing release: no relevant output")
    fi
fi

# =========================================================================
# Section E: Tool Detection Edge Cases (5 tests)
# =========================================================================
log_info "Section E: Tool Detection Edge Cases"

# P11-031: Doctor with PATH manipulation (hide helm)
# Remove common tool locations to simulate missing helm
run_test "P11-031" "Doctor with restricted PATH (hide helm)" env PATH=/usr/bin:/bin "$ILUM" doctor
COMBINED_OUTPUT="$LAST_STDOUT$LAST_STDERR"
if echo "$COMBINED_OUTPUT" | grep -qiE "not found|fail|missing|FAIL"; then
    PASSED_TESTS=$((PASSED_TESTS + 1))
    print_pass "P11-031 — Doctor detected missing tools with restricted PATH"
    echo "PASS" > "$TEST_LOG_DIR/P11-031/result.txt"
else
    # The restricted PATH might still have helm in /usr/bin — check
    if command -v /usr/bin/helm &>/dev/null; then
        PASSED_TESTS=$((PASSED_TESTS + 1))
        print_pass "P11-031 — Doctor ran (helm is in /usr/bin, still found)"
        echo "PASS" > "$TEST_LOG_DIR/P11-031/result.txt"
    else
        FAILED_TESTS=$((FAILED_TESTS + 1))
        print_fail "P11-031 — Doctor did not detect missing tools with restricted PATH"
        echo "FAIL: no 'not found' in output" > "$TEST_LOG_DIR/P11-031/result.txt"
        FAILURES+=("P11-031 — Doctor did not detect missing tools with restricted PATH")
    fi
fi

# P11-032: Doctor with PATH manipulation (hide kubectl)
run_test "P11-032" "Doctor with restricted PATH (hide kubectl)" env PATH=/usr/bin:/bin "$ILUM" doctor
COMBINED_OUTPUT="$LAST_STDOUT$LAST_STDERR"
# Similar logic — just verify doctor runs and reports something
if [[ "$LAST_EXIT_CODE" -eq 0 ]] || [[ "$LAST_EXIT_CODE" -eq 1 ]]; then
    PASSED_TESTS=$((PASSED_TESTS + 1))
    print_pass "P11-032 — Doctor with restricted PATH ran (exit $LAST_EXIT_CODE)"
    echo "PASS" > "$TEST_LOG_DIR/P11-032/result.txt"
else
    FAILED_TESTS=$((FAILED_TESTS + 1))
    print_fail "P11-032 — Doctor with restricted PATH crashed (exit $LAST_EXIT_CODE)"
    echo "FAIL: unexpected exit code $LAST_EXIT_CODE" > "$TEST_LOG_DIR/P11-032/result.txt"
    FAILURES+=("P11-032 — Doctor crashed with restricted PATH (exit $LAST_EXIT_CODE)")
fi

# P11-033: Version flag works without cluster dependency
run_test "P11-033" "Version flag works independently" "$ILUM" --version
assert_exit_code 0 || true

# P11-034: Module list works without cluster (static data)
run_test "P11-034" "Module list works (static data, no cluster needed)" "$ILUM" module list
assert_exit_code 0 || true

# P11-035: Preset list works without cluster (static data)
run_test "P11-035" "Preset list works (static data, no cluster needed)" "$ILUM" preset list
assert_exit_code 0 || true

# =========================================================================
# Final Cleanup
# =========================================================================
log_info "Phase 11 cleanup..."

# Ensure no leftover minikube profiles from this phase
minikube delete --profile test-p11-mk 2>/dev/null || true
minikube delete --profile custom-e2e-test 2>/dev/null || true
minikube delete --profile test-p11-kind 2>/dev/null || true
minikube delete --profile test-p11-k3d 2>/dev/null || true

# Restore original kubecontext
if [[ -n "$ORIGINAL_CONTEXT" ]]; then
    kubectl config use-context "$ORIGINAL_CONTEXT" 2>/dev/null || true
fi

log_info "Phase 11 complete — dependency detection, cluster lifecycle & quickstart tested"
