"""Admin service — whitelist validation and user management.

⚠️ AUTO-GENERATED BY PRISM - DO NOT EDIT
"""

from __future__ import annotations

import re
from typing import Sequence

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

from {{ project_name }}.admin.whitelist_model import SignupWhitelist
from {{ project_name }}.models.{{ user_model_snake }} import {{ user_model }}


async def validate_signup_access(email: str, db: AsyncSession) -> bool:
    """Check whether an email is allowed to sign up.

    In 'open' mode this always returns True.  In 'whitelist' mode the
    email must match at least one whitelist rule stored in the database.
    In 'invite_only' mode signup is disabled entirely (returns False).

    The signup_access mode is baked into the generated code at generation
    time via the template variable ``signup_access_mode``.
    """
{% if signup_access_mode == "open" %}
    return True
{% elif signup_access_mode == "invite_only" %}
    return False
{% else %}
    # Whitelist mode — check rules
    result = await db.execute(select(SignupWhitelist))
    rules = result.scalars().all()

    if not rules:
        # No rules means nobody is whitelisted
        return False

    for rule in rules:
        if rule.rule_type == "email" and rule.value.lower() == email.lower():
            return True
        elif rule.rule_type == "domain":
            domain = email.split("@")[-1].lower()
            if domain == rule.value.lower():
                return True
        elif rule.rule_type == "pattern" and re.match(
            rule.value, email, re.IGNORECASE
        ):
            return True

    return False
{% endif %}


# ── User management helpers ─────────────────────────────────────


async def list_users(
    db: AsyncSession, *, skip: int = 0, limit: int = 50
) -> Sequence[{{ user_model }}]:
    """Return paginated user list."""
    result = await db.execute(
        select({{ user_model }}).offset(skip).limit(limit).order_by({{ user_model }}.id)
    )
    return result.scalars().all()


async def count_users(db: AsyncSession) -> int:
    """Return total user count."""
    result = await db.execute(select(func.count({{ user_model }}.id)))
    return result.scalar_one()


async def get_user_by_id(db: AsyncSession, user_id: int) -> {{ user_model }} | None:
    """Return a single user by ID."""
    result = await db.execute(select({{ user_model }}).where({{ user_model }}.id == user_id))
    return result.scalar_one_or_none()


async def update_user_roles(
    db: AsyncSession, user_id: int, roles: list[str]
) -> {{ user_model }} | None:
    """Update a user's roles."""
    user = await get_user_by_id(db, user_id)
    if user:
        user.roles = roles
        await db.commit()
        await db.refresh(user)
    return user


async def set_user_active(
    db: AsyncSession, user_id: int, *, is_active: bool
) -> {{ user_model }} | None:
    """Activate or deactivate a user."""
    user = await get_user_by_id(db, user_id)
    if user:
        user.is_active = is_active
        await db.commit()
        await db.refresh(user)
    return user


async def delete_user(db: AsyncSession, user_id: int) -> bool:
    """Hard-delete a user. Returns True if deleted."""
    user = await get_user_by_id(db, user_id)
    if not user:
        return False
    await db.delete(user)
    await db.commit()
    return True


# ── Whitelist CRUD ───────────────────────────────────────────────


async def list_whitelist_rules(db: AsyncSession) -> Sequence[SignupWhitelist]:
    """Return all whitelist rules."""
    result = await db.execute(
        select(SignupWhitelist).order_by(SignupWhitelist.id)
    )
    return result.scalars().all()


async def add_whitelist_rule(
    db: AsyncSession, *, rule_type: str, value: str, created_by: str | None = None
) -> SignupWhitelist:
    """Add a new whitelist rule."""
    rule = SignupWhitelist(rule_type=rule_type, value=value, created_by=created_by)
    db.add(rule)
    await db.commit()
    await db.refresh(rule)
    return rule


async def delete_whitelist_rule(db: AsyncSession, rule_id: int) -> bool:
    """Delete a whitelist rule. Returns True if deleted."""
    result = await db.execute(
        delete(SignupWhitelist).where(SignupWhitelist.id == rule_id)
    )
    await db.commit()
    return result.rowcount > 0
