from http import HTTPStatus
from typing import Annotated, override

from fastapi import Body, Depends, HTTPException, Security
from fastapi.responses import JSONResponse

from phederation.api.routes.base import BaseRoute
from phederation.models import (
    APUser,
)
from phederation.models.activities import APUpdate
from phederation.models.actors import APAccount, APActor
from phederation.security.authentication import UserInfo
from phederation.utils.exceptions import (
    ActivityPubException,
    AuthorizationError,
    UserError,
)


class AccountRoute(BaseRoute):

    @override
    def setup(self):

        @self.router.get(
            "/accounts/{username}",
            tags=["accounts"],
            response_model=APAccount,
            response_model_exclude_none=True,
        )
        async def get_account_route(  # pyright: ignore[reportUnusedFunction]
            actor: Annotated[APActor, Depends(self.middleware.authentication.verify_local_username)],
            user_info: Annotated[UserInfo | None, Security(self.middleware.authentication, scopes=["user"])],
        ) -> APAccount:
            """Handle user account requests."""
            actor_for_authorization = user_info.actor_id if user_info else None

            if not actor.id or not actor_for_authorization or actor.id != actor_for_authorization:
                raise AuthorizationError(
                    f"Accounts can only be accessed by their associated actor. Actor '{actor_for_authorization}' is not the correct actor for account with id '{actor.id}'"
                )

            account = await self.api.server.storage.account.read(actor_for_authorization)
            if not account:
                raise UserError(f"Account for username '{actor.id}' not found")

            return account

        @self.router.put(
            "/accounts",
            tags=["users"],
            response_model_exclude_none=True,
            dependencies=[Security(self.middleware.authorization, scopes=["user"])],
        )
        async def update_account(  # pyright: ignore[reportUnusedFunction]
            user: Annotated[
                APUser,
                Body(description="The actor associated to the account."),
            ],
            user_account: Annotated[
                APAccount,
                Body(description="The information to update the account on the instance."),
            ],
        ):
            """Update the details of a user account."""
            activity = APUpdate(object=user_account, actor=user, summary="Update a given account.")
            try:
                actor_id = await self.server.update_account(activity=activity)
                return JSONResponse(
                    content={"Status": "OK", "location": actor_id, "detail": "User account updated successfully"},
                    status_code=HTTPStatus.OK,
                    media_type="application/activity+json",
                    headers={"Location": actor_id},
                )
            except ActivityPubException as e:
                self.logger.error(f"AccountRoute handler error in update_account: {e.message}")
                raise HTTPException(detail="User account could not be updated", status_code=HTTPStatus.BAD_REQUEST)
