from __future__ import annotations

import json
from types import SimpleNamespace

from libs.backtest import artifacts


def test_write_snapshot_provenance_copies_manifest_and_fingerprint(tmp_path, monkeypatch):
    parquet_root = tmp_path / "parquet"
    snapshot_dir = parquet_root / "snap_a"
    snapshot_dir.mkdir(parents=True)
    manifest = {
        "snapshot_id": "snap_a",
        "created_at_utc": "2026-03-25T21:30:10+00:00",
        "code_commit_hash": "abc123",
        "feature_version": "market_v1",
        "parser_version": "rule-1.0.0",
        "label_version": "label-2.0.0",
        "row_counts": {"train": 10, "valid": 2, "test": 3},
        "total_rows": 15,
    }
    (snapshot_dir / "manifest.json").write_text(json.dumps(manifest))

    monkeypatch.setattr(artifacts, "resolve_snapshot_path", lambda snapshot_id: snapshot_dir)

    run_dir = tmp_path / "run"
    run_dir.mkdir()
    paths = artifacts.write_snapshot_provenance(
        run_dir,
        SimpleNamespace(
            dataset_snapshot_id="snap_a",
            requested_snapshot_id="snap_a",
            canonical_snapshot_id="snap_a",
        ),
    )

    assert set(paths) == {"snapshot_manifest", "snapshot_fingerprint"}
    copied_manifest = json.loads((run_dir / "snapshot_manifest.json").read_text())
    fingerprint = json.loads((run_dir / "snapshot_fingerprint.json").read_text())

    assert copied_manifest == manifest
    assert fingerprint["dataset_snapshot_id"] == "snap_a"
    assert fingerprint["requested_snapshot_id"] == "snap_a"
    assert fingerprint["canonical_snapshot_id"] == "snap_a"
    assert fingerprint["snapshot_dir_name"] == "snap_a"
    assert fingerprint["manifest_snapshot_id"] == "snap_a"
    assert fingerprint["snapshot_id_matches_manifest"] is True
    assert fingerprint["output_dir_matches_manifest"] is True
    assert fingerprint["snapshot_created_at_utc"] == manifest["created_at_utc"]
    assert fingerprint["code_commit_hash"] == manifest["code_commit_hash"]
    assert fingerprint["row_counts"] == manifest["row_counts"]
    assert fingerprint["total_rows"] == manifest["total_rows"]


def test_write_snapshot_provenance_records_manifest_mismatch(tmp_path, monkeypatch):
    parquet_root = tmp_path / "parquet"
    snapshot_dir = parquet_root / "snap_b"
    snapshot_dir.mkdir(parents=True)
    manifest = {
        "snapshot_id": "snap_old",
        "created_at_utc": "2026-03-25T21:30:10+00:00",
        "code_commit_hash": "abc123",
        "feature_version": "market_v1",
        "parser_version": "rule-1.0.0",
        "label_version": "label-2.0.0",
        "row_counts": {"train": 10, "valid": 2, "test": 3},
        "total_rows": 15,
        "output_dir": "data/datasets/snapshots/snap_old",
    }
    (snapshot_dir / "manifest.json").write_text(json.dumps(manifest))

    monkeypatch.setattr(artifacts, "resolve_snapshot_path", lambda snapshot_id: snapshot_dir)

    run_dir = tmp_path / "run"
    run_dir.mkdir()
    artifacts.write_snapshot_provenance(
        run_dir,
        SimpleNamespace(
            dataset_snapshot_id="snap_b",
            requested_snapshot_id="snap_b",
            canonical_snapshot_id="snap_b",
        ),
    )
    fingerprint = json.loads((run_dir / "snapshot_fingerprint.json").read_text())

    assert fingerprint["snapshot_dir_name"] == "snap_b"
    assert fingerprint["manifest_snapshot_id"] == "snap_old"
    assert fingerprint["snapshot_id_matches_manifest"] is False
    assert fingerprint["output_dir_matches_manifest"] is False
