"""Firm clients list — paginated, searchable, firm-only."""

from __future__ import annotations

from fastapi.testclient import TestClient
from sqlalchemy import select

from app.db import SessionLocal, SnelStartConnectionRow
from app.main import app
from app.services import users as user_service
from app.services.snelstart.connection import ensure_connection_row
from app.store import store

client = TestClient(app)


def _firm_email(prefix: str) -> str:
    email = f"firm-list-{prefix}@test.com"
    user_service.ensure_user(platform="firm", email=email, name="Firm User")
    return email


def _create_client(name: str, *, kvk: str = "", email: str = "") -> str:
    created = store.create_client(name, kvk=kvk, email=email)
    return created.id


def test_firm_can_list_clients_with_pagination():
    firm_email = _firm_email("paginated")
    created_ids = [_create_client(f"Pagination Client {index}") for index in range(25)]

    first_page = client.get(
        f"/api/v1/clients?platform=firm&email={firm_email}&page=1&page_size=10"
    )
    assert first_page.status_code == 200
    body = first_page.json()
    assert len(body["items"]) == 10
    assert body["page"] == 1
    assert body["page_size"] == 10
    assert body["total"] >= 25
    assert body["total_pages"] >= 3
    assert body["items"][0]["documentCount"] == 0
    assert body["items"][0]["openDocuments"] == 0
    assert body["items"][0]["openQueries"] == 0

    second_page = client.get(
        f"/api/v1/clients?platform=firm&email={firm_email}&page=2&page_size=10"
    )
    assert second_page.status_code == 200
    page_two = second_page.json()
    assert len(page_two["items"]) == 10
    assert page_two["page"] == 2
    first_ids = {item["id"] for item in body["items"]}
    second_ids = {item["id"] for item in page_two["items"]}
    assert first_ids.isdisjoint(second_ids)
    assert any(item["id"] in created_ids for item in page_two["items"])


def test_search_filters_clients_and_resets_total():
    firm_email = _firm_email("search")
    target_id = _create_client("Acme Holdings BV", kvk="99887766")
    _create_client("Other Company")

    res = client.get(
        f"/api/v1/clients?platform=firm&email={firm_email}&search=acme&page=1&page_size=20"
    )
    assert res.status_code == 200
    body = res.json()
    assert body["total"] >= 1
    assert any(item["id"] == target_id for item in body["items"])
    assert all("acme" in item["name"].lower() for item in body["items"])


def _set_connection_status(client_id: str, status: str) -> None:
    ensure_connection_row(client_id)
    with SessionLocal() as session:
        row = session.scalar(
            select(SnelStartConnectionRow).where(SnelStartConnectionRow.client_id == client_id)
        )
        assert row is not None
        row.status = status
        session.commit()


def test_connected_filter_limits_results():
    firm_email = _firm_email("connected")
    connected = store.create_client("Connected Co")
    disconnected = store.create_client("Disconnected Co")
    _set_connection_status(connected.id, "connected")
    _set_connection_status(disconnected.id, "not_connected")

    res = client.get(
        f"/api/v1/clients?platform=firm&email={firm_email}&connected=true&page=1&page_size=50"
    )
    assert res.status_code == 200
    body = res.json()
    ids = {item["id"] for item in body["items"]}
    assert connected.id in ids
    assert disconnected.id not in ids


def test_client_portal_cannot_list_clients():
    client_email = "portal-list@test.com"
    client_id = _create_client("Portal Client", email=client_email)
    user_service.ensure_user(
        platform="client",
        email=client_email,
        name="Portal User",
        client_id=client_id,
    )

    res = client.get(f"/api/v1/clients?platform=client&email={client_email}&page=1&page_size=20")
    assert res.status_code == 403


def test_unauthenticated_firm_list_is_rejected():
    res = client.get("/api/v1/clients?platform=firm&email=missing-user@test.com&page=1&page_size=20")
    assert res.status_code == 403


def test_page_size_is_capped():
    firm_email = _firm_email("page-size")
    res = client.get(
        f"/api/v1/clients?platform=firm&email={firm_email}&page=1&page_size=100"
    )
    assert res.status_code == 422
