#auth_router.py
from fastapi import APIRouter, Depends, HTTPException, Header
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session
from datetime import datetime
from src.utils.db import get_db
from src.apps.auth.services import create_access_token
from src.apps.auth.models import UserSession,PasswordResetToken
from src.apps.users.models import User
from src.apps.auth.schemas import LoginTokenRequest, TokenRequest,UserDetailsResponse, BranchInfo
from src.apps.auth.controller import verify_password, get_current_user, oauth2_scheme,decode_access_token
import traceback

import secrets

from fastapi import APIRouter, Depends,status
from src.apps.auth.schemas import ForgotPasswordRequest, PasswordReset, PasswordResetResponse
from src.apps.auth.controller import forgot_password, reset_password
from src.apps.auth.services import hash_password
from src.apps.stores.models import Branch, Store

router = APIRouter()




@router.post("/login", response_model=dict)
def login(
    credentials: OAuth2PasswordRequestForm = Depends(),
    db: Session = Depends(get_db)
):
    try:
        user = db.query(User).filter(User.email == credentials.username).first()
        if not user:
            return {
                "status": False,
                "code": 404,
                "message": "User not found",
                "data": {}
            }

        if not verify_password(credentials.password, user.password_hash):
            return {
                "status": False,
                "code": 401,
                "message": "Invalid credentials",
                "data": {}
            }

        # Delete old sessions
        db.query(UserSession).filter(UserSession.user_id == user.user_id).delete()

        # Create JWT token
        jwt_token = create_access_token({"sub": user.email})

        # Generate unique 4–5 digit login_token
        import random
        while True:
            login_code = str(random.randint(1000, 99999))
            existing_token = db.query(UserSession).filter(UserSession.login_code == login_code).first()
            if not existing_token:
                break

        # Store tokens
        session = UserSession(
            user_id=user.user_id,
            token=jwt_token,
            login_code=login_code,
            is_login_code_used=False,
            created_at=datetime.utcnow()
        )
        db.add(session)
        db.commit()

        return {
            "status": True,
            "code": 200,
            "message": "Login successful",
            "access_token": jwt_token,
            "token_type": "bearer",
            "data": {
                "access_token": jwt_token,
                "login_code": login_code,
                "token_type": "bearer"
            }
        }

    except Exception as e:
        print("ERROR:", str(e))
        print(traceback.format_exc())
        return {
            "status": False,
            "code": 500,
            "message": str(e),
            "data": {}
        }



@router.post("/use-login-code", response_model=dict)
def use_login_code(
    request: LoginTokenRequest,
    db: Session = Depends(get_db)
):
    try:
        session = db.query(UserSession).filter(
            UserSession.login_code == request.login_code
        ).first()

        if not session:
            return {
                "status": False,
                "code": 404,
                "message": "Invalid login code",
                "data": {}
            }

        if session.is_login_code_used:
            return {
                "status": False,
                "code": 400,
                "message": "Login code has already been used",
                "data": {}
            }

        user = db.query(User).filter(User.user_id == session.user_id).first()
        if not user:
            return {
                "status": False,
                "code": 404,
                "message": "User not found",
                "data": {}
            }

        # Mark token as used
        session.is_login_code_used = True
        db.commit()

        return {
            "status": True,
            "code": 200,
            "message": "Login via login code successful",
            "access_token": session.token,
            "token_type": "bearer",
            "data": {
                "access_token": session.token,
                "token_type": "bearer"
            }
        }

    except Exception as e:
        print("ERROR:", str(e))
        print(traceback.format_exc())
        return {
            "status": False,
            "code": 500,
            "message": str(e),
            "data": {}
        }


