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.server.actor_manager.verify_local_username)],
            user_info: Annotated[UserInfo | None, Security(self.middleware.check_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)
