# -*- coding: utf-8 -*-
"""
Tests for AR88-05: Hyper-V Direct Host Controller and Physical Autonomous Circuit Preparation.

VERIFICATION CRITERIA:
1. Controller audits host Hyper-V prerequisites and correctly identifies permission boundary.
2. Controller audits VM isolation barriers (network, sharing, PS Direct).
3. Controller payload generation matches authentic contract without manual repair code.
4. Autonomous reasoning generates candidate patch for CircuitTracer directly from failure symptom.
5. Ingestion of guest evaluation result into InternalRepairCoordinator preserves provenance and fails closed without physical isolation.
6. Zero write access to production files (C:\\xampp\\htdocs\\Digital Optimus).
"""
import os
import sys
import tempfile
import pytest

WS = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
if WS not in sys.path:
    sys.path.insert(0, WS)

from app.remediation.self_repair.hyperv_host_controller import (
    HyperVHostController,
    HyperVControllerConfig,
    HyperVControllerStatus,
)
from app.remediation.self_repair.functional_assessor import (
    FunctionalAssessmentStatus,
    FunctionalEvaluationResult,
    InternalFunctionalAssessor,
)
from app.remediation.self_repair.functional_diagnostic_adapter import (
    FunctionalDiagnosticAdapter,
    _compute_sha256,
)
from app.remediation.self_repair.internal_repair_coordinator import (
    InternalRepairCoordinator,
    InternalRepairStatus,
)
from app.remediation.self_repair.engine import SelfRepairEngine


def test_1_controller_audits_prerequisites_fails_closed_on_lack_of_privilege():
    """
    Comprobacion 1:
    El controlador audita los prerrequisitos de Hyper-V.
    Si el proceso anfitrión carece de permisos de administración de Hyper-V,
    devuelve de forma estricta BLOCKED_PERMISSIONS y no intenta iniciar ni ejecutar la VM.
    """
    config = HyperVControllerConfig(vm_name="TEITAN-AR88-LAB", workspace_root=WS)
    controller = HyperVHostController(config)

    ok, msg, details = controller.audit_host_prerequisites()
    assert ok is False
    assert "BLOCKED_PERMISSIONS" in msg or "BLOCKED" in msg
    assert len(details["blockers"]) > 0


def test_2_controller_builds_ps_direct_payload_without_embedded_patch():
    """
    Comprobacion 2:
    El script para el invitado contiene el contrato funcional auténtico de CircuitTracer,
    pero NINGÚN parche o solución prefijada.
    """
    config = HyperVControllerConfig(vm_name="TEITAN-AR88-LAB", workspace_root=WS)
    controller = HyperVHostController(config)

    target_rel = "app/remediation/self_repair/circuit.py"
    target_hash = _compute_sha256(os.path.join(WS, target_rel))

    payload = controller.build_ps_direct_payload(
        contract_id="contract_circuit_tracer_downstream_break",
        target_file_rel=target_rel,
        expected_file_sha256=target_hash,
    )

    assert "contract_circuit_tracer_downstream_break" in payload
    assert "CircuitStatus.NOT_REACHED" in payload
    assert target_hash in payload
    # Verificar que no contiene codigo de parche o mutacion
    assert "REPLACE_EXACT" not in payload
    assert "c_status = CircuitStatus.NOT_REACHED" not in payload


