import logging

from pydantic import EmailStr, TypeAdapter, ValidationError
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.core.config import settings
from app.core.security import hash_password
from app.models.user import User
from app.repositories.rbac_repository import RbacRepository
from app.services.audit_service import write_audit_log

logger = logging.getLogger(__name__)

email_adapter = TypeAdapter(EmailStr)


def bootstrap_initial_admin(db: Session) -> None:
    active_user_exists = db.scalar(select(User.id).where(User.is_active.is_(True)).limit(1))
    if active_user_exists is not None:
        logger.info("initial_admin.skipped_active_user_exists")
        return

    username = (settings.initial_admin_username or "").strip()
    email = (settings.initial_admin_email or "").strip()
    password = settings.initial_admin_password or ""

    if not username or not email or not password:
        logger.warning(
            "initial_admin.not_configured",
            extra={"reason": "missing_required_initial_admin_environment"},
        )
        return

    try:
        normalized_email = str(email_adapter.validate_python(email))
    except ValidationError:
        logger.warning("initial_admin.invalid_email")
        return

    administrator_role = RbacRepository.get_role_by_name(db, "administrator")
    if administrator_role is None:
        logger.warning("initial_admin.missing_administrator_role")
        return

    existing_user = db.scalar(select(User).where((User.username == username) | (User.email == normalized_email)))
    if existing_user is not None:
        logger.info("initial_admin.skipped_user_already_exists")
        return

    admin = User(
        first_name=settings.initial_admin_first_name.strip(),
        last_name=settings.initial_admin_last_name.strip(),
        username=username,
        email=normalized_email,
        password_hash=hash_password(password),
        role="administrator",
        role_id=administrator_role.id,
        is_active=True,
    )
    db.add(admin)
    db.commit()
    db.refresh(admin)

    write_audit_log(
        db,
        action="users.initial_admin_bootstrap",
        entity_type="users",
        entity_id=admin.id,
        entity_label=admin.username,
        actor_username="system",
        after_data={
            "id": admin.id,
            "username": admin.username,
            "email": admin.email,
            "role": admin.role,
            "role_id": admin.role_id,
            "is_active": admin.is_active,
        },
        metadata={"source": "initial_admin_bootstrap"},
    )
    logger.info("initial_admin.created", extra={"user_id": admin.id})
