import re
from decimal import Decimal
from enum import Enum
from typing import Optional

import dateutil.parser
from smb.common.http_client import collect_errors

from smb.common.aiotvm import HttpClientWithTvm

__all__ = ["UgcdbClient", "OrderBy"]


_tpl_postfix_re = re.compile("{size}$")


class OrderBy(Enum):
    BY_TIME = "by_time"
    BY_RELEVANCE_ORG = "by_relevance_org"
    BY_LIKES_COUNT_DESC = "by_likes_count_desc"
    BY_RATING_ASC = "by_rating_asc"
    BY_RATING_DESC = "by_rating_desc"


class UgcdbClient(HttpClientWithTvm):
    @collect_errors
    async def fetch_org_reviews(
        self, permalink: int, limit: int = 10, order_by: OrderBy = OrderBy.BY_TIME
    ) -> Optional[dict]:
        data = await self.request(
            "GET",
            f"/v1/orgs/{permalink}/get-reviews",
            expected_statuses=[200],
            params={
                "limit": limit,
                "ranking": order_by.value,
            },
            metric_name="/v1/orgs/{permalink}/get-reviews",
        )

        if "Rating" not in data:
            return None

        reviews = []
        for review in data["Reviews"]:
            reviews.append(
                {
                    "updated_at": dateutil.parser.parse(review["UpdatedTime"]),
                    "rating": review["Rating"],
                    "text": review["Text"],
                }
            )
            if not review["IsAnonymous"]:
                reviews[-1]["username"] = review["Author"]["Name"]
                if review["Author"]["AvatarUrl"]:
                    reviews[-1]["avatar"] = _tpl_postfix_re.sub(
                        "%s", review["Author"]["AvatarUrl"]
                    )

        return {
            "aggregated_rating": Decimal(str(data["Rating"]["Value"])),
            "review_count": data["TotalCount"],
            "reviews": reviews,
        }
