from datetime import timedelta
from typing import Any

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

from app.api.deps import get_db, get_current_user
from app.core.config import settings
from app.core.security import create_access_token, create_refresh_token
from app.crud.user import user, admin
from app.schemas.user import (
    UserCreate, UserResponse, UserLogin, UserWithToken,
    Token, PasswordChange, AdminWithToken
)
from app.utils.response import success_response, error_response
from app.utils.errors import BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError

router = APIRouter()


@router.post("/register", response_model=UserWithToken, status_code=status.HTTP_201_CREATED)
def register(
    *,
    db: Session = Depends(get_db),
    user_in: UserCreate,
) -> Any:
    """
    用户注册
    """
    # 检查用户名是否已存在
    if user.get_by_username(db, username=user_in.username):
        raise BadRequestError("用户名已存在")
    
    # 检查邮箱是否已存在
    if user_in.email and user.get_by_email(db, email=user_in.email):
        raise BadRequestError("邮箱已存在")
    
    # 检查手机号是否已存在
    if user_in.phone and user.get_by_phone(db, phone=user_in.phone):
        raise BadRequestError("手机号已存在")
    
    # 创建新用户
    db_user = user.create(db, obj_in=user_in)
    
    # 更新最后登录时间
    user.update_last_login(db, db_obj=db_user)
    
    # 生成令牌
    access_token = create_access_token(db_user.id)
    refresh_token = create_refresh_token(db_user.id)
    
    return success_response(
        data={
            "user": db_user,
            "token": access_token,
            "refresh_token": refresh_token
        },
        message="注册成功",
        code=201
    )


@router.post("/login", response_model=UserWithToken)
def login(
    *,
    db: Session = Depends(get_db),
    form_data: OAuth2PasswordRequestForm = Depends()
) -> Any:
    """
    用户登录
    """
    # 验证用户
    db_user = user.authenticate(db, username=form_data.username, password=form_data.password)
    if not db_user:
        raise UnauthorizedError("用户名或密码错误")
    
    # 检查用户状态
    if not user.is_active(db_user):
        raise ForbiddenError("账户已被禁用")
    
    # 更新最后登录时间
    user.update_last_login(db, db_obj=db_user)
    
    # 生成令牌
    access_token = create_access_token(db_user.id)
    refresh_token = create_refresh_token(db_user.id)
    
    return success_response(
        data={
            "user": db_user,
            "token": access_token,
            "refresh_token": refresh_token
        },
        message="登录成功"
    )


@router.post("/login/json", response_model=UserWithToken)
def login_json(
    *,
    db: Session = Depends(get_db),
    login_in: UserLogin
) -> Any:
    """
    用户登录（JSON格式）
    """
    # 验证用户
    db_user = user.authenticate(db, username=login_in.username, password=login_in.password)
    if not db_user:
        raise UnauthorizedError("用户名或密码错误")
    
    # 检查用户状态
    if not user.is_active(db_user):
        raise ForbiddenError("账户已被禁用")
    
    # 更新最后登录时间
    user.update_last_login(db, db_obj=db_user)
    
    # 生成令牌
    access_token = create_access_token(db_user.id)
    refresh_token = create_refresh_token(db_user.id)
    
    return success_response(
        data={
            "user": db_user,
            "token": access_token,
            "refresh_token": refresh_token
        },
        message="登录成功"
    )


@router.post("/refresh-token", response_model=Token)
def refresh_token(
    *,
    db: Session = Depends(get_db),
    refresh_token: str = Body(..., embed=True)
) -> Any:
    """
    刷新访问令牌
    """
    try:
        from jose import jwt
        from pydantic import ValidationError
        from app.schemas.user import TokenPayload
        
        payload = jwt.decode(
            refresh_token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM]
        )
        token_data = TokenPayload(**payload)
        
        # 检查令牌类型
        if token_data.type != "refresh":
            raise UnauthorizedError("无效的刷新令牌")
        
        # 检查用户是否存在
        db_user = user.get(db, user_id=token_data.sub)
        if not db_user:
            raise NotFoundError("用户不存在")
        
        # 检查用户状态
        if not user.is_active(db_user):
            raise ForbiddenError("账户已被禁用")
        
        # 生成新令牌
        access_token = create_access_token(db_user.id)
        new_refresh_token = create_refresh_token(db_user.id)
        
        return success_response(
            data={
                "access_token": access_token,
                "refresh_token": new_refresh_token,
                "token_type": "bearer"
            }
        )
    except (jwt.JWTError, ValidationError):
        raise UnauthorizedError("无效的刷新令牌")


