"""用户服务（与 npm UserService 对齐）。"""
from typing import Any, Optional

from .base_client import BaseClient
from .types import (
    ClientConfig,
    RequestOptions,
    TokenStorage,
    PaginatedResponse,
    User,
    UserCreateRequest,
    UserUpdateRequest,
    SelfPasswordChangeRequest,
    SelfUserUpdateRequest,
)


class UserService(BaseClient):
    service_path = "users"

    def __init__(
        self,
        config: ClientConfig,
        token_storage: Optional[TokenStorage] = None,
    ) -> None:
        super().__init__(config, token_storage=token_storage)

    @property
    def service_name(self) -> str:
        return "user"

    def get_current_user(
        self,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        return self.request("/me", RequestOptions(method="GET"))

    def get_user_by_id(
        self,
        user_id: int,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        return self.request(f"/{user_id}", RequestOptions(method="GET"))

    def create_user(
        self,
        user_data: UserCreateRequest,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        body = {
            "username": user_data.username,
            "email": user_data.email,
            "password": user_data.password,
            "name": user_data.name,
            "role": user_data.role,
            "phone": user_data.phone,
            "project_id": user_data.project_id,
        }
        return self.request("", RequestOptions(method="POST", body=body))

    def update_user(
        self,
        user_id: int,
        update_data: UserUpdateRequest,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        body = {
            "name": update_data.name,
            "avatar": update_data.avatar,
            "phone": update_data.phone,
            "role": update_data.role,
            "project_id": update_data.project_id,
        }
        return self.request(f"/{user_id}", RequestOptions(method="PUT", body=body))

    def list_users(
        self,
        include_inactive: bool = False,
        page: int = 1,
        per_page: int = 10,
        project_id: Optional[int] = None,
        options: Optional[RequestOptions] = None,
    ) -> PaginatedResponse:
        params = {
            "include_inactive": include_inactive,
            "page": page,
            "per_page": per_page,
        }
        if project_id is not None:
            params["project_id"] = project_id
        return self.paginated_request("", RequestOptions(
            method="GET",
            params=params,
        ))

    def deactivate_user(
        self,
        user_id: int,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        return self.request(f"/{user_id}", RequestOptions(method="DELETE"))

    def restore_user(
        self,
        user_id: int,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        return self.request(f"/{user_id}/restore", RequestOptions(method="POST"))

    def reset_password(
        self,
        user_id: int,
        new_password: str,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        return self.request(f"/{user_id}/password", RequestOptions(
            method="PUT",
            body={"new_password": new_password},
        ))

    def change_own_password(
        self,
        password_data: SelfPasswordChangeRequest,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        return self.request("/me/password", RequestOptions(
            method="PUT",
            body={
                "old_password": password_data.old_password,
                "new_password": password_data.new_password,
            },
        ))

    def update_current_user(
        self,
        update_data: SelfUserUpdateRequest,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        return self.request("/me", RequestOptions(
            method="PUT",
            body={
                "name": update_data.name,
                "avatar": update_data.avatar,
                "phone": update_data.phone,
            },
        ))
