import secrets
from sqlmodel import Session, select
from app.models.models import User, UserActivity
from app.core.security import get_password_hash

def get_user_by_username(session: Session, username: str):
    statement = select(User).where(User.username == username)
    return session.exec(statement).one_or_none()

def create_user(session: Session, user_create):
    db_user = User(
        username=user_create.username,
        password_hash=get_password_hash(user_create.password),
        display_name=user_create.username,
        email=getattr(user_create, 'email', None) or None,
        community_role='mentee',
    )
    session.add(db_user)
    session.commit()
    session.refresh(db_user)
    return db_user

def log_activity(session: Session, user_id: int, action: str, details: str = None):
    activity = UserActivity(user_id=user_id, action=action, details=details)
    session.add(activity)
    session.commit()
    session.refresh(activity)
    return activity

def get_user_activity(session: Session, user_id: int, limit: int = 50):
    statement = (
        select(UserActivity)
        .where(UserActivity.user_id == user_id)
        .order_by(UserActivity.timestamp.desc())
        .limit(limit)
    )
    return session.exec(statement).all()


def get_user_by_email(session: Session, email: str):
    statement = select(User).where(User.email == email)
    return session.exec(statement).one_or_none()


def get_user_by_reset_token(session: Session, token: str):
    statement = select(User).where(User.reset_token == token)
    return session.exec(statement).one_or_none()


def get_user_by_google_id(session: Session, google_id: str):
    statement = select(User).where(User.google_id == google_id)
    return session.exec(statement).one_or_none()


def get_or_create_google_user(session: Session, google_id: str, email: str, display_name: str) -> User:
    import re

    def sanitize_username(name: str, fallback_email: str) -> str:
        """Derive a clean username from display name or email local part."""
        if name and '@' not in name:
            u = re.sub(r'\s+', '_', name.lower().strip())
            u = re.sub(r'[^a-z0-9_]', '', u).strip('_')
            u = re.sub(r'_+', '_', u)
            return u or fallback_email.split('@')[0].lower()
        return fallback_email.split('@')[0].lower() if fallback_email else "user"

    desired_username = sanitize_username(display_name, email)

    # 1. Look up by google_id — update display_name on every login
    user = get_user_by_google_id(session, google_id)
    if user:
        changed = False
        if display_name and user.display_name != display_name:
            user.display_name = display_name
            changed = True
        if changed:
            session.add(user)
            session.commit()
            session.refresh(user)
        return user

    # 2. Look up by email (link to existing account)
    if email:
        statement = select(User).where(User.email == email)
        user = session.exec(statement).one_or_none()
        if user:
            user.google_id = google_id
            if display_name:
                user.display_name = display_name
            session.add(user)
            session.commit()
            session.refresh(user)
            return user

    # 3. Create new user
    username = desired_username
    counter = 1
    while get_user_by_username(session, username):
        username = f"{desired_username}_{counter}"
        counter += 1

    placeholder_hash = get_password_hash(secrets.token_hex(32))
    new_user = User(
        username=username,
        password_hash=placeholder_hash,
        email=email,
        google_id=google_id,
        display_name=display_name or username,
        community_role='mentee',
    )
    session.add(new_user)
    session.commit()
    session.refresh(new_user)
    return new_user