@router.get("/me", response_model=UserResponse)
def get_current_user_info(
    current_user: UserResponse = Depends(get_current_user)
) -> Any:
    """
    获取当前用户信息
    """
    return success_response(data=current_user)


@router.put("/profile", response_model=UserResponse)
def update_profile(
    *,
    db: Session = Depends(get_db),
    current_user: UserResponse = Depends(get_current_user),
    profile_in: dict = Body(...)
) -> Any:
    """
    更新用户个人信息
    """
    # 更新用户信息
    db_user = user.update(db, db_obj=current_user, obj_in=profile_in)
    
    return success_response(
        data=db_user,
        message="个人信息更新成功"
    )


@router.put("/password", response_model=dict)
def change_password(
    *,
    db: Session = Depends(get_db),
    current_user: UserResponse = Depends(get_current_user),
    password_in: PasswordChange
) -> Any:
    """
    修改密码
    """
    from app.core.security import verify_password
    
    # 验证当前密码
    if not verify_password(password_in.current_password, current_user.password_hash):
        raise UnauthorizedError("当前密码错误")
    
    # 更新密码
    user.update_password(db, db_obj=current_user, new_password=password_in.new_password)
    
    return success_response(message="密码修改成功")


@router.post("/admin/login", response_model=AdminWithToken)
def admin_login(
    *,
    db: Session = Depends(get_db),
    login_in: UserLogin
) -> Any:
    """
    管理员登录
    """
    # 验证管理员
    db_admin = admin.authenticate(db, username=login_in.username, password=login_in.password)
    if not db_admin:
        raise UnauthorizedError("用户名或密码错误")
    
    # 检查管理员状态
    if not admin.is_active(db_admin):
        raise ForbiddenError("账户已被禁用")
    
    # 更新最后登录时间
    admin.update_last_login(db, db_obj=db_admin)
    
    # 生成令牌
    access_token = create_access_token(db_admin.id)
    refresh_token = create_refresh_token(db_admin.id)
    
    return success_response(
        data={
            "admin": db_admin,
            "token": access_token,
            "refresh_token": refresh_token
        },
        message="管理员登录成功"
    )


@router.post("/wechat", response_model=UserWithToken)
def wechat_login(
    *,
    db: Session = Depends(get_db),
    code: str = Body(...),
    user_info: dict = Body(None)
) -> Any:
    """
    微信登录/注册
    """
    # 模拟获取微信用户信息
    wechat_user_info = {
        "openid": f"mock_openid_{code}",
        "unionid": f"mock_unionid_{code}",
        "nickname": user_info.get("nickName") if user_info else "微信用户",
        "avatar": user_info.get("avatarUrl") if user_info else "",
        "gender": "male" if user_info and user_info.get("gender") == 1 else 
                 "female" if user_info and user_info.get("gender") == 2 else "other"
    }
    
    # 查找是否已存在微信用户
    db_user = user.get_by_wechat_openid(db, openid=wechat_user_info["openid"])
    
    if db_user:
        # 更新最后登录时间
        user.update_last_login(db, db_obj=db_user)
    else:
        # 创建新用户（微信注册）
        import secrets
        import string
        from app.schemas.user import UserCreate
        
        # 生成随机密码
        alphabet = string.ascii_letters + string.digits
        random_password = ''.join(secrets.choice(alphabet) for _ in range(12))
        
        # 创建用户
        user_in = UserCreate(
            username=f"wx_{wechat_user_info['openid'][-8:]}",
            password=random_password,
            nickname=wechat_user_info["nickname"],
            user_type="farmer"
        )
        
        db_user = user.create(db, obj_in=user_in)
        
        # 更新微信信息
        user.update(db, db_obj=db_user, obj_in={
            "wechat_openid": wechat_user_info["openid"],
            "wechat_unionid": wechat_user_info["unionid"],
            "avatar_url": wechat_user_info["avatar"],
            "gender": wechat_user_info["gender"]
        })
    
    # 生成令牌
    access_token = create_access_token(db_user.id)
    refresh_token = create_refresh_token(db_user.id)
    
    return success_response(
        data={
            "user": db_user,
            "token": access_token,
            "refresh_token": refresh_token
        },
        message="微信登录成功"
    )