# SPDX-License-Identifier: AGPL-3.0-only
# Copyright (c) 2026 sol pbc

import importlib

import pytest


def _minimal_valid_stats(schema_mod):
    return {
        "schema_version": schema_mod.SCHEMA_VERSION,
        "generated_at": "2026-05-30T00:00:00+00:00",
        "day_count": 0,
        "days": {},
        "totals": {field: 0 for field in schema_mod.TOTAL_FIELDS},
        "heatmap": [],
        "tokens": {},
        "talents": {},
        "facets": {},
        "backlog": {
            "window": 30,
            "days": [],
            "pending_days": 0,
            "stuck_days": 0,
            "oldest_pending_day": None,
            "errors": [],
        },
    }


def test_schema_version_is_8():
    schema_mod = importlib.import_module("solstone.think.stats_schema")

    assert schema_mod.SCHEMA_VERSION == 8


def test_validate_passes_on_valid_output(tmp_path, monkeypatch):
    """Build a JournalStats from fixture data, call to_dict(), validate."""
    stats_mod = importlib.import_module("solstone.think.journal_stats")
    schema_mod = importlib.import_module("solstone.think.stats_schema")
    journal = tmp_path
    day = journal / "chronicle" / "20240101"
    day.mkdir(parents=True)

    # Create minimal transcript fixture
    ts_dir = day / "default" / "123456_300"
    ts_dir.mkdir(parents=True)
    (ts_dir / "audio.jsonl").write_text(
        '{"raw": "raw.flac"}\n{"start": "10:00:00", "text": "hello"}\n'
    )

    monkeypatch.setenv("SOLSTONE_JOURNAL", str(journal))
    js = stats_mod.JournalStats()
    js.scan(str(journal))

    data = js.to_dict()
    errors = schema_mod.validate(data)
    assert errors == [], f"Validation errors: {errors}"


def test_validate_rejects_missing_fields():
    """Incomplete dicts should produce non-empty error lists."""
    schema_mod = importlib.import_module("solstone.think.stats_schema")

    # Empty dict
    errors = schema_mod.validate({})
    assert len(errors) > 0
    assert any("schema_version" in e for e in errors)

    # Missing days
    errors = schema_mod.validate(
        {"schema_version": 2, "generated_at": "2026-04-10T00:00:00+00:00"}
    )
    assert any("days" in e for e in errors)

    # Wrong schema version
    errors = schema_mod.validate(
        {
            "schema_version": 99,
            "generated_at": "x",
            "day_count": 0,
            "days": {},
            "totals": {},
            "heatmap": [],
            "tokens": {},
            "agents": {},
            "facets": {},
        }
    )
    assert any("schema_version" in e for e in errors)


def test_save_json_raises_on_invalid(tmp_path, monkeypatch):
    """save_json() must raise ValueError when validation fails."""
    stats_mod = importlib.import_module("solstone.think.journal_stats")
    monkeypatch.setenv("SOLSTONE_JOURNAL", str(tmp_path))
    js = stats_mod.JournalStats()
    # Corrupt the schema version so validation fails
    original = js.to_dict
    js.to_dict = lambda: {**original(), "schema_version": 99}
    with pytest.raises(ValueError, match="Stats validation failed"):
        js.save_json(str(tmp_path))


def test_validate_rejects_missing_backlog_contract_fields():
    schema_mod = importlib.import_module("solstone.think.stats_schema")
    data = _minimal_valid_stats(schema_mod)

    del data["totals"]["backlog_pending_days"]
    errors = schema_mod.validate(data)
    assert any("backlog_pending_days" in error for error in errors)

    data = _minimal_valid_stats(schema_mod)
    del data["totals"]["backlog_stuck_days"]
    errors = schema_mod.validate(data)
    assert any("backlog_stuck_days" in error for error in errors)

    data = _minimal_valid_stats(schema_mod)
    del data["backlog"]
    errors = schema_mod.validate(data)
    assert any("backlog" in error for error in errors)


def test_day_fields_present_in_scan_day(tmp_path, monkeypatch):
    """Verify every key in DAY_FIELDS appears in scan_day output."""
    stats_mod = importlib.import_module("solstone.think.journal_stats")
    schema_mod = importlib.import_module("solstone.think.stats_schema")
    journal = tmp_path
    day = journal / "chronicle" / "20240101"
    day.mkdir(parents=True)

    # Create transcript and percept fixtures
    ts_dir = day / "default" / "123456_300"
    ts_dir.mkdir(parents=True)
    (ts_dir / "audio.jsonl").write_text(
        '{"raw": "raw.flac"}\n{"start": "10:00:00", "text": "hello"}\n'
    )
    (ts_dir / "screen.jsonl").write_text(
        '{"header": true}\n{"frame_id": 1, "timestamp": "10:00:00"}\n'
    )

    monkeypatch.setenv("SOLSTONE_JOURNAL", str(journal))
    js = stats_mod.JournalStats()
    day_data = js.scan_day("20240101", str(day))

    stats = day_data["stats"]
    for field in schema_mod.DAY_FIELDS:
        assert field in stats, (
            f"DAY_FIELDS field '{field}' missing from scan_day output"
        )
