"""Tests for the codal statement domain."""

from __future__ import annotations

from types import SimpleNamespace
from unittest.mock import AsyncMock

import pytest

from repo_core.domains.codal.model import CodalStatement
from repo_core.domains.codal.repository import CodalStatementRepository


def test_codal_statement_defaults_version_to_one():
    statement = CodalStatement(id="stmt-1", url="https://example.com/statement")
    assert statement.version == 1


def test_codal_statement_includes_version_in_db_payload():
    statement = CodalStatement(id="stmt-1", url="https://example.com/statement", version=3)
    payload = statement.to_db()
    assert payload["version"] == 3


@pytest.mark.asyncio
async def test_upsert_by_url_defaults_version_and_uses_version_in_lookup(monkeypatch):
    repo = CodalStatementRepository(model=CodalStatement)
    first = AsyncMock(return_value=None)
    insert_one = AsyncMock(return_value=SimpleNamespace(id="stmt-1"))
    monkeypatch.setattr(repo, "first", first)
    monkeypatch.setattr(repo, "insert_one", insert_one)

    await repo.upsert_by_url({"url": "https://example.com/statement"})

    first.assert_awaited_once()
    assert first.call_args.args[1] == {"url": "https://example.com/statement", "version": 1}
    assert insert_one.call_args.args[1]["version"] == 1


@pytest.mark.asyncio
async def test_upsert_by_url_updates_matching_version(monkeypatch):
    repo = CodalStatementRepository(model=CodalStatement)
    existing = SimpleNamespace(id="stmt-1")
    first = AsyncMock(return_value=existing)
    update_by_id = AsyncMock(return_value=None)
    find_by_id = AsyncMock(return_value=existing)
    monkeypatch.setattr(repo, "first", first)
    monkeypatch.setattr(repo, "update_by_id", update_by_id)
    monkeypatch.setattr(repo, "find_by_id", find_by_id)

    await repo.upsert_by_url({"url": "https://example.com/statement", "version": 2})

    first.assert_awaited_once()
    assert first.call_args.args[1] == {"url": "https://example.com/statement", "version": 2}
    update_by_id.assert_awaited_once()
