import json
from pathlib import Path

from auditwalk.runs.schema import (
    assert_meta_valid,
    assert_score_valid,
    normalize_meta,
    validate_meta,
    validate_score,
)


def _meta_base() -> dict:
    return {
        "schema_version": 1,
        "product": "auditwalk",
        "product_version": "0.1.0",
        "run_id": "run_test",
        "created_utc": 1,
        "mode": "quick",
        "host": {"hostname": "host", "os_family": "linux", "arch": "x86_64"},
        "collector_status": {
            "system": "ok",
            "disk": "ok",
            "processes": "ok",
            "network": "ok",
            "persistence": "ok",
            "installed": "skipped",
            "files": "ok",
            "firewall": "skipped",
        },
        "options": {
            "roots": ["/tmp"],
            "exclude": [],
            "hash": False,
            "max_files": 100,
            "max_procs": 10,
            "timeout_seconds": 60,
        },
    }


def test_validate_meta_ok():
    meta = _meta_base()
    issues = validate_meta(meta)
    assert [i for i in issues if i.level == "error"] == []
    assert_meta_valid(meta)


def test_validate_meta_missing_arch_is_error():
    meta = _meta_base()
    del meta["host"]["arch"]
    issues = validate_meta(meta)
    errors = [i for i in issues if i.level == "error"]
    assert any(i.path == "$.host.arch" for i in errors)


def test_normalize_meta_sets_defaults():
    meta = normalize_meta({})
    assert meta["schema_version"] == 1
    assert meta["product"] == "auditwalk"
    assert meta["product_version"] == "0.1.0"
    assert meta["host"]["os_family"] == "unknown"


def test_validate_meta_fixture_schema_v1_compatible():
    fixture = Path(__file__).resolve().parent / "fixtures" / "meta_schema_v1_valid.json"
    if fixture.exists():
        meta = json.loads(fixture.read_text(encoding="utf-8"))
        assert_meta_valid(meta)


def test_validate_score_ok():
    score = {"total": 5, "tier": "Low", "breakdown": {}, "findings": []}
    issues = validate_score(score)
    assert [i for i in issues if i.level == "error"] == []
    assert_score_valid(score)


def test_validate_score_total_must_be_int():
    score = {"total": "5", "tier": "Low", "breakdown": {}, "findings": []}
    issues = validate_score(score)
    assert any(i.path == "$.total" and i.level == "error" for i in issues)
