import uuid
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from sqlalchemy.exc import IntegrityError

from app.domains.tenants.models import Tenant
from app.domains.auth.models import User


async def list_tenants(db: AsyncSession) -> list[dict]:
    """Return all tenants with user counts."""
    result = await db.execute(
        select(
            Tenant,
            func.count(User.id).label("user_count"),
        )
        .outerjoin(User, User.tenant_id == Tenant.id)
        .group_by(Tenant.id)
        .order_by(Tenant.created_at)
    )
    rows = result.all()
    tenants = []
    for tenant, user_count in rows:
        tenants.append({"tenant": tenant, "user_count": user_count})
    return tenants


async def get_tenant(db: AsyncSession, tenant_id: uuid.UUID) -> Tenant | None:
    result = await db.execute(select(Tenant).where(Tenant.id == tenant_id))
    return result.scalar_one_or_none()


async def create_tenant(db: AsyncSession, name: str, slug: str, is_active: bool = True) -> Tenant:
    tenant = Tenant(name=name, slug=slug, is_active=is_active)
    db.add(tenant)
    await db.commit()
    await db.refresh(tenant)
    return tenant


async def update_tenant(
    db: AsyncSession,
    tenant_id: uuid.UUID,
    name: str | None = None,
    slug: str | None = None,
    is_active: bool | None = None,
) -> Tenant | None:
    tenant = await get_tenant(db, tenant_id)
    if not tenant:
        return None
    if name is not None:
        tenant.name = name
    if slug is not None:
        tenant.slug = slug
    if is_active is not None:
        tenant.is_active = is_active
    await db.commit()
    await db.refresh(tenant)
    return tenant


async def delete_tenant(db: AsyncSession, tenant_id: uuid.UUID) -> bool:
    """Delete a tenant. Returns False if tenant has users or does not exist."""
    tenant = await get_tenant(db, tenant_id)
    if not tenant:
        return False
    # Check for users
    result = await db.execute(
        select(func.count(User.id)).where(User.tenant_id == tenant_id)
    )
    user_count = result.scalar_one()
    if user_count > 0:
        return False
    await db.delete(tenant)
    await db.commit()
    return True
