from http import HTTPStatus
from typing import Annotated, override

from fastapi import HTTPException, Security

from phederation.api.routes.base import BaseRoute
from phederation.models import (
    ErrorMessageActivityNotFound,
    ErrorMessageActivityRestricted,
)
from phederation.models.activities import APActivity
from phederation.security.authentication import UserInfo
from phederation.utils.base import UrlType, assemble_id_url


class ActivityRoute(BaseRoute):

    @override
    def setup(self):

        @self.router.get(
            "/activities/{activity_id}",
            tags=["activities"],
            status_code=HTTPStatus.OK,
            response_model_exclude_none=True,
            responses={
                HTTPStatus.NOT_FOUND: {
                    "model": ErrorMessageActivityNotFound,
                    "description": ErrorMessageActivityNotFound().description,
                },
                HTTPStatus.BAD_REQUEST: {
                    "model": ErrorMessageActivityRestricted,
                    "description": ErrorMessageActivityRestricted().description,
                },
            },
        )
        async def get_activity(  # pyright: ignore[reportUnusedFunction]
            activity_id: str, user_info: Annotated[UserInfo | None, Security(self.middleware.authentication, scopes=["user"])] = None
        ) -> APActivity:
            """Return activity with given id, if accessible."""
            activity_id = assemble_id_url(
                base_url=self.api.settings.domain.base_url,
                primary=activity_id,
                type=UrlType.Activities,
            )
            activity: APActivity | None = await self.server.storage.activity.read(id=activity_id)
            if not activity:
                raise HTTPException(
                    status_code=HTTPStatus.NOT_FOUND,
                    detail=ErrorMessageActivityNotFound().message,
                )

            actor_requesting_access = user_info.actor_id if user_info else None
            activity_with_access = await self.api.server.resolver.resolve_access_type(
                object=activity, actor_requesting_access=actor_requesting_access
            )
            if not activity_with_access or not isinstance(activity_with_access, APActivity):
                self.logger.warning(f"Activity visibility restricted, user: {user_info} cannot access it")
                raise HTTPException(
                    status_code=HTTPStatus.BAD_REQUEST,
                    detail=ErrorMessageActivityRestricted().message,
                )
            return activity_with_access
