from typing import Optional, Union

from lxml import etree
from smb.common.http_client import BaseHttpClientException, collect_errors

from smb.common.aiotvm import HttpClientWithTvm, TvmClient


class YasmsError(BaseHttpClientException):
    pass


class IncorrectParams(YasmsError):
    pass


class YasmsClient(HttpClientWithTvm):
    _sender: str

    def __init__(
        self,
        *,
        url: str,
        tvm: TvmClient,
        tvm_source: Optional[Union[str, int]] = None,
        tvm_destination: Union[str, int],
        sender: str,
    ):
        super().__init__(
            url=url, tvm=tvm, tvm_source=tvm_source, tvm_destination=tvm_destination
        )
        if not sender:
            raise IncorrectParams("Sender must be specified.")

        self._sender = sender

    @collect_errors
    async def send_sms(
        self, *, phone: int, text: str, identity: Optional[str] = None
    ) -> str:
        if not all([phone, text]):
            raise IncorrectParams("Phone number and message text must be set.")

        params = {"sender": self._sender, "phone": f"+{phone}", "text": text}
        if identity:
            params["identity"] = identity

        response = await self.request(
            method="GET",
            uri="/sendsms",
            expected_statuses=[200],
            params=params,
            metric_name="/sendsms",
        )
        response_body = etree.XML(response)

        if response_body[0].tag == "message-sent":
            return response_body[0].attrib["id"]
        else:
            error = response_body[0].text
            errorcode = response_body[1].text
            raise YasmsError(errorcode, error)
