"""
Authentication Routes
User registration, login, OTP verification, and token management
"""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from sqlalchemy.ext.asyncio import AsyncSession

from app.database import get_db
from app.schemas.auth import (
    RegisterRequest,
    LoginRequest,
    OTPSendRequest,
    OTPVerifyRequest,
    RefreshTokenRequest,
    TokenResponse,
    VerifyOTPResponse,
    SocialLoginRequest,
    UserProfileUpdate,
    DeleteAccountRequest,
)
from app.schemas.user import UserResponse
from app.schemas.common import MessageResponse
from app.services.auth_service import AuthService
from app.utils.dependencies import get_current_user
from app.models.user import User
from app.config import settings

router = APIRouter()


@router.post("/send-otp", response_model=MessageResponse)
async def send_otp(
    data: OTPSendRequest,
    db: AsyncSession = Depends(get_db)
):
    """
    Step 1 — Send OTP to **phone** only. Creates a placeholder account if none exists yet.
    """
    try:
        await AuthService.send_otp(db, phone=data.phone, email=None)
        return MessageResponse(message="OTP sent successfully")
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))


@router.post("/verify-otp", response_model=VerifyOTPResponse)
async def verify_otp(
    data: OTPVerifyRequest,
    db: AsyncSession = Depends(get_db)
):
    """
    Step 2 — Verify OTP; returns **access_token**, **refresh_token**, flat profile fields
    (`email`, `phone`, `first_name`, `last_name`, …), and nested **`user`** (full `UserResponse`).
    """
    try:
        user = await AuthService.verify_otp(
            db,
            phone=data.phone,
            email=None,
            otp=data.otp
        )
        access_token = AuthService.create_access_token(user.id, user.role.value)
        refresh_token = AuthService.create_refresh_token(user.id)
        user.refresh_token = refresh_token
        await db.flush()

        res = await db.execute(
            select(User)
            .where(User.id == user.id)
            .options(selectinload(User.wallet), selectinload(User.driver_profile))
        )
        u = res.scalar_one()
        wallet_balance = u.wallet.balance if u.wallet else None
        driver_info = None
        if u.driver_profile:
            driver_info = {
                "status": u.driver_profile.status.value,
                "is_online": u.driver_profile.is_online,
                "average_rating": u.driver_profile.average_rating,
            }
        ur = UserResponse.from_orm_with_extras(
            u, wallet_balance=wallet_balance, driver_info=driver_info
        )
        role_str = ur.role.value if hasattr(ur.role, "value") else str(ur.role)
        exp = settings.access_token_expire_minutes * 60
        return VerifyOTPResponse(
            access_token=access_token,
            refresh_token=refresh_token,
            expires_in=exp,
            user_id=ur.id,
            role=role_str,
            email=ur.email,
            phone=ur.phone,
            first_name=ur.first_name,
            last_name=ur.last_name,
            full_name=ur.full_name,
            profile_picture=ur.profile_picture,
            is_active=ur.is_active,
            is_verified=ur.is_verified,
            is_phone_verified=ur.is_phone_verified,
            is_email_verified=ur.is_email_verified,
            created_at=ur.created_at,
            wallet_balance=ur.wallet_balance,
            user=ur,
        )
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))


@router.post("/register", response_model=TokenResponse, status_code=status.HTTP_201_CREATED)
async def register(
    data: RegisterRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """
    Step 3 — Complete signup. Requires **Authorization: Bearer \<access_token from verify-otp\>**.
    **profile_picture_base64** is required (JPEG/PNG/WebP as raw base64 or `data:image/...;base64,...`).
    Optional profile fields (**first_name**, **email**, etc.) must not conflict with the verified phone.
    """
    try:
        user, access_token, refresh_token = await AuthService.register_user(db, data, current_user)
        
        return TokenResponse(
            access_token=access_token,
            refresh_token=refresh_token,
            expires_in=settings.access_token_expire_minutes * 60,
            user_id=user.id,
            role=user.role.value
        )
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))


@router.post("/login", response_model=TokenResponse)
async def login(
    data: LoginRequest,
    db: AsyncSession = Depends(get_db)
):
    """
    Login with email or phone (no password). Account must be OTP-verified.

    Returns access and refresh tokens.
    """
    try:
        user, access_token, refresh_token = await AuthService.login(
            db,
            email=data.email,
            phone=data.phone,
            fcm_token=data.fcm_token
        )
        
        return TokenResponse(
            access_token=access_token,
            refresh_token=refresh_token,
            expires_in=1800,
            user_id=user.id,
            role=user.role.value
        )
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))


@router.post("/refresh-token", response_model=TokenResponse)
async def refresh_token(
    data: RefreshTokenRequest,
    db: AsyncSession = Depends(get_db)
):
    """
    Refresh access token using refresh token.
    """
    try:
        access_token, new_refresh_token = await AuthService.refresh_tokens(db, data.refresh_token)
        
        # Get user info from new token
        payload = AuthService.decode_token(access_token)
        
        return TokenResponse(
            access_token=access_token,
            refresh_token=new_refresh_token,
            expires_in=1800,
            user_id=int(payload["sub"]),
            role=payload["role"]
        )
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))


@router.post("/social-login", response_model=TokenResponse)
async def social_login(
    data: SocialLoginRequest,
    db: AsyncSession = Depends(get_db)
):
    """
    Login/Register using social OAuth provider (Google, Facebook, Apple).
    """
    # TODO: Implement social OAuth verification
    raise HTTPException(
        status_code=status.HTTP_501_NOT_IMPLEMENTED,
        detail="Social login not yet implemented"
    )


@router.post("/logout", response_model=MessageResponse)
async def logout(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Logout user and invalidate refresh token.
    """
    await AuthService.logout(db, current_user.id)
    return MessageResponse(message="Logged out successfully")


@router.delete("/account", response_model=MessageResponse)
async def delete_account(
    data: DeleteAccountRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Delete user account and related data. Works for both Driver and Passenger.
    """
    if not data.confirm_delete:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Confirmation required to delete account"
        )
    try:
        await AuthService.delete_account(db, current_user.id)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    return MessageResponse(message="Account deleted successfully")


@router.get("/me", response_model=UserResponse)
async def get_current_user_profile(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Get current authenticated user's profile.
    """
    # Get wallet balance
    wallet_balance = None
    if current_user.wallet:
        wallet_balance = current_user.wallet.balance
    
    # Get driver info if applicable
    driver_info = None
    if current_user.driver_profile:
        driver_info = {
            "status": current_user.driver_profile.status.value,
            "is_online": current_user.driver_profile.is_online,
            "average_rating": current_user.driver_profile.average_rating,
        }
    
    return UserResponse.from_orm_with_extras(
        current_user,
        wallet_balance=wallet_balance,
        driver_info=driver_info
    )


@router.put("/profile", response_model=UserResponse)
async def update_user_profile(
    data: UserProfileUpdate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Update current authenticated user's profile.
    """
    try:
        user = await AuthService.update_profile(db, current_user.id, data)
        
        # Get extra info for response
        wallet_balance = None
        if user.wallet:
            wallet_balance = user.wallet.balance
        
        driver_info = None
        if user.driver_profile:
            driver_info = {
                "status": user.driver_profile.status.value,
                "is_online": user.driver_profile.is_online,
                "average_rating": user.driver_profile.average_rating,
            }
            
        return UserResponse.from_orm_with_extras(
            user,
            wallet_balance=wallet_balance,
            driver_info=driver_info
        )
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
