"""ProjectAuthService._push_auth_config includes the project's resolved admin/login
routes (Phase 1's runtime_invariants) in every payload pushed to Cloud."""
from __future__ import annotations

from types import SimpleNamespace
from unittest.mock import AsyncMock
from uuid import uuid4

import pytest

from src.domain.project_auth.service import ProjectAuthService


def _fake_config():
    return SimpleNamespace(
        enabled=True,
        providers=["email", "magic_link"],
        allow_signup=True,
        require_email_verify=False,
        google_oauth_mode=None,
        google_client_id_enc=None,
        access_token_ttl_seconds=3600,
        refresh_token_ttl_days=30,
        password_min_length=8,
    )


def _service(project):
    class _FakeDB:
        async def execute(self, _query):
            return SimpleNamespace(scalar_one_or_none=lambda: project)

    cloud = SimpleNamespace(push_auth_config=AsyncMock(return_value=True))
    service = ProjectAuthService(
        config_repo=SimpleNamespace(_db=_FakeDB(), update=AsyncMock()),
        key_repo=SimpleNamespace(),
        role_repo=SimpleNamespace(list_for_project=AsyncMock(return_value=[])),
        cloud_client=cloud,
    )
    return service, cloud


@pytest.mark.asyncio
async def test_push_includes_named_admin_path():
    project = SimpleNamespace(
        workspace_id=uuid4(),
        runtime_invariants={"admin_panel_path": "/be-admin", "customer_login_path": "/login"},
    )
    service, cloud = _service(project)
    await service._push_auth_config(uuid4(), _fake_config())
    pushed = cloud.push_auth_config.call_args.kwargs["config"]
    assert pushed["admin_panel_path"] == "/be-admin"
    assert pushed["customer_login_path"] == "/login"


@pytest.mark.asyncio
async def test_push_defaults_when_no_invariants_recorded():
    project = SimpleNamespace(workspace_id=uuid4(), runtime_invariants={})
    service, cloud = _service(project)
    await service._push_auth_config(uuid4(), _fake_config())
    pushed = cloud.push_auth_config.call_args.kwargs["config"]
    assert pushed["admin_panel_path"] == "/admin"
    assert pushed["customer_login_path"] == "/login"


@pytest.mark.asyncio
async def test_push_defaults_when_project_missing_entirely():
    """_config._db.execute finds no matching project row -- must not raise, must not
    invent a path other than the platform default."""
    service, cloud = _service(project=None)
    await service._push_auth_config(uuid4(), _fake_config())
    pushed = cloud.push_auth_config.call_args.kwargs["config"]
    assert pushed["admin_panel_path"] == "/admin"
    assert pushed["workspace_id"] is None


@pytest.mark.asyncio
async def test_required_auth_projection_rejects_unconfigured_cloud():
    project = SimpleNamespace(workspace_id=uuid4(), runtime_invariants={})
    service, cloud = _service(project)
    cloud.push_auth_config.return_value = False

    with pytest.raises(RuntimeError, match="cloud_not_configured"):
        await service._push_auth_config(uuid4(), _fake_config())
