import uuid
from types import SimpleNamespace

import pytest
from sqlalchemy import delete, select
from sqlalchemy.ext.asyncio import AsyncSession

from app import seed
from app.db.engine import get_engine
from app.sites.models import Site, SiteTarget


def test_seed_requires_org_id() -> None:
    with pytest.raises(SystemExit) as exc:
        seed.main([])
    assert exc.value.code == 2


async def test_seed_run_names_the_org(capsys: pytest.CaptureFixture[str]) -> None:
    await seed.run("org_dev")
    assert "org_dev" in capsys.readouterr().out


def test_seed_main_refuses_remote_host(
    monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
    remote = "postgresql+asyncpg://seoinsight:secret@db.example.com:5432/data"
    monkeypatch.setattr(seed, "get_settings", lambda: SimpleNamespace(database_url=remote))

    with pytest.raises(SystemExit) as exc:
        seed.main(["--org-id", "org_dev"])

    assert exc.value.code == 1
    assert "db.example.com" in capsys.readouterr().err


async def _demo_sites(org_id: str) -> list[Site]:
    async with AsyncSession(get_engine()) as session:
        sites = list(
            (
                await session.scalars(
                    select(Site).where(Site.org_id == org_id, Site.domain == seed.DEMO_DOMAIN)
                )
            ).all()
        )
        for site in sites:
            await session.refresh(site, ["targets"])
    return sites


async def test_seed_run_creates_demo_site() -> None:
    org_id = f"org_{uuid.uuid4().hex[:12]}"
    await seed.run(org_id)
    sites = await _demo_sites(org_id)
    assert len(sites) == 1
    assert sites[0].name == seed.DEMO_NAME
    targets = [(t.country, t.language, t.is_default) for t in sites[0].targets]
    assert targets == [("FR", "fr", True)]


async def test_seed_run_is_idempotent(capsys: pytest.CaptureFixture[str]) -> None:
    org_id = f"org_{uuid.uuid4().hex[:12]}"
    await seed.run(org_id)
    await seed.run(org_id)
    assert len(await _demo_sites(org_id)) == 1
    assert "déjà présent" in capsys.readouterr().out


async def test_seed_run_restores_a_missing_default_target() -> None:
    # État atteignable seulement à la main en psql (l'api ne supprime jamais la dernière
    # cible) : le seed doit le réparer plutôt que de sortir sur « déjà présent ».
    org_id = f"org_{uuid.uuid4().hex[:12]}"
    await seed.run(org_id)
    site_id = (await _demo_sites(org_id))[0].id
    async with AsyncSession(get_engine()) as session:
        await session.execute(delete(SiteTarget).where(SiteTarget.site_id == site_id))
        await session.commit()

    await seed.run(org_id)

    sites = await _demo_sites(org_id)
    assert len(sites) == 1
    assert [(t.country, t.language, t.is_default) for t in sites[0].targets] == [("FR", "fr", True)]


async def test_seed_run_does_not_duplicate_the_default_target() -> None:
    org_id = f"org_{uuid.uuid4().hex[:12]}"
    await seed.run(org_id)
    await seed.run(org_id)
    assert len((await _demo_sites(org_id))[0].targets) == 1
