"""消息服务（与 npm MsgService 对齐）。"""
import dataclasses
from typing import Any, Dict, List, Optional

from .base_client import BaseClient
from .types import (
    ClientConfig,
    RequestOptions,
    TokenStorage,
    Message,
    MessageQueryParams,
    MessageTypeItem,
    CategoryInfo,
    MessageStats,
    BatchMarkAsReadRequest,
    CreateMessageRequest,
    BatchCreateMessageRequest,
    SendFeishuRequest,
    SendSmsCodeRequest,
    VerifySmsCodeRequest,
)


class MsgService(BaseClient):
    service_path = "msg"

    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 "msg"

    def get_messages(
        self,
        params: Optional[MessageQueryParams] = None,
        options: Optional[RequestOptions] = None,
    ) -> List[Any]:
        opts = options or RequestOptions()
        req_params = dict(self._params_to_dict(params))
        if opts.params:
            req_params.update(opts.params)
        return self.request("/message/list", RequestOptions(
            method="GET",
            headers=opts.headers,
            params=req_params or None,
            user_context=opts.user_context,
            project_id=opts.project_id,
            org_id=opts.org_id,
            app_id=opts.app_id,
        ))

    def get_admin_messages(
        self,
        params: Optional[MessageQueryParams] = None,
        options: Optional[RequestOptions] = None,
    ) -> List[Any]:
        opts = options or RequestOptions()
        req_params = dict(self._params_to_dict(params))
        if opts.params:
            req_params.update(opts.params)
        return self.request("/message/admin/list", RequestOptions(
            method="GET",
            headers=opts.headers,
            params=req_params or None,
            user_context=opts.user_context,
            project_id=opts.project_id,
            org_id=opts.org_id,
            app_id=opts.app_id,
        ))

    def get_types(
        self,
        options: Optional[RequestOptions] = None,
    ) -> List[Any]:
        return self.request("/message/types", RequestOptions(method="GET"))

    def get_categories(
        self,
        options: Optional[RequestOptions] = None,
    ) -> List[Any]:
        return self.request("/message/categories", RequestOptions(method="GET"))

    def get_unread_stats(
        self,
        user_id: Optional[str] = None,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        params = {"userId": user_id} if user_id else {}
        return self.request("/message/stats", RequestOptions(
            method="GET",
            params=params,
        ))

    def mark_as_read(
        self,
        message_id: str,
        user_id: Optional[str] = None,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        body = {"userId": user_id} if user_id else {}
        return self.request(f"/message/{message_id}/read", RequestOptions(
            method="PATCH",
            body=body,
        ))

    def mark_many_as_read(
        self,
        request: BatchMarkAsReadRequest,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        body = {
            "messageIds": request.messageIds,
            "userId": request.userId,
        }
        return self.request("/message/batch/read", RequestOptions(
            method="PATCH",
            body=body,
        ))

    def delete_message(
        self,
        message_id: str,
        user_id: Optional[str] = None,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        body = {"userId": user_id} if user_id else None
        return self.request(f"/message/{message_id}", RequestOptions(
            method="DELETE",
            body=body,
        ))

    def create_message(
        self,
        request: CreateMessageRequest,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        body = {
            "title": request.title,
            "content": request.content,
            "type": request.type,
            "category": request.category,
            "userId": request.userId,
            "metadata": request.metadata,
        }
        return self.request("/message/", RequestOptions(
            method="POST",
            body=body,
        ))

    def create_many_messages(
        self,
        request: BatchCreateMessageRequest,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        return self.request("/message/batch", RequestOptions(
            method="POST",
            body={"messages": request.messages},
        ))

    def send_mail(
        self,
        request: Dict[str, Any],
        options: Optional[RequestOptions] = None,
    ) -> Any:
        return self.request("/mail/send", RequestOptions(
            method="POST",
            body=request,
        ))

    def send_feishu(
        self,
        request: SendFeishuRequest,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        body = {
            "url": request.url,
            "elements": request.elements,
            "title": request.title,
            "bgColor": request.bgColor,
            "noticeUser": request.noticeUser,
            "actions": request.actions,
        }
        return self.request("/webhook/feishu/send", RequestOptions(
            method="POST",
            body=body,
        ))

    def send_sms_code(
        self,
        request: SendSmsCodeRequest,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        return self.request("/sms/send-code", RequestOptions(
            method="POST",
            body={"phone": request.phone, "scene": request.scene},
        ))

    def verify_sms_code(
        self,
        request: VerifySmsCodeRequest,
        options: Optional[RequestOptions] = None,
    ) -> Any:
        return self.request("/sms/verify-code", RequestOptions(
            method="POST",
            body={"phone": request.phone, "code": request.code, "scene": request.scene},
        ))

    @staticmethod
    def _params_to_dict(params: Optional[MessageQueryParams]) -> Dict[str, Any]:
        if params is None:
            return {}
        return {k: v for k, v in dataclasses.asdict(params).items() if v is not None}
