"""
認證 API
處理登入、登出、Token 管理
"""
from typing import Dict, Any
from fastapi import APIRouter, Depends, HTTPException, status, Request
from sqlalchemy.orm import Session

from app.db.session import get_db
from app.schemas.auth import LoginRequest, TokenResponse, UserInfo
from app.schemas.response import MessageResponse
from app.api.deps import get_current_user, require_auth
from app.services.keycloak_service import keycloak_service
from app.services.audit_service import audit_service

router = APIRouter()


@router.post("/login", response_model=TokenResponse)
def login(
    login_data: LoginRequest,
    request: Request,
    db: Session = Depends(get_db),
):
    """
    用戶登入

    使用 Keycloak Direct Access Grant (Resource Owner Password Credentials)
    獲取 Access Token 和 Refresh Token

    Args:
        login_data: 登入憑證 (username, password)
        request: HTTP Request (用於獲取 IP)
        db: 資料庫 Session

    Returns:
        TokenResponse: Access Token 和 Refresh Token

    Raises:
        HTTPException: 登入失敗時拋出 401
    """
    try:
        # 使用 Keycloak 進行認證
        token_response = keycloak_service.openid.token(
            login_data.username,
            login_data.password
        )

        # 記錄登入成功的審計日誌
        audit_service.log_login(
            db=db,
            username=login_data.username,
            ip_address=audit_service.get_client_ip(request),
            success=True
        )

        return TokenResponse(
            access_token=token_response["access_token"],
            token_type=token_response["token_type"],
            expires_in=token_response["expires_in"],
            refresh_token=token_response.get("refresh_token")
        )

    except Exception as e:
        # 記錄登入失敗的審計日誌
        audit_service.log_login(
            db=db,
            username=login_data.username,
            ip_address=audit_service.get_client_ip(request),
            success=False
        )

        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )


@router.post("/logout", response_model=MessageResponse)
def logout(
    request: Request,
    current_user: Dict[str, Any] = Depends(require_auth),
    db: Session = Depends(get_db),
):
    """
    用戶登出

    記錄登出審計日誌

    Args:
        request: HTTP Request
        current_user: 當前用戶資訊
        db: 資料庫 Session

    Returns:
        MessageResponse: 登出成功訊息
    """
    # 記錄登出審計日誌
    audit_service.log_logout(
        db=db,
        username=current_user["username"],
        ip_address=audit_service.get_client_ip(request)
    )

    # TODO: 可選擇在 Keycloak 端撤銷 Token
    # keycloak_service.openid.logout(refresh_token)

    return MessageResponse(
        message=f"User {current_user['username']} logged out successfully"
    )


@router.post("/refresh", response_model=TokenResponse)
def refresh_token(
    refresh_token: str,
):
    """
    刷新 Access Token

    使用 Refresh Token 獲取新的 Access Token

    Args:
        refresh_token: Refresh Token

    Returns:
        TokenResponse: 新的 Access Token 和 Refresh Token

    Raises:
        HTTPException: Refresh Token 無效時拋出 401
    """
    try:
        # 使用 Refresh Token 獲取新的 Access Token
        token_response = keycloak_service.openid.refresh_token(refresh_token)

        return TokenResponse(
            access_token=token_response["access_token"],
            token_type=token_response["token_type"],
            expires_in=token_response["expires_in"],
            refresh_token=token_response.get("refresh_token")
        )

    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid or expired refresh token",
            headers={"WWW-Authenticate": "Bearer"},
        )


