#!/usr/bin/env python3
from __future__ import annotations

import copy
import hashlib
import json
import sys
from pathlib import Path

ROOT = Path("/home/shire3d/ARMOR")

if str(ROOT) not in sys.path:
    sys.path.insert(0, str(ROOT))

from ai import brain_server
from services.design_academy_practice_service import (
    AcademyBrainResponseError,
    practice_service,
)
from tools.design_academy_generic_qualify import (
    classify_brain_failure,
)

PRACTICE_STATE = (
    ROOT
    / "data/academy/design_mastery/runtime/practice_state.json"
)

AUTOPILOT_STATE = (
    ROOT
    / "data/academy/design_mastery/runtime/autopilot_state.json"
)

SKILL = "geometry_foundations.fillets"


def sha256(path: Path) -> str:
    return hashlib.sha256(path.read_bytes()).hexdigest()


practice_sha_before = sha256(PRACTICE_STATE)
autopilot_sha_before = sha256(AUTOPILOT_STATE)

criteria = [
    (
        "The resulting solid contains no non-manifold edges or "
        "self-intersections."
    ),
    (
        "All generated surface normals point outward consistently "
        "after validation."
    ),
]

round3_with_root_criteria = {
    "round": 3,
    "transfer_project": {
        "title": "Household Corner Fillet Transfer",
        "goal": (
            "Apply filleting principles to a harmless household model "
            "while checking predictable geometry limits."
        ),
        "inputs": [
            "Corner edge selection",
            "Fillet radius in millimetres",
        ],
        "steps": [
            (
                "Define the harmless household test shape using stable "
                "dimensions."
            ),
            (
                "Apply the selected fillet radius to the intended "
                "corner edges."
            ),
            (
                "Inspect the resulting solid against the stated "
                "geometry checks."
            ),
        ],
        "outputs": [
            "Validated filleted solid",
            "Recorded geometry check report",
        ],
    },
    "acceptance_criteria": criteria,
    "boundary_cases": {
        "minimum": (
            "Use a small positive radius that remains visibly measurable."
        ),
        "nominal": (
            "Use the normal design radius specified by the lesson input."
        ),
        "maximum": (
            "Use the largest radius that preserves the intended solid."
        ),
        "invalid": (
            "Reject zero, negative or topology-breaking radius values."
        ),
    },
    "provenance_review": {
        "licence_status": "unknown",
        "decision": "quarantine",
        "commercial_use": "blocked",
        "reason": (
            "Source provenance is unverified, so the exercise remains "
            "quarantined and blocked from commercial use."
        ),
    },
    "safety_gate": {
        "risk_class": "low",
        "action": "continue",
        "forge_execution_allowed": False,
        "reason": (
            "This is a harmless knowledge-only geometry exercise with "
            "no release authority or physical safety claim."
        ),
    },
    "limitations": [
        "No physical part was manufactured or physically validated.",
        "The exercise does not grant Forge execution or release authority.",
    ],
}

normalised = brain_server.canonicalise_academy_answer(
    json.dumps(round3_with_root_criteria),
    3,
)

canonical = json.loads(normalised["canonical"])

assert "acceptance_criteria" not in canonical
assert (
    canonical["transfer_project"]["acceptance_criteria"]
    == criteria
)
assert normalised["repaired"] is True
assert (
    "moved_root_acceptance_criteria_to_transfer_project"
    in normalised["canonicalisation_notes"]
)

duplicate = copy.deepcopy(canonical)
duplicate["acceptance_criteria"] = list(criteria)

duplicate_result = brain_server.canonicalise_academy_answer(
    json.dumps(duplicate),
    3,
)

assert (
    "pruned_duplicate_root_acceptance_criteria"
    in duplicate_result["canonicalisation_notes"]
)

conflicting = copy.deepcopy(canonical)

conflicting["acceptance_criteria"] = [
    (
        "A conflicting root criterion must not overwrite preserved "
        "nested content."
    ),
    (
        "Conflicting criteria require an honest content-contract "
        "failure."
    ),
]

try:
    brain_server.canonicalise_academy_answer(
        json.dumps(conflicting),
        3,
    )
except brain_server.AcademyStructuredOutputError as exc:
    assert "conflicting acceptance_criteria" in str(exc)