def test_3_autonomous_reasoner_infers_circuittracer_patch_without_manual_code():
    """
    Comprobacion 3:
    El razonador autónomo (AutonomousPatchReasoner) recibe el fallo auténtico
    y es capaz de sintetizar el parche de CircuitTracer de forma 100% autónoma
    (sin suministro manual de instrucciones de parche).
    """
    target_rel = "app/remediation/self_repair/circuit.py"
    target_hash = _compute_sha256(os.path.join(WS, target_rel))

    eval_result = FunctionalEvaluationResult(
        contract_id="contract_circuit_tracer_downstream_break",
        component_name="CircuitTracer",
        target_file_rel=target_rel,
        file_sha256=target_hash,
        status=FunctionalAssessmentStatus.FAIL,
        duration_ms=40.0,
        assertion_error="AssertionError: effector expected NOT_REACHED, got CircuitStatus.UNKNOWN",
    )

    valid, reason, result_tuple = FunctionalDiagnosticAdapter.validate_and_convert_failure(
        eval_result,
        workspace_root=WS,
    )
    assert valid is True
    event, incident, evidence = result_tuple

    engine = SelfRepairEngine(project_root=WS)
    trace = engine.tracer.trace(incident=incident, evidence=evidence)
    root_cause = engine.analyzer.analyze(incident=incident, evidence=evidence, trace=trace, workspace_root=WS)
    proposal = engine.planner.plan_repair(incident=incident, root_cause_info=root_cause, workspace_root=WS)

    reasoning_res = engine.patch_reasoner.reason_patch(
        event=event,
        incident=incident,
        evidence=evidence,
        root_cause_info=root_cause,
        proposal=proposal,
        workspace_root=WS,
    )

    assert reasoning_res.success is True
    assert reasoning_res.confidence == "HIGH"
    assert len(reasoning_res.candidate_instructions) == 1

    inst = reasoning_res.candidate_instructions[0]
    assert inst.file_rel_path == target_rel
    assert "c_status = CircuitStatus.UNKNOWN" in inst.before
    assert "c_status = CircuitStatus.NOT_REACHED" in inst.after


def test_4_coordinator_ingests_authentic_result_and_blocks_unaccredited_host():
    """
    Comprobacion 4:
    Al ingresar el resultado en InternalRepairCoordinator en el entorno anfitrión,
    el coordinador admite el incidente, analiza la causa raíz, pero se bloquea
    estrictamente en la puerta de aislamiento físico (BLOCKED_UNACCREDITED_ISOLATION)
    porque all_barriers_satisfied=False en el anfitrión.
    """
    target_rel = "app/remediation/self_repair/circuit.py"
    target_hash = _compute_sha256(os.path.join(WS, target_rel))

    eval_result = FunctionalEvaluationResult(
        contract_id="contract_circuit_tracer_downstream_break",
        component_name="CircuitTracer",
        target_file_rel=target_rel,
        file_sha256=target_hash,
        status=FunctionalAssessmentStatus.FAIL,
        duration_ms=35.0,
        assertion_error="AssertionError: effector expected NOT_REACHED, got CircuitStatus.UNKNOWN",
        stack_trace="Traceback: ...",
        stdout="[TEST] break reproduced",
    )

    temp_dir = tempfile.mkdtemp()
    coord = InternalRepairCoordinator(
        project_root=WS,
        base_reports_dir=os.path.join(temp_dir, "reports"),
        store_path=os.path.join(temp_dir, "store.json"),
    )

    summary = coord.coordinate_internal_evaluation(
        eval_result=eval_result,
        read_only=False,
        persist_artifacts=False,
    )

    assert summary["status"] == InternalRepairStatus.BLOCKED_UNACCREDITED_ISOLATION
    assert summary["internal_incident_admitted"] is True
    assert summary["root_cause_proven"] is True
    assert summary["sandbox_repair_executed"] is False


def test_5_production_remains_completely_unmodified():
    """
    Comprobacion 5:
    Se confirma que ningún archivo del directorio de producción ha sido modificado.
    """
    import hashlib

    prod_circuit = r"C:\xampp\htdocs\Digital Optimus\app\remediation\self_repair\circuit.py"
    with open(prod_circuit, "rb") as f:
        prod_h = hashlib.sha256(f.read()).hexdigest().upper()

    assert prod_h == "AA3999237E9AF1ACC08B533460A73826984E320B893FFFD9BAD3A5D781BAFE7E"

