"""Tests for PipelineErrorPayload model validation."""

from __future__ import annotations

import uuid
from datetime import datetime, timezone

import pytest
from pydantic import ValidationError

from broker_core.topics.models.errors import PipelineErrorPayload


class TestPipelineErrorPayload:
    """Verify PipelineErrorPayload construction and validation."""

    # -- Required fields ---------------------------------------------------

    def test_minimal_valid_payload(self) -> None:
        """Only the 5 required fields — auto-fills everything else."""
        p = PipelineErrorPayload(
            error_category="publish",
            source_service="tele-crawler",
            source_topic="telethon",
            error_message="Connection refused",
            error_type="ConnectionError",
        )
        assert isinstance(p.id, uuid.UUID)
        assert p.severity == "error"
        assert p.is_retryable is True
        assert p.retry_count == 0
        assert p.max_retries == 3
        assert isinstance(p.occurred_at, datetime)
        assert p.telegram_message_id is None
        assert p.peer_id is None
        assert p.payload_truncated is False
        assert p.created_at is None

    def test_full_valid_payload(self) -> None:
        """All fields populated — no errors."""
        p = PipelineErrorPayload(
            error_category="parse",
            severity="critical",
            source_service="tele-parser",
            source_topic="telegram_message_raw_ready",
            source_partition=2,
            source_offset=12345,
            target_topic="telegram_message_parse_ready",
            target_operation="normalize",
            telegram_message_id=42,
            peer_id=100500,
            account_id=uuid.uuid4(),
            proxy_id="proxy-abc",
            error_message="Invalid field 'foo'",
            error_type="KeyError",
            error_traceback='  File "x.py", line 1, in foo\n    raise KeyError',
            payload_preview='{"id":"abc","message":"Hel',
            full_payload={"id": "abc", "message": "Hello"},
            payload_truncated=False,
            payload_size_bytes=42,
            is_retryable=False,
            retry_count=3,
            max_retries=3,
            occurred_at=datetime(2026, 6, 22, tzinfo=timezone.utc),
        )
        assert p.telegram_message_id == 42
        assert p.peer_id == 100500
        assert p.severity == "critical"
        assert p.is_retryable is False
        assert p.retry_count == 3

    def test_missing_error_category_raises(self) -> None:
        """error_category is required — missing it raises ValidationError."""
        with pytest.raises(ValidationError):
            PipelineErrorPayload(
                source_service="s",
                source_topic="t",
                error_message="m",
                error_type="e",
            )

    def test_missing_source_service_raises(self) -> None:
        with pytest.raises(ValidationError):
            PipelineErrorPayload(
                error_category="c",
                source_topic="t",
                error_message="m",
                error_type="e",
            )

    def test_missing_source_topic_raises(self) -> None:
        with pytest.raises(ValidationError):
            PipelineErrorPayload(
                error_category="c",
                source_service="s",
                error_message="m",
                error_type="e",
            )

    def test_missing_error_message_raises(self) -> None:
        with pytest.raises(ValidationError):
            PipelineErrorPayload(
                error_category="c",
                source_service="s",
                source_topic="t",
                error_type="e",
            )

    def test_missing_error_type_raises(self) -> None:
        with pytest.raises(ValidationError):
            PipelineErrorPayload(
                error_category="c",
                source_service="s",
                source_topic="t",
                error_message="m",
            )

    # -- Serialization -----------------------------------------------------

    def test_model_dump_json_mode(self) -> None:
        """model_dump(mode='json') serializes UUID and datetime to strings."""
        p = PipelineErrorPayload(
            error_category="publish",
            source_service="tele-crawler",
            source_topic="telethon",
            error_message="err",
            error_type="Err",
        )
        d = p.model_dump(mode="json")
        assert isinstance(d["id"], str)
        assert isinstance(d["occurred_at"], str)

    # -- telegram_message_id is the only message identity field ------------

    def test_no_legacy_fields(self) -> None:
        """original_message_id and original_telegram_id were removed."""
        p = PipelineErrorPayload(
            error_category="publish",
            source_service="s",
            source_topic="t",
            error_message="m",
            error_type="e",
        )
        assert not hasattr(p, "original_message_id")
        assert not hasattr(p, "original_telegram_id")
        assert hasattr(p, "telegram_message_id")
