
from datetime import datetime, timedelta
import json
import logging

from pydantic import EmailStr
from core.websocket_manager import ConnectionManager
from utility.send_email import send_mail
from core.excption import NotFoundException
from models.models import KYCVerification, User
from schemas.users import ForgotPasswordRequest, LoginResponse, LoginSchema, PreSignupRequest, CompleteSignupRequest, ResetPasswordRequest, UpdatePassword, UserResponse, UserUpdate, VerifyOtpRequest
from fastapi import APIRouter, BackgroundTasks, Depends, File, HTTPException, Request, UploadFile, status
from core.config import settings
from services.users import delete_account, get_user_wallet, login_user, pre_signup, update_password, verify_is_opt, complete_signup,update_user_profile, mot_depasse_oublie,reset_password, blocked_user, active_user
from database import get_db
from sqlalchemy.orm import Session
from fastapi.responses import JSONResponse
import logging
logger = logging.getLogger(__name__)

from utility.auth_token import create_access_token, create_refresh_token, get_current_user
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Query
from typing import Optional


router = APIRouter()

@router.post("/financials/auth/user/register-phone")
async def create_usrer(user: PreSignupRequest, db: Session = Depends(get_db), background_tasks: BackgroundTasks = BackgroundTasks()  ):
    return await pre_signup(user, db,background_tasks)


@router.post("/financials/auth/user/confirm-otp")
async def verify(request_data: VerifyOtpRequest, db: Session = Depends(get_db)):
    otp = request_data.otp
    logging.info(f"OTP reçu: {otp}")
    
    user = await verify_is_opt(db=db, request=request_data)
    if not user:
        raise HTTPException(status_code=400, detail="Invalid OTP or email")
     # Créer les tokens
    access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.email}, expires_delta=access_token_expires
    )
    refresh_token = create_refresh_token(data={"sub": user.email})
    
    logger.info(f"New user registered: {user.email}")
    
    
    return {
        "success": 200,
        "data": {
           "access_token": access_token,
            "refresh_token": refresh_token,
            "token_type": "bearer"
            }
        }

@router.patch("/financials/auth/user/register-user")
def complete_user_signup(request:Request,payload: CompleteSignupRequest, db: Session = Depends(get_db)):
    logger.info(f"Login attempt at {datetime.utcnow().isoformat()} payload {payload} from {request.client.host}")
    return complete_signup(payload, db)

@router.patch("/financials/update/user/profile")
async def update_user_profiles(
    request: Request,
    file: UploadFile = File(...),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    logger.info(f"Login attempt at {datetime.utcnow().isoformat()} from {request.client.host}")
    return await update_user_profile(
        current_user=current_user,
        email= current_user.email,
        phone= current_user.phone,
        last_name= current_user.last_name,
        full_name= current_user.full_name,
        file=file,
        db=db
    )

@router.post("/financials/auth/user/login", response_model=LoginResponse)
async def login( resquest: Request, loginUser: LoginSchema  ,db: Session = Depends(get_db)):
    user_login = await login_user(loginUser, db)
    if not user_login:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid credentials")
    return user_login



@router.get("/auth/me")
async def get_current_user_info(
    request: Request,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    logger.info(f"Login attempt at {datetime.utcnow().isoformat()} from {request.client.host}")
    
    wallet = get_user_wallet(current_user.id, db)
    
    # ✅ Récupération KYC de l'utilisateur
    kyc = db.query(KYCVerification).filter(KYCVerification.user_id == current_user.id).first()
    
    result = {
        "id": current_user.id,
        "username": current_user.username,
        "email": current_user.email,
        "full_name": current_user.full_name,
        "last_name": current_user.last_name,
        "phone": current_user.phone,
        "photo_profile": current_user.photo_profile,
        "commission_payee": current_user.commission_payee,
        "tim_account_type": current_user.tim_account_type.value,
        "country": current_user.country.name,
        "wallet": {
            "id": wallet.id,
            "balance": wallet.balance,
            "max_balance": wallet.max_balance,
            "currency": wallet.currency,
            "is_active": wallet.is_active,
            "nfc_enabled": wallet.nfc_enabled
        },
        # ✅ Statut KYC
        "kyc": kyc.status if kyc else "not_submitted",
        "created_at": current_user.created_at.isoformat() if current_user.created_at else None
    }

    json_data = json.dumps(result, ensure_ascii=False)

    return JSONResponse(
        content=json.loads(json_data),
        media_type="application/json; charset=utf-8"
    )

    
@router.get("/users/by-phone/{phone}", response_model=UserResponse)
def get_user_by_phone(phone: str, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.phone == phone).first()
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return user



@router.post("/financials/auth/user/forget_password")
async def send_reset_password_email(request: ForgotPasswordRequest, session_db: Session = Depends(get_db),background_tasks: BackgroundTasks = BackgroundTasks()):
   return await mot_depasse_oublie(request,session_db ,background_tasks)

@router.post("/financials/auth/user/reset_password")
async def reset_user_password(request: Request,current_data: ResetPasswordRequest , db: Session = Depends(get_db)):
    return await reset_password( curent_data=current_data, db=db)


@router.websocket("/ws")
async def websocket_endpoint(
    websocket: WebSocket,
    token: str = Query(...),           # Token JWT passé en query param
    client_type: Optional[str] = "mobile"  # Type de client, par défaut "mobile"
):
    """
    Endpoint WebSocket pour Flutter.
    Le token est obligatoire pour s'authentifier.
    """
    await ConnectionManager.connect(websocket, token, client_type)
    if websocket.client_state != websocket.CONNECTED:
        return
    try:
        while True:
            data = await websocket.receive_text()
            print(f"Message reçu: {data}")
            # Envoi d'une confirmation
            await websocket.send_text(f"Serveur a reçu: {data}")
    except WebSocketDisconnect:
        await ConnectionManager.disconnect(websocket, client_type=client_type)
        
@router.patch("/block/{user_id}")
async def blocked_user_route(
    user_id: str,
    db: Session = Depends(get_db)
):
    return await blocked_user(user_id, db)

        
@router.patch("/active/{user_id}")
async def blocked_user_route(
    user_id: str,
    db: Session = Depends(get_db)
):
    return await active_user(user_id, db)

@router.delete("/financials/auth/user/delete-account")
async def delete_account_route(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    return await delete_account(current_user, db)

@router.patch("/financials/auth/user/update-password")
async def update_password_route(
    payload: UpdatePassword,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    await update_password(
        current_user=current_user,
        data_password=payload,
        db=db
    )
    return {"message": "Mot de passe mis à jour avec succès"}
