"""CodegenService._update_runtime_invariants must push a locked admin_panel_path/
customer_login_path to Cloud -- previously it only wrote to Postgres and logged, so a
custom admin path picked up mid-run never reached Cloud unless some unrelated
auth-config edit happened to trigger a push afterward."""
from __future__ import annotations

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

import pytest

from src.domain.codegen.service import CodegenService


def _fake_project(project_id, runtime_invariants):
    return SimpleNamespace(id=project_id, workspace_id=uuid4(), runtime_invariants=runtime_invariants)


def _service(project):
    execute_result = SimpleNamespace(scalar_one_or_none=lambda: project)
    fake_db = SimpleNamespace(execute=AsyncMock(return_value=execute_result), flush=AsyncMock())
    codegen_repo = SimpleNamespace(_db=fake_db)
    project_facade = SimpleNamespace()
    service = CodegenService(codegen_repo=codegen_repo, project_facade=project_facade)
    service._push_runtime_invariants_to_cloud = AsyncMock()
    return service


@pytest.mark.asyncio
async def test_locking_a_custom_admin_path_pushes_to_cloud():
    project_id = uuid4()
    project = _fake_project(project_id, {})  # no invariants yet
    service = _service(project)

    await service._update_runtime_invariants(project_id, "put the admin panel at /be-admin")

    service._push_runtime_invariants_to_cloud.assert_awaited_once_with(project_id)


@pytest.mark.asyncio
async def test_a_change_unrelated_to_routes_does_not_push():
    project_id = uuid4()
    # Already has a locked admin path; this prompt only adds an email preference,
    # which _push_auth_config's Cloud payload doesn't even carry.
    project = _fake_project(project_id, {"admin_panel_path": "/be-admin", "source": "prompt"})
    service = _service(project)

    await service._update_runtime_invariants(project_id, "send emails via our own SMTP provider")

    service._push_runtime_invariants_to_cloud.assert_not_awaited()


@pytest.mark.asyncio
async def test_no_signal_in_the_prompt_is_a_pure_noop():
    project_id = uuid4()
    project = _fake_project(project_id, {"admin_panel_path": "/be-admin", "source": "prompt"})
    service = _service(project)

    await service._update_runtime_invariants(project_id, "make the hero button bigger")

    service._push_runtime_invariants_to_cloud.assert_not_awaited()