else:
    raise AssertionError(
        "Conflicting Round 3 criteria were silently accepted"
    )

bad_boundaries = copy.deepcopy(round3_with_root_criteria)

bad_boundaries["boundary_cases"]["minimum"] = {
    "radius_mm": 0.1,
    "status": "valid",
}

try:
    brain_server.canonicalise_academy_answer(
        json.dumps(bad_boundaries),
        3,
    )
except brain_server.AcademyStructuredOutputError as exc:
    assert "plain-language string" in str(exc)
else:
    raise AssertionError(
        "Invalid object-valued Round 3 boundary case was accepted"
    )

content_error = AcademyBrainResponseError(
    "Brain API HTTP 422: Academy structured output invalid",
    {
        "retryable": False,
        "infrastructure_failure": False,
        "content_format_failure": True,
        "failure_class": "academy_output_contract_failure",
    },
)

content_record = {
    "infrastructure_failures": 2,
    "attempts": 7,
}

content_record_before = copy.deepcopy(content_record)

assert (
    practice_service._transient_brain_failure(content_error)
    is False
)
assert classify_brain_failure(content_error) == "content"
assert content_record == content_record_before

timeout_error = AcademyBrainResponseError(
    "Brain API HTTP 504: Academy model request timed out",
    {
        "retryable": True,
        "infrastructure_failure": True,
        "timeout_stage": "ollama_generation",
    },
)

assert (
    practice_service._transient_brain_failure(timeout_error)
    is True
)
assert classify_brain_failure(timeout_error) == "infrastructure"

transport_error = AcademyBrainResponseError(
    "Brain API practice request failed: connection refused"
)

assert (
    practice_service._transient_brain_failure(transport_error)
    is True
)
assert classify_brain_failure(transport_error) == "infrastructure"

transport_record = {
    "infrastructure_failures": 2,
    "attempts": 7,
}

count, status, retryable = (
    practice_service._infrastructure_failure_outcome(
        transport_record
    )
)

assert count == 3
assert transport_record["infrastructure_failures"] == 3
assert transport_record["attempts"] == 6
assert status == "failed"
assert retryable is False

brain_source = Path(
    brain_server.__file__
).read_text(encoding="utf-8")

assert '"content_format_failure": True' in brain_source
assert '"infrastructure_failure": False' in brain_source
assert "status=422" in brain_source

practice = json.loads(
    PRACTICE_STATE.read_text(encoding="utf-8")
)

autopilot = json.loads(
    AUTOPILOT_STATE.read_text(encoding="utf-8")
)

practice_record = practice["skills"][SKILL]
qualification = autopilot["skills"][SKILL]
runs = qualification.get("qualification_runs") or []

successful_rounds = {
    int(item.get("round") or 0)
    for item in runs
    if isinstance(item, dict)
    and item.get("passed") is True
    and int(item.get("score_percent") or 0) == 100
}

assert int(
    practice_record.get("successful_attempts") or 0
) == 2

assert int(
    practice_record.get("latest_score") or 0
) == 100

assert successful_rounds == {1, 2, 3}
assert practice_record.get("knowledge_certified") is False
assert practice_record.get("forge_allowed") is False
assert qualification.get("forge_allowed") is False
assert autopilot.get("forge_unlock_allowed") is False
assert autopilot.get("counted_execution_enabled") is False

assert sha256(PRACTICE_STATE) == practice_sha_before
assert sha256(AUTOPILOT_STATE) == autopilot_sha_before

print(json.dumps({
    "ok": True,
    "tests": {
        "root_acceptance_criteria_migrated": True,
        "duplicate_root_acceptance_criteria_pruned": True,
        "conflicting_criteria_rejected": True,
        "invalid_boundary_object_rejected": True,
        "brain_contract_failure_is_http_422": True,
        "content_failure_not_infrastructure": True,
        "content_failure_counter_unchanged": True,
        "timeout_classified_as_infrastructure": True,
        "transport_classified_as_infrastructure": True,
        "genuine_infrastructure_counter_incremented": True,
        "successful_rounds_preserved":
            sorted(successful_rounds),
        "successful_counted_attempts_preserved": 2,
        "latest_score_preserved": 100,
        "practice_state_unchanged": True,
        "autopilot_state_unchanged": True,
        "forge_remains_locked": True,
    },
}, indent=2, sort_keys=True))
