"""Tests für Reseller-Rolle + Mandantenverwaltung + RLS-Isolation."""
import uuid

import pytest
from httpx import AsyncClient
from sqlalchemy import text

from app.core.security import hash_password
from app.models.user import User, UserRole


async def _make_user(db, *, email, role, company_id=None, password="Secret123"):
    await db.execute(text("SET LOCAL app.bypass_rls = 'on'"))
    user = User(
        id=uuid.uuid4(), company_id=company_id, email=email,
        password_hash=hash_password(password),
        first_name=role.title(), last_name="User",
        role=UserRole(role), is_active=True,
    )
    db.add(user)
    await db.commit()
    return user.id


async def _login(client, email, password="Secret123"):
    r = await client.post("/api/v1/auth/login", json={"email": email, "password": password})
    assert r.status_code == 200, r.text
    return {"Authorization": f"Bearer {r.json()['access_token']}"}


@pytest.mark.asyncio(loop_scope="session")
async def test_superadmin_creates_reseller(client: AsyncClient, db_session):
    await _make_user(db_session, email="sa@platform.de", role="SUPER_ADMIN")
    h = await _login(client, "sa@platform.de")

    r = await client.post("/api/v1/admin/resellers", json={
        "email": "reseller-a@partner.de", "first_name": "Rita", "last_name": "Reseller",
    }, headers=h)
    assert r.status_code == 201, r.text
    assert r.json()["company_count"] == 0

    lst = await client.get("/api/v1/admin/resellers", headers=h)
    assert any(x["email"] == "reseller-a@partner.de" for x in lst.json())


@pytest.mark.asyncio(loop_scope="session")
async def test_reseller_creates_and_sees_only_own_company(client: AsyncClient, db_session):
    rid_a = await _make_user(db_session, email="res-a@p.de", role="RESELLER")
    rid_b = await _make_user(db_session, email="res-b@p.de", role="RESELLER")

    ha = await _login(client, "res-a@p.de")
    hb = await _login(client, "res-b@p.de")

    # Reseller A legt eine Firma an
    r = await client.post("/api/v1/reseller/companies", json={
        "name": "Alpha GmbH", "admin_email": "admin@alpha.de",
        "admin_first_name": "Al", "admin_last_name": "Pha",
    }, headers=ha)
    assert r.status_code == 201, r.text
    assert r.json()["name"] == "Alpha GmbH"

    # Reseller B legt eine andere Firma an
    r2 = await client.post("/api/v1/reseller/companies", json={
        "name": "Beta GmbH", "admin_email": "admin@beta.de",
        "admin_first_name": "Be", "admin_last_name": "Ta",
    }, headers=hb)
    assert r2.status_code == 201, r2.text

    # A sieht nur Alpha, NICHT Beta (RLS-Isolation)
    la = await client.get("/api/v1/reseller/companies", headers=ha)
    names_a = {c["name"] for c in la.json()}
    assert "Alpha GmbH" in names_a
    assert "Beta GmbH" not in names_a

    lb = await client.get("/api/v1/reseller/companies", headers=hb)
    names_b = {c["name"] for c in lb.json()}
    assert "Beta GmbH" in names_b
    assert "Alpha GmbH" not in names_b
    assert rid_a != rid_b


@pytest.mark.asyncio(loop_scope="session")
async def test_create_company_without_email_returns_temp_password(client: AsyncClient, db_session):
    await _make_user(db_session, email="res-noemail@p.de", role="RESELLER")
    h = await _login(client, "res-noemail@p.de")

    r = await client.post("/api/v1/reseller/companies", json={
        "name": "Delta GmbH", "admin_first_name": "De", "admin_last_name": "Lta",
    }, headers=h)
    assert r.status_code == 201, r.text
    body = r.json()
    assert body["initial_password"], "Temp-Passwort muss zurückgegeben werden"
    assert body["admin_email"], "Login-Kennung muss erzeugt werden"

    # Mit den generierten Zugangsdaten kann sich der Admin sofort einloggen
    ok = await client.post("/api/v1/auth/login", json={
        "email": body["admin_email"], "password": body["initial_password"],
    })
    assert ok.status_code == 200, ok.text


@pytest.mark.asyncio(loop_scope="session")
async def test_reseller_cannot_access_admin_endpoints(client: AsyncClient, db_session):
    await _make_user(db_session, email="res-c@p.de", role="RESELLER")
    h = await _login(client, "res-c@p.de")
    r = await client.get("/api/v1/admin/tenants", headers=h)
    assert r.status_code == 403


@pytest.mark.asyncio(loop_scope="session")
async def test_deactivated_tenant_blocks_login(client: AsyncClient, db_session):
    rid = await _make_user(db_session, email="res-d@p.de", role="RESELLER")
    h = await _login(client, "res-d@p.de")
    create = await client.post("/api/v1/reseller/companies", json={
        "name": "Gamma GmbH", "admin_email": "admin@gamma.de",
        "admin_first_name": "Ga", "admin_last_name": "Mma",
    }, headers=h)
    company_id = create.json()["id"]

    # Direkt einen aktiven Mitarbeiter in Gamma anlegen (per DB) und Login testen
    await _make_user(db_session, email="emp@gamma.de", role="EMPLOYEE", company_id=company_id)
    ok = await client.post("/api/v1/auth/login", json={"email": "emp@gamma.de", "password": "Secret123"})
    assert ok.status_code == 200

    # Firma deaktivieren → Login gesperrt
    await client.patch(f"/api/v1/reseller/companies/{company_id}", json={"is_active": False}, headers=h)
    blocked = await client.post("/api/v1/auth/login", json={"email": "emp@gamma.de", "password": "Secret123"})
    assert blocked.status_code == 403
    assert rid is not None