@router.get("/me", response_model=UserInfo)
def get_current_user_info(
    current_user: Dict[str, Any] = Depends(require_auth),
    db: Session = Depends(get_db)
):
    """
    獲取當前用戶資訊

    從 JWT Token 解析用戶資訊，並查詢租戶資訊

    Args:
        current_user: 當前用戶資訊 (從 Token 解析)
        db: 資料庫 Session

    Returns:
        UserInfo: 用戶詳細資訊（包含租戶資訊）
    """
    # 查詢用戶所屬租戶
    from app.models.tenant import Tenant
    from app.models.employee import Employee

    tenant_info = None

    # 從 email 查詢員工,取得租戶資訊
    email = current_user.get("email")
    if email:
        employee = db.query(Employee).filter(Employee.email == email).first()
        if employee and employee.tenant_id:
            tenant = db.query(Tenant).filter(Tenant.id == employee.tenant_id).first()
            if tenant:
                tenant_info = {
                    "id": tenant.id,
                    "code": tenant.code,
                    "name": tenant.name,
                    "is_sysmana": tenant.is_sysmana
                }

    return UserInfo(
        sub=current_user.get("sub", ""),
        username=current_user.get("username", ""),
        email=current_user.get("email", ""),
        first_name=current_user.get("first_name"),
        last_name=current_user.get("last_name"),
        email_verified=current_user.get("email_verified", False),
        tenant=tenant_info
    )


@router.post("/change-password", response_model=MessageResponse)
def change_password(
    old_password: str,
    new_password: str,
    current_user: Dict[str, Any] = Depends(require_auth),
    db: Session = Depends(get_db),
    request: Request = None,
):
    """
    修改密碼

    用戶修改自己的密碼

    Args:
        old_password: 舊密碼
        new_password: 新密碼
        current_user: 當前用戶資訊
        db: 資料庫 Session
        request: HTTP Request

    Returns:
        MessageResponse: 成功訊息

    Raises:
        HTTPException: 舊密碼錯誤或修改失敗時拋出錯誤
    """
    username = current_user["username"]

    try:
        # 1. 驗證舊密碼
        try:
            keycloak_service.openid.token(username, old_password)
        except:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Old password is incorrect"
            )

        # 2. 獲取用戶 Keycloak ID
        user = keycloak_service.get_user_by_username(username)
        if not user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="User not found in Keycloak"
            )

        user_id = user["id"]

        # 3. 重設密碼 (非臨時密碼)
        success = keycloak_service.reset_password(
            user_id=user_id,
            new_password=new_password,
            temporary=False
        )

        if not success:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="Failed to change password"
            )

        # 4. 記錄審計日誌
        audit_service.log(
            db=db,
            action="change_password",
            resource_type="authentication",
            performed_by=username,
            details={"success": True},
            ip_address=audit_service.get_client_ip(request) if request else None
        )

        return MessageResponse(
            message="Password changed successfully"
        )

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to change password: {str(e)}"
        )


@router.post("/reset-password/{username}", response_model=MessageResponse)
def reset_user_password(
    username: str,
    new_password: str,
    temporary: bool = True,
    current_user: Dict[str, Any] = Depends(require_auth),
    db: Session = Depends(get_db),
    request: Request = None,
):
    """
    重設用戶密碼 (管理員功能)

    管理員為其他用戶重設密碼

    Args:
        username: 目標用戶名稱
        new_password: 新密碼
        temporary: 是否為臨時密碼 (用戶首次登入需修改)
        current_user: 當前用戶資訊 (管理員)
        db: 資料庫 Session
        request: HTTP Request

    Returns:
        MessageResponse: 成功訊息

    Raises:
        HTTPException: 權限不足或重設失敗時拋出錯誤
    """
    # TODO: 檢查是否為管理員
    # 目前暫時允許所有已認證用戶

    try:
        # 1. 獲取目標用戶
        user = keycloak_service.get_user_by_username(username)
        if not user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"User {username} not found"
            )

        user_id = user["id"]

        # 2. 重設密碼
        success = keycloak_service.reset_password(
            user_id=user_id,
            new_password=new_password,
            temporary=temporary
        )

        if not success:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="Failed to reset password"
            )

        # 3. 記錄審計日誌
        audit_service.log(
            db=db,
            action="reset_password",
            resource_type="authentication",
            performed_by=current_user["username"],
            details={
                "target_user": username,
                "temporary": temporary,
                "success": True
            },
            ip_address=audit_service.get_client_ip(request) if request else None
        )

        return MessageResponse(
            message=f"Password reset for user {username}"
        )

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to reset password: {str(e)}"
        )