@router.post("/user-details", response_model=UserDetailsResponse)
def get_user_details_from_token(
    request: TokenRequest,
    db: Session = Depends(get_db)
):
    payload = decode_access_token(request.token)
    if not payload:
        raise HTTPException(status_code=401, detail="Invalid or expired token")

    # Fetch the user
    user = db.query(User).filter(User.email == payload["sub"]).first()
    if not user:
        raise HTTPException(status_code=404, detail="User not found")

    # Fetch all branches associated with the user
    branches = db.query(Branch).filter(Branch.user_id == user.user_id).all()

    # Default values
    store_id = None
    store_name = None
    branch_data = []

    if branches:
        store_id = branches[0].store_id  # assuming all branches belong to one store
        # Fetch store name from the first branch's store
        store = db.query(Store).filter(Store.store_id == store_id).first()
        if store:
            store_name = store.name

        # Build branch info list
        branch_data = [
            BranchInfo(
                branch_id=branch.branch_id,
                branch_name=branch.branch_name,
                branch_address=branch.address
            )
            for branch in branches
        ]

    return UserDetailsResponse(
        status=True,
        user_id=user.user_id,
        user_name=user.name,
        store_id=store_id,
        store_name=store_name,
        branches=branch_data
    )



#Logout API
@router.post("/logout")
def logout(user: User = Depends(get_current_user), db: Session = Depends(get_db)):
    """Logout user by deleting their session tokens."""
    db.query(UserSession).filter(UserSession.user_id == user.user_id).delete()
    db.commit()
    return {"message": "User logged out, session removed"}


#######################################################################################################




# Forgot Password API
@router.post("/forgot-password", response_model=PasswordResetResponse)
async def forgot_password_endpoint(request: ForgotPasswordRequest, db: Session = Depends(get_db)):
    return await forgot_password(request, db)



## Reset Password API
@router.post(
    "/reset-password",
    response_model=PasswordResetResponse
)
async def reset_password_endpoint(
    request: PasswordReset,
    db: Session = Depends(get_db),
    # current_user: User = Depends(get_current_user)  
):
    
    # 1. Validate current user
    token = request.token
    new_password = request.new_password
    
    # Decode the token to get the user
    current_user = decode_access_token(token)
    if not current_user:
        raise HTTPException(status_code=401, detail="Invalid or expired token")
   
    # Fetch the user from the database
    current_user = db.query(User).filter(User.email == current_user["sub"]).first()
    # print("current_user", current_user)
    if not current_user:
        raise HTTPException(status_code=404, detail="User not found")
    
    # # 2. Check if the token exists in the database
    # reset_token_entry = db.query(PasswordResetToken).filter(PasswordResetToken.token == token).first()
    # if not reset_token_entry:
    #     raise HTTPException(status_code=400, detail="Invalid or expired reset token")
    
    # 2. Hash new password
    hashed_password = hash_password(new_password)


    # 3. Update in DB
    current_user.password_hash = hashed_password
    db.commit()
    db.refresh(current_user)

    # 4. Return success message
    return PasswordResetResponse(
        success=True,
        message="Password has been reset successfully."
    )
    

# # Endpoint for resetting password
# @router.post("/reset-password")
# async def reset_password(request: PasswordReset, db: Session = Depends(get_db)):
#     # Get the token and new password from the request body
#     token = request.token
#     new_password = request.new_password
    
#     # Verify if the reset token is valid
#     reset_token_entry = db.query(PasswordResetToken).filter(PasswordResetToken.token == token).first()
    
#     if not reset_token_entry:
#         # If the token is invalid or expired, raise an error
#         raise HTTPException(status_code=400, detail="Invalid or expired token")
    
#     # Get the user associated with this token
#     user = db.query(User).filter(User.user_id == reset_token_entry.user_id).first()
    
#     if not user:
#         # If no user is found for the token, raise an error
#         raise HTTPException(status_code=404, detail="User not found")
    
#     # Hash the new password before updating the user record
#     hashed_password = hash_password(new_password)
    
#     # Update the user's password
#     user.password_hash = hashed_password
#     db.commit()

#     # Optionally, delete the token after it has been used
#     db.delete(reset_token_entry)
#     db.commit()

#     # Return a success message
#     return PasswordResetResponse(message="Password has been successfully reset.")



#--------------temp API---------------

@router.get("/latest-reset-token")
async def get_latest_token(email: str, db: Session = Depends(get_db)):
    """
    Fetch the latest reset token for a given email.
    Only for debugging and testing purposes.
    """
    user = db.query(User).filter(User.email == email).first()
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    
    reset_token = db.query(PasswordResetToken).filter(
        PasswordResetToken.user_id == user.user_id
    ).order_by(PasswordResetToken.created_at.desc()).first()

    if not reset_token:
        raise HTTPException(status_code=404, detail="No reset token found")

    return {"token": reset_token.token}
