"""Authentication endpoints."""

from datetime import datetime

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session

from app.api.deps import get_current_admin, get_db
from app.schemas.admin import AdminLogin, AdminResponse, Token
from app.schemas.user import UserLogin, UserResponse
from app.schemas.common import ErrorResponse, SuccessResponse
from app.utils.security import (
    create_access_token,
    create_refresh_token,
    get_password_hash,
    verify_password,
)

router = APIRouter(prefix="/auth/admin", tags=["authentication"])

# Unified auth router for all user types
unified_router = APIRouter(prefix="/auth", tags=["authentication"])


@router.post("/login", response_model=SuccessResponse)
async def login(
    login_data: AdminLogin,
    db: Session = Depends(get_db),
):
    """Admin login endpoint."""
    from app.models.admin_user import AdminUser
    
    # Find user by username or email
    user = db.query(AdminUser).filter(
        (AdminUser.username == login_data.username) | (AdminUser.email == login_data.username)
    ).first()
    
    if not user or not verify_password(login_data.password, user.password_hash):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid username or password",
        )
    
    if not user.is_active:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Account is inactive. Contact support or an administrator.",
        )
    
    # Update last login
    user.last_login = datetime.utcnow()
    db.commit()
    
    # Create tokens
    token_data = {"sub": str(user.id), "username": user.username, "role": user.role.value}
    access_token = create_access_token(token_data)
    refresh_token = create_refresh_token(token_data)
    
    # Convert AdminUser to dict for AdminResponse
    user_dict = {
        "id": str(user.id),
        "username": user.username,
        "email": user.email,
        "role": user.role.value,  # Convert enum to string value
        "is_active": user.is_active,
        "last_login": user.last_login.isoformat() if user.last_login else None,  # Convert datetime to ISO string
    }
    
    return SuccessResponse(
        data={
            "access_token": access_token,
            "refresh_token": refresh_token,
            "token_type": "bearer",
            "user": AdminResponse.model_validate(user_dict).model_dump(),
        },
        message="Login successful",
    )


@router.post("/logout", response_model=SuccessResponse)
async def logout(
    current_admin = Depends(get_current_admin),
):
    """Admin logout endpoint (client should discard token)."""
    return SuccessResponse(
        data=None,
        message="Logout successful",
    )


@router.get("/me", response_model=SuccessResponse)
async def get_current_user(
    current_admin = Depends(get_current_admin),
):
    """Get current authenticated admin user."""
    # Convert AdminUser to dict for AdminResponse
    user_dict = {
        "id": str(current_admin.id),
        "username": current_admin.username,
        "email": current_admin.email,
        "role": current_admin.role.value,  # Convert enum to string value
        "is_active": current_admin.is_active,
        "last_login": current_admin.last_login.isoformat() if current_admin.last_login else None,  # Convert datetime to ISO string
    }
    return SuccessResponse(
        data=AdminResponse.model_validate(user_dict).model_dump(),
        message="User retrieved successfully",
    )


@router.post("/refresh", response_model=SuccessResponse)
async def refresh_token(
    refresh_token: str,
    db: Session = Depends(get_db),
):
    """Refresh access token using refresh token."""
    from app.models.admin_user import AdminUser
    from app.utils.security import verify_token
    
    payload = verify_token(refresh_token, token_type="refresh")
    if not payload:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid refresh token",
        )
    
    user_id = payload.get("sub")
    user = db.query(AdminUser).filter(AdminUser.id == user_id).first()
    
    if not user or not user.is_active:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Account is inactive. Contact support or an administrator.",
        )
    
    # Create new access token
    token_data = {"sub": str(user.id), "username": user.username, "role": user.role.value}
    access_token = create_access_token(token_data)
    
    return SuccessResponse(
        data={
            "access_token": access_token,
            "token_type": "bearer",
        },
        message="Token refreshed successfully",
    )


# Unified login endpoint for all user types
@unified_router.post("/login", response_model=SuccessResponse)
async def unified_login(
    login_data: UserLogin,
    db: Session = Depends(get_db),
):
    """Unified login endpoint for all user types (admin and regular users)."""
    import traceback
    from app.models.user import User
    from app.models.admin_user import AdminUser
    
    try:
        # Try AdminUser first
        admin_user = db.query(AdminUser).filter(
            (AdminUser.username == login_data.email) | (AdminUser.email == login_data.email)
        ).first()
        
        if admin_user and verify_password(login_data.password, admin_user.password_hash):
            if not admin_user.is_active:
                raise HTTPException(
                    status_code=status.HTTP_403_FORBIDDEN,
                    detail="Account is inactive. Contact support or an administrator.",
                )
            
            # Update last login
            admin_user.last_login = datetime.utcnow()
            db.commit()
            
            # Create tokens
            token_data = {
                "sub": str(admin_user.id),
                "username": admin_user.username,
                "role": admin_user.role.value,
                "user_type": "admin"
            }
            access_token = create_access_token(token_data)
            refresh_token = create_refresh_token(token_data)
            
            # Convert AdminUser to dict for AdminResponse
            admin_user_dict = {
                "id": str(admin_user.id),
                "username": admin_user.username,
                "email": admin_user.email,
                "role": admin_user.role.value,  # Convert enum to string value
                "is_active": admin_user.is_active,
                "last_login": admin_user.last_login.isoformat() if admin_user.last_login else None,  # Convert datetime to ISO string
            }
            
            return SuccessResponse(
                data={
                    "access_token": access_token,
                    "refresh_token": refresh_token,
                    "token_type": "bearer",
                    "user": AdminResponse.model_validate(admin_user_dict).model_dump(),
                    "user_type": "admin",
                },
                message="Login successful",
            )
        
        # Try regular User
        user = db.query(User).filter(User.email == login_data.email).first()
        
        if user and verify_password(login_data.password, user.password_hash):
            if not user.is_active:
                raise HTTPException(
                    status_code=status.HTTP_403_FORBIDDEN,
                    detail="Account is inactive. Contact support or an administrator.",
                )
            
            # Update last login
            user.last_login = datetime.utcnow()
            db.commit()
            
            # Create tokens
            token_data = {
                "sub": str(user.id),
                "email": user.email,
                "user_type": user.user_type.value
            }
            access_token = create_access_token(token_data)
            refresh_token = create_refresh_token(token_data)
            
            # Convert User to dict matching UserResponse schema
            user_dict = {
                "id": str(user.id),
                "email": user.email,
                "userType": user.user_type.value,
                "matricNumber": user.matric_number,
                "applicationId": user.application_id,
                "isActive": user.is_active,
                "lastLogin": user.last_login.isoformat() if user.last_login else None,
                "createdAt": user.created_at.isoformat() if user.created_at else datetime.utcnow().isoformat(),
                "updatedAt": user.updated_at.isoformat() if user.updated_at else datetime.utcnow().isoformat(),
            }
            
            return SuccessResponse(
                data={
                    "access_token": access_token,
                    "refresh_token": refresh_token,
                    "token_type": "bearer",
                    "user": UserResponse.model_validate(user_dict).model_dump(),
                    "user_type": user.user_type.value,
                },
                message="Login successful",
            )
        
        # No user found
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid email or password",
        )
    except HTTPException:
        # Re-raise HTTP exceptions (they already have proper status codes)
        raise
    except Exception as e:
        # Log any unexpected errors
        print(f"Error in unified_login: {e}")
        print(traceback.format_exc())
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Internal server error: {str(e)}",
        )
