import uuid

from sqlalchemy import select
from sqlalchemy.orm import Session

from . import models, schemas, security


def _new_registration_id() -> str:
    return "CY26-" + uuid.uuid4().hex[:8].upper()


def create_registration(db: Session, data: schemas.RegistrationCreate) -> models.Registration:
    registration = models.Registration(
        registration_id=_new_registration_id(),
        **data.model_dump(),
    )
    db.add(registration)
    db.commit()
    db.refresh(registration)
    return registration


def list_registrations(db: Session, skip: int = 0, limit: int = 100) -> list[models.Registration]:
    stmt = (
        select(models.Registration)
        .order_by(models.Registration.registered_at.desc())
        .offset(skip)
        .limit(limit)
    )
    return list(db.scalars(stmt).all())


def get_registration(db: Session, registration_id: str) -> models.Registration | None:
    stmt = select(models.Registration).where(
        models.Registration.registration_id == registration_id
    )
    return db.scalars(stmt).first()


def delete_registration(db: Session, registration_id: str) -> bool:
    registration = get_registration(db, registration_id)
    if registration is None:
        return False
    db.delete(registration)
    db.commit()
    return True


# --- Contact messages -----------------------------------------------------

def create_contact_message(db: Session, data: schemas.ContactCreate) -> models.ContactMessage:
    contact = models.ContactMessage(**data.model_dump())
    db.add(contact)
    db.commit()
    db.refresh(contact)
    return contact


def list_contact_messages(db: Session, skip: int = 0, limit: int = 100) -> list[models.ContactMessage]:
    stmt = (
        select(models.ContactMessage)
        .order_by(models.ContactMessage.created_at.desc())
        .offset(skip)
        .limit(limit)
    )
    return list(db.scalars(stmt).all())


# --- Sponsorship requests -------------------------------------------------

def create_sponsorship_request(
    db: Session, data: schemas.SponsorshipCreate
) -> models.SponsorshipRequest:
    sponsorship = models.SponsorshipRequest(**data.model_dump())
    db.add(sponsorship)
    db.commit()
    db.refresh(sponsorship)
    return sponsorship


def list_sponsorship_requests(
    db: Session, skip: int = 0, limit: int = 100
) -> list[models.SponsorshipRequest]:
    stmt = (
        select(models.SponsorshipRequest)
        .order_by(models.SponsorshipRequest.created_at.desc())
        .offset(skip)
        .limit(limit)
    )
    return list(db.scalars(stmt).all())


# --- Admin users ----------------------------------------------------------

def get_admin(db: Session, admin_id: int) -> models.AdminUser | None:
    return db.get(models.AdminUser, admin_id)


def get_admin_by_email(db: Session, email: str) -> models.AdminUser | None:
    stmt = select(models.AdminUser).where(models.AdminUser.email == email)
    return db.scalars(stmt).first()


def list_admins(db: Session, skip: int = 0, limit: int = 100) -> list[models.AdminUser]:
    stmt = (
        select(models.AdminUser)
        .order_by(models.AdminUser.created_at.desc())
        .offset(skip)
        .limit(limit)
    )
    return list(db.scalars(stmt).all())


def create_admin(db: Session, data: schemas.AdminUserCreate) -> models.AdminUser:
    admin = models.AdminUser(
        email=data.email,
        name=data.name,
        role=data.role,
        hashed_password=security.hash_password(data.password),
    )
    db.add(admin)
    db.commit()
    db.refresh(admin)
    return admin


def update_admin(
    db: Session, admin: models.AdminUser, data: schemas.AdminUserUpdate
) -> models.AdminUser:
    if data.name is not None:
        admin.name = data.name
    if data.role is not None:
        admin.role = data.role
    if data.is_active is not None:
        admin.is_active = data.is_active
    if data.password is not None:
        admin.hashed_password = security.hash_password(data.password)
    db.commit()
    db.refresh(admin)
    return admin


def delete_admin(db: Session, admin: models.AdminUser) -> None:
    db.delete(admin)
    db.commit()


# --- Media assets ---------------------------------------------------------

def create_media_asset(
    db: Session,
    *,
    public_id: str,
    secure_url: str,
    title: str | None,
    category: str,
    format: str | None = None,
    width: int | None = None,
    height: int | None = None,
    bytes: int | None = None,
) -> models.MediaAsset:
    asset = models.MediaAsset(
        public_id=public_id,
        secure_url=secure_url,
        title=title,
        category=category,
        format=format,
        width=width,
        height=height,
        bytes=bytes,
    )
    db.add(asset)
    db.commit()
    db.refresh(asset)
    return asset


def list_media_assets(
    db: Session,
    *,
    category: str | None = None,
    skip: int = 0,
    limit: int = 200,
) -> list[models.MediaAsset]:
    stmt = select(models.MediaAsset).order_by(models.MediaAsset.created_at.desc())
    if category:
        stmt = stmt.where(models.MediaAsset.category == category)
    stmt = stmt.offset(skip).limit(limit)
    return list(db.scalars(stmt).all())


def get_media_asset(db: Session, asset_id: int) -> models.MediaAsset | None:
    return db.get(models.MediaAsset, asset_id)


def delete_media_asset(db: Session, asset: models.MediaAsset) -> None:
    db.delete(asset)
    db.commit()
