from fastapi import HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from sqlalchemy import and_,update
import time
from fastapi import Request
from sqlalchemy import literal_column, desc
import anyio
from app.utils.responses import custom_response

from app.models.user import User
from app.models.user_device import UserDevice
from app.models.user_device_login import UserDeviceLogin
from typing import Optional

def now_epoch():
    return int(time.time())

async def get_user_device_data(
    device_unique_id: str,
    db: AsyncSession,
    user_id: Optional[str] = None
):
    print(f"Fetching user device data for unique_id: {device_unique_id}, user_id: {user_id}")  # Debug log
    """
    Optimized, fully non-blocking helper:
    - Uses an asynchronous SQLAlchemy query directly.
    - Selects only required columns.
    - Uses a single ordered lookup (latest login) with LIMIT 1.
    - Returns a plain dict or None.
    """
    try:

        stmt = (
            select(
                User.user_id,
                User.signup_type,
                User.social_id,
                User.firstname,
                User.lastname,
                User.fullname,
                User.auth_key,
                User.email,
                User.profilepic,
                User.is_profile_completed,
                User.is_new_user,
                UserDevice.user_device_id,
                UserDevice.device_unique_id,
                UserDevice.device_name,
                UserDevice.device_token,
                UserDevice.device_type,
                UserDevice.app_version,
            )
            .select_from(UserDevice)
            .join(
                UserDeviceLogin,
                UserDeviceLogin.user_device_id == UserDevice.user_device_id,
            )
            .outerjoin(
                User,
                (UserDeviceLogin.user_id == User.user_id) & (User.is_deleted == 0)
            )
            .filter(
                and_(
                    UserDevice.device_unique_id == device_unique_id,
                    UserDeviceLogin.logout_at == None
                )
            )
            .order_by(desc(UserDeviceLogin.created_at))
            .limit(1)
        )

        # Execute the query asynchronously and fetch the first result
        result = await db.execute(stmt)
        row = result.first()

        print(f"Row fetched >>>>>>>>>>>>>>>>>>>>>>>: {row}")  # Debug log
        
        if not row:
            return None
        # Return a dictionary directly
        return dict(row._mapping)
    
    except Exception as e:
        await db.rollback()
        return custom_response(401,message=f"Error fetching user device data: {str(e)}")


async def get_user_device_data_guest(
    device_unique_id: str,
    db: AsyncSession,
    user_id: Optional[str] = None
):
    print(f"Fetching user device data for unique_id: {device_unique_id}, user_id: {user_id}")  # Debug log
    """
    Optimized, fully non-blocking helper:
    - Uses an asynchronous SQLAlchemy query directly.
    - Selects only required columns.
    - Uses a single ordered lookup (latest login) with LIMIT 1.
    - Returns a plain dict or None.
    """
    try:
        # Step 1: Check and update existing active session for this device
        update_stmt = (
            update(UserDeviceLogin)
            .where(
                and_(
                    UserDeviceLogin.user_device_id == select(UserDevice.user_device_id)
                        .where(UserDevice.device_unique_id == device_unique_id)
                        .scalar_subquery(),
                    UserDeviceLogin.user_id.isnot(None),
                    UserDeviceLogin.logout_at.is_(None)
                )
            )
            .values(
                user_id=None,
                logout_at=now_epoch()
            )
        )

        await db.execute(update_stmt)
        await db.commit()

        stmt = (
            select(
                User.user_id,
                User.signup_type,
                User.social_id,
                User.firstname,
                User.lastname,
                User.fullname,
                User.auth_key,
                User.email,
                User.profilepic,
                User.is_profile_completed,
                User.is_new_user,
                UserDevice.user_device_id,
                UserDevice.device_unique_id,
                UserDevice.device_name,
                UserDevice.device_token,
                UserDevice.device_type,
                UserDevice.app_version,
            )
            .select_from(UserDevice)
            .join(
                UserDeviceLogin,
                UserDeviceLogin.user_device_id == UserDevice.user_device_id,
            )
            .outerjoin(
                User,
                (UserDeviceLogin.user_id == User.user_id) & (User.is_deleted == 0)
            )
            .filter(
                and_(
                    UserDevice.device_unique_id == device_unique_id,
                    UserDeviceLogin.logout_at == None
                )
            )
            .order_by(desc(UserDeviceLogin.created_at))
            .limit(1)
        )

        # Execute the query asynchronously and fetch the first result
        result = await db.execute(stmt)
        row = result.first()

        print(f"Row fetched >>>>>>>>>>>>>>>>>>>>>>>: {row}")  # Debug log
        
        if not row:
            return None
        # Return a dictionary directly
        return dict(row._mapping)
    
    except Exception as e:
        await db.rollback()
        return custom_response(401,message=f"Error fetching user device data: {str(e)}")
