from dataclasses import dataclass

from http_tools import AbmServiceConnector
from typeful import to_dataclass


@dataclass(frozen=True, slots=True)
class AccessResult:
    resource_type: str
    resource_id: int
    state: str
    allowed: bool
    available_at: int | None
    expires_at: int | None
    lock_reason: str | None
    winning_layer: str | None
    reasons: tuple[int, ...]


@dataclass(frozen=True, slots=True)
class CourseSummary:
    course_id: int
    state: str
    allowed: bool
    reasons: tuple[int, ...]


@dataclass(frozen=True, slots=True)
class OwnedPackage:
    access_package_id: int
    title: str
    payment_type: str
    is_active: bool
    is_locked: bool
    reason_id: int
    kind: str
    status: str
    granted_at: int


class AccessServerConnector:
    Config = AbmServiceConnector.Config

    @dataclass(slots=True)
    class Context(AbmServiceConnector.Context):
        server_name: str

    def __init__(self, config: Config, context: Context) -> None:
        self._context = context
        self._http_connector = AbmServiceConnector(config, context)

    async def check(
        self,
        portal_id: int,
        member_id: int,
        resource_type: str,
        resource_id: int,
        course_id: int | None = None,
    ) -> AccessResult:
        answer = await self._http_connector.post(
            "/v1/access/check",
            payload={
                "portal_id": portal_id,
                "member_id": member_id,
                "resource_type": resource_type,
                "resource_id": resource_id,
                "course_id": course_id,
            },
            headers={"server_name": self._context.server_name},
        )
        return to_dataclass(answer, AccessResult)

    async def courses_summary(self, portal_id: int, member_id: int) -> list[CourseSummary]:
        answer = await self._http_connector.post(
            f"/v1/access/users/{member_id}/courses",
            payload={"portal_id": portal_id},
            headers={"server_name": self._context.server_name},
        )
        return [to_dataclass(course, CourseSummary) for course in answer]

    async def get_member_packages(
        self, portal_id: int, member_id: int, active_only: bool = True
    ) -> list[OwnedPackage]:
        answer = await self._http_connector.post(
            "/v1/ownership/packages",
            payload={"portal_id": portal_id, "member_id": member_id, "active_only": active_only},
            headers={"server_name": self._context.server_name},
        )
        return [to_dataclass(item, OwnedPackage) for item in answer["items"]]

    async def grant(
        self,
        portal_id: int,
        access_package_id: int,
        member_id: int,
        kind: str = "manual",
    ) -> int:
        answer = await self._http_connector.post(
            "/v1/ownership/grant",
            payload={
                "portal_id": portal_id,
                "access_package_id": access_package_id,
                "member_id": member_id,
                "kind": kind,
            },
            headers={"server_name": self._context.server_name},
        )
        return answer["id"]
