"""Tests pour les modèles de messages inter-pipelines."""

from __future__ import annotations

import pytest
from pydantic import ValidationError

from cezam_lib.pipeline_template.messages import (
    ConsolidatedPipelineMessage,
    SpecializedDocumentItem,
)


def _make_doc(**overrides) -> dict:
    defaults = {
        "doc_name": "livret_famille.pdf",
        "document_type": "livret_famille",
        "confidence": 0.88,
        "ocr_json_path": "sim-xxx/ocr/livret_famille.pdf.json",
    }
    return {**defaults, **overrides}


def _make_specialized_doc(**overrides) -> dict:
    defaults = {
        "doc_name": "compromis_vente_maison.pdf",
        "document_type": "compromis_vente",
        "confidence": 0.96,
        "target_pipeline": "pipeline_compromis_promesse",
        "legacy_hint": "skip",
        "ocr_json_path": "sim-xxx/ocr/compromis_vente_maison.pdf.json",
    }
    return {**defaults, **overrides}


# --- SpecializedDocumentItem ---


class TestSpecializedDocumentItem:
    def test_valid_skip(self):
        doc = SpecializedDocumentItem(**_make_specialized_doc(legacy_hint="skip"))
        assert doc.legacy_hint == "skip"
        assert doc.target_pipeline == "pipeline_compromis_promesse"

    def test_valid_full(self):
        doc = SpecializedDocumentItem(**_make_specialized_doc(legacy_hint="full"))
        assert doc.legacy_hint == "full"

    def test_default_hint_is_full(self):
        data = _make_specialized_doc()
        del data["legacy_hint"]
        doc = SpecializedDocumentItem(**data)
        assert doc.legacy_hint == "full"

    def test_invalid_hint_rejected(self):
        with pytest.raises(ValidationError):
            SpecializedDocumentItem(**_make_specialized_doc(legacy_hint="partial"))

    def test_empty_doc_name_rejected(self):
        with pytest.raises(ValidationError):
            SpecializedDocumentItem(**_make_specialized_doc(doc_name=""))


# --- ConsolidatedPipelineMessage with specialized_documents ---


class TestConsolidatedPipelineMessageSpecialized:
    def _base_msg(self, **overrides) -> dict:
        defaults = {
            "simulation_id": "69c2676d77e8575e7086571c",
            "simulation_public_id": "pub-98d3e7c1",
            "n_doc_total": 10,
            "documents": [_make_doc()],
        }
        return {**defaults, **overrides}

    def test_without_specialized_documents(self):
        msg = ConsolidatedPipelineMessage(**self._base_msg())
        assert msg.specialized_documents == []

    def test_with_empty_specialized_documents(self):
        msg = ConsolidatedPipelineMessage(
            **self._base_msg(specialized_documents=[])
        )
        assert msg.specialized_documents == []

    def test_with_mixed_hints(self):
        spec_docs = [
            _make_specialized_doc(
                doc_name="compromis.pdf", legacy_hint="skip"
            ),
            _make_specialized_doc(
                doc_name="releve.pdf",
                document_type="releves_bancaires",
                target_pipeline="pipeline_rb",
                legacy_hint="full",
            ),
        ]
        msg = ConsolidatedPipelineMessage(
            **self._base_msg(specialized_documents=spec_docs)
        )
        assert len(msg.specialized_documents) == 2
        assert msg.specialized_documents[0].legacy_hint == "skip"
        assert msg.specialized_documents[1].legacy_hint == "full"

    def test_invalid_specialized_doc_rejected(self):
        bad_spec = [_make_specialized_doc(legacy_hint="invalid")]
        with pytest.raises(ValidationError):
            ConsolidatedPipelineMessage(
                **self._base_msg(specialized_documents=bad_spec)
            )

    def test_model_dump_roundtrip(self):
        spec_docs = [_make_specialized_doc()]
        msg = ConsolidatedPipelineMessage(
            **self._base_msg(specialized_documents=spec_docs)
        )
        dumped = msg.model_dump()
        restored = ConsolidatedPipelineMessage(**dumped)
        assert restored == msg
