from datetime import datetime, timedelta
from typing import Optional

from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.hashers import make_password, check_password
from ninja import Router
from ninja.security import HttpBearer

from .schemas import TokenSchema, UserCreate, UserOut, LoginSchema, ErrorMessage, UserUpdate
import jwt

router = Router()

# JWT settings
JWT_SECRET = settings.SECRET_KEY  # 使用 Django 的 secret key
JWT_ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

User = get_user_model()


def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str:
    to_encode = data.copy()
    current_time = datetime.utcnow()
    
    if expires_delta:
        expire = current_time + expires_delta
    else:
        expire = current_time + timedelta(minutes=15)
    
    # 正确设置时间戳
    to_encode.update({
        "exp": expire,  # PyJWT 会自动处理 datetime 对象
        "iat": current_time
    })
    
    print(f"Creating token with payload: {to_encode}")
    print(f"Current UTC time: {current_time}")
    print(f"Token expires at: {expire}")
    print(f"Using JWT_SECRET: {JWT_SECRET}")
    
    encoded_jwt = jwt.encode(to_encode, JWT_SECRET, algorithm=JWT_ALGORITHM)
    print(f"Generated token: {encoded_jwt}")
    return encoded_jwt


class AuthBearer(HttpBearer):
    def authenticate(self, request, token: str) -> Optional[User]:
        print("\n=== Token Authentication Debug ===")
        print(f"Received token: {token}")
        print(f"Current UTC time: {datetime.utcnow()}")
        print(f"Using JWT_SECRET: {JWT_SECRET}")
        print(f"Using JWT_ALGORITHM: {JWT_ALGORITHM}")
        
        try:
            print("\nAttempting to decode token...")
            # 添加 leeway 参数，允许有一定的时间误差
            payload = jwt.decode(
                token, 
                JWT_SECRET, 
                algorithms=[JWT_ALGORITHM],
                leeway=timedelta(seconds=10)  # 允许10秒的时间误差
            )
            print(f"Successfully decoded payload: {payload}")
            
            user_id = int(payload.get("sub"))  # 将字符串转回整数
            print(f"\nLooking for user with ID: {user_id}")
            user = User.objects.filter(id=user_id).first()
            
            if not user:
                print(f"No user found with ID: {user_id}")
                return None
            
            print(f"Found user: {user.username} (ID: {user.id})")
            return user
            
        except jwt.ExpiredSignatureError:
            print("\nError: Token has expired")
            return None
        except jwt.InvalidTokenError as e:
            print(f"\nError: Invalid token: {str(e)}")
            return None
        except Exception as e:
            print(f"\nUnexpected error: {str(e)}")
            print(f"Error type: {type(e)}")
            import traceback
            print("Traceback:")
            traceback.print_exc()
            return None
        finally:
            print("\n=== End of Authentication Debug ===\n")


@router.post("/register", response={201: UserOut, 400: ErrorMessage})
def register(request, data: UserCreate):
    if User.objects.filter(email=data.email).exists():
        return 400, {"detail": "Email already registered"}
    
    if User.objects.filter(username=data.username).exists():
        return 400, {"detail": "Username already taken"}
    
    user = User.objects.create(
        username=data.username,
        email=data.email,
        password=make_password(data.password),
        avatar=data.avatar,
        bio=data.bio
    )
    
    return 201, user


@router.post("/login", response={200: TokenSchema, 401: ErrorMessage})
def login(request, data: LoginSchema):
    print(f"\n=== Login Debug ===")
    print(f"Login attempt for email: {data.email}")
    
    user = User.objects.filter(email=data.email).first()
    if not user:
        print("User not found")
        return 401, {"detail": "Invalid email or password"}
    
    if not check_password(data.password, user.password):
        print("Invalid password")
        return 401, {"detail": "Invalid email or password"}
    
    print(f"User authenticated successfully: {user.username} (ID: {user.id})")
    
    access_token = create_access_token(
        data={"sub": str(user.id)},  # 将 user.id 转换为字符串
        expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    )
    
    print(f"Generated access token: {access_token}")
    print("=== End of Login Debug ===\n")
    
    return 200, {"access_token": access_token, "token_type": "bearer"}


@router.get("/me", response=UserOut, auth=AuthBearer())
def get_current_user(request):
    return request.auth


@router.put("/profile", response={200: UserOut, 400: ErrorMessage}, auth=AuthBearer())
def update_profile(request, data: UserUpdate):
    user = request.auth
    
    # Check if username is being updated and is unique
    if data.username and data.username != user.username:
        if User.objects.filter(username=data.username).exists():
            return 400, {"detail": "Username already taken"}
        user.username = data.username
    
    # Check if email is being updated and is unique
    if data.email and data.email != user.email:
        if User.objects.filter(email=data.email).exists():
            return 400, {"detail": "Email already registered"}
        user.email = data.email
    
    # Update bio if provided
    if data.bio is not None:  # Allow empty string for bio
        user.bio = data.bio
    
    try:
        user.save()
        return 200, user
    except Exception as e:
        return 400, {"detail": str(e)}
