# app/services/user_device_login.py
import time
from typing import Optional
from fastapi import HTTPException, Request
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from pydantic import BaseModel
from app.utils.responses import custom_response

# adjust this import to match your project layout
from app.crud import crud
from app.models.user_device_login import UserDeviceLogin


# Minimal Pydantic payloads so we can reuse crud.create / crud.update
class LoginCreate(BaseModel):
    user_id: Optional[int]  # None for guest
    user_device_id: int
    login_ip: str
    login_at: int
    created_at: int

class LoginUpdate(BaseModel):
    login_ip: str
    login_at: int
    logout_at: Optional[int] = None
    logout_ip: Optional[str] = None


async def update_or_create_login(user_device_id: int, user_id: Optional[int], request: Request, db: AsyncSession):
    """
    Asynchronously upserts a login row for (user_device_id, user_id).
    - If found: update login_ip/login_at
    - If not:  create new row with created_at/login_at
    Uses generic CRUD helpers for DB writes; single session; rollback on failure.
    """
    try:
        # Use asynchronous select statement
        stmt = select(UserDeviceLogin).filter(
            UserDeviceLogin.user_device_id == user_device_id,
            UserDeviceLogin.user_id == user_id,
        )
        result = await db.execute(stmt)

        existing_login = result.scalars().first()
        print("result:", existing_login)  # Debug log

        now = int(time.time())
        ip_address = request.client.host if request.client else "unknown"

        if existing_login:
            # UPDATE via async crud.update
            update_payload = LoginUpdate(
                login_ip=ip_address,
                login_at=now,
                logout_at=None,
                logout_ip=None
            )
            await crud.update(db=db, db_record=existing_login, updated_data=update_payload)
            return existing_login
        else:
            # CREATE via async crud.create
            create_payload = LoginCreate(
                user_id=user_id,
                user_device_id=user_device_id,
                login_ip=ip_address,
                login_at=now,
                created_at=now,
            )
            created = await crud.create(db=db, model=UserDeviceLogin, schema=create_payload)
            return created

    except HTTPException as e:
        msg = e.detail if isinstance(e.detail, str) else "HTTP error"
        return custom_response(e.status_code, message=msg)
    except Exception as e:
        await db.rollback()
        return custom_response(401,message=f"Error updating or creating login entry: {str(e)}")
