"""
认证 API：注册、登录、登出、修改密码
"""
from fastapi import APIRouter, HTTPException, Response, status, Request
from pydantic import BaseModel, field_validator
from app.core.supabase import get_supabase
from app.core.security import (
    get_password_hash,
    verify_password,
    create_access_token,
    generate_session_token,
    set_auth_cookie,
    clear_auth_cookie,
    decode_access_token
)
from loguru import logger
from typing import Optional
import re

router = APIRouter(prefix="/api/auth", tags=["认证"])


class RegisterRequest(BaseModel):
    phone: str
    password: str
    username: Optional[str] = None

    @field_validator('phone')
    @classmethod
    def validate_phone(cls, v):
        if not re.match(r'^\d{11}$', v):
            raise ValueError('手机号必须是11位数字')
        return v


class LoginRequest(BaseModel):
    phone: str
    password: str

    @field_validator('phone')
    @classmethod
    def validate_phone(cls, v):
        if not re.match(r'^\d{11}$', v):
            raise ValueError('手机号必须是11位数字')
        return v


class ChangePasswordRequest(BaseModel):
    old_password: str
    new_password: str

    @field_validator('new_password')
    @classmethod
    def validate_new_password(cls, v):
        if len(v) < 6:
            raise ValueError('新密码长度至少6位')
        return v


class UserResponse(BaseModel):
    id: str
    phone: str
    username: Optional[str]
    role: str
    is_active: bool
    expires_at: Optional[str] = None


@router.post("/register")
async def register(request: RegisterRequest):
    """
    用户注册
    
    注册后状态为 pending，需要管理员激活
    """
    try:
        supabase = get_supabase()
        
        # 检查手机号是否已存在
        existing = supabase.table("users").select("id").eq(
            "phone", request.phone
        ).execute()
        
        if existing.data:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="该手机号已注册"
            )
        
        # 创建用户
        password_hash = get_password_hash(request.password)
        
        result = supabase.table("users").insert({
            "phone": request.phone,
            "password_hash": password_hash,
            "username": request.username or f"用户{request.phone[-4:]}",
            "role": "pending",
            "is_active": False
        }).execute()
        
        logger.info(f"新用户注册: {request.phone}")
        
        return {
            "success": True,
            "message": "注册成功，请等待管理员审核激活"
        }
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"注册失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="注册失败，请稍后重试"
        )


@router.post("/login")
async def login(request: LoginRequest, response: Response):
    """
    用户登录
    
    - 验证密码
    - 检查是否激活
    - 实现"后踢前"单设备登录
    """
    try:
        supabase = get_supabase()
        
        # 查找用户
        user_result = supabase.table("users").select("*").eq(
            "phone", request.phone
        ).single().execute()
        
        user = user_result.data
        if not user:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="手机号或密码错误"
            )
        
        # 验证密码
        if not verify_password(request.password, user["password_hash"]):
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="手机号或密码错误"
            )
        
        # 检查是否激活
        if not user["is_active"]:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="账号未激活，请等待管理员审核"
            )
        
        # 检查授权是否过期
        if user.get("expires_at"):
            from datetime import datetime, timezone
            expires_at = datetime.fromisoformat(user["expires_at"].replace("Z", "+00:00"))
            if datetime.now(timezone.utc) > expires_at:
                raise HTTPException(
                    status_code=status.HTTP_403_FORBIDDEN,
                    detail="授权已过期，请联系管理员续期"
                )
        
        # 生成新的 session_token (后踢前)
        session_token = generate_session_token()
        
        # 删除旧 session，插入新 session
        supabase.table("user_sessions").delete().eq(
            "user_id", user["id"]
        ).execute()
        
        supabase.table("user_sessions").insert({
            "user_id": user["id"],
            "session_token": session_token,
            "device_info": None  # 可以从 request headers 获取
        }).execute()
        
        # 生成 JWT Token
        token = create_access_token(user["id"], session_token)
        
        # 设置 HttpOnly Cookie
        set_auth_cookie(response, token)
        
        logger.info(f"用户登录: {request.phone}")
        
        return {
            "success": True,
            "message": "登录成功",
            "user": UserResponse(
                id=user["id"],
                phone=user["phone"],
                username=user.get("username"),
                role=user["role"],
                is_active=user["is_active"],
                expires_at=user.get("expires_at")
            )
        }
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"登录失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="登录失败，请稍后重试"
        )


@router.post("/logout")
async def logout(response: Response):
    """用户登出"""
    clear_auth_cookie(response)
    return {"success": True, "message": "已登出"}


@router.post("/change-password")
async def change_password(request: ChangePasswordRequest, req: Request, response: Response):
    """
    修改密码
    
    - 验证当前密码
    - 设置新密码
    - 重新生成 session token
    """
    # 从 Cookie 获取用户
    token = req.cookies.get("access_token")
    if not token:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="未登录"
        )
    
    token_data = decode_access_token(token)
    if not token_data:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Token 无效"
        )
    
    try:
        supabase = get_supabase()
        
        # 获取用户信息
        user_result = supabase.table("users").select("*").eq(
            "id", token_data.user_id
        ).single().execute()
        
        user = user_result.data
        if not user:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="用户不存在"
            )
        
        # 验证当前密码
        if not verify_password(request.old_password, user["password_hash"]):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="当前密码错误"
            )
        
        # 更新密码
        new_password_hash = get_password_hash(request.new_password)
        supabase.table("users").update({
            "password_hash": new_password_hash
        }).eq("id", user["id"]).execute()
        
        # 生成新的 session token，使旧 token 失效
        new_session_token = generate_session_token()
        
        supabase.table("user_sessions").delete().eq(
            "user_id", user["id"]
        ).execute()
        
        supabase.table("user_sessions").insert({
            "user_id": user["id"],
            "session_token": new_session_token,
            "device_info": None
        }).execute()
        
        # 生成新的 JWT Token
        new_token = create_access_token(user["id"], new_session_token)
        set_auth_cookie(response, new_token)
        
        logger.info(f"用户修改密码: {user['phone']}")
        
        return {
            "success": True,
            "message": "密码修改成功"
        }
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"修改密码失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="修改密码失败，请稍后重试"
        )


@router.get("/me")
async def get_me(request: Request):
    """获取当前用户信息"""
    # 从 Cookie 获取用户
    token = request.cookies.get("access_token")
    if not token:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="未登录"
        )
    
    token_data = decode_access_token(token)
    if not token_data:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Token 无效"
        )
    
    supabase = get_supabase()
    user_result = supabase.table("users").select("*").eq(
        "id", token_data.user_id
    ).single().execute()
    
    user = user_result.data
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="用户不存在"
        )
    
    return UserResponse(
        id=user["id"],
        phone=user["phone"],
        username=user.get("username"),
        role=user["role"],
        is_active=user["is_active"],
        expires_at=user.get("expires_at")
    )
