from typing import override

from fastapi import FastAPI

from phederation.federation import ActivityPubMiddleware, ActivityPubServer
from phederation.utils.settings import PhedSettings

from .base import BaseAPI
from .routes import BaseRoute as PhederationBaseRoute
from .routes.v1 import (
    AccountRoute,
    ActivityRoute,
    ActorRoute,
    AdminInstanceRoute,
    InstanceRoute,
    KeyRoute,
    MediaRoute,
    ObjectRoute,
    ProofRoute,
    SecurityRoute,
    WebfingerRoute,
)


class APIv1(BaseAPI):
    """Version 1 of the API.
    Sub-versions 1.1, 1.2, etc. are managed by this one.
    """

    @override
    async def initialize(self, app: FastAPI, settings: PhedSettings, middleware: ActivityPubMiddleware, server: ActivityPubServer) -> None:
        await super().initialize(app=app, settings=settings, server=server, middleware=middleware)

        self._routes: list[PhederationBaseRoute] = self.routes()
        for route in self._routes:
            await route.initialize(app=app, middleware=middleware, api=self, server=server)
            app.include_router(route.router)

    def routes(self) -> list[PhederationBaseRoute]:
        self.logger.info("Initializing API with basic routes.")
        result: list[PhederationBaseRoute] = [
            ActorRoute(),
            AccountRoute(),
            WebfingerRoute(),
            ActivityRoute(),
            ObjectRoute(),
            KeyRoute(),
            ProofRoute(),
            InstanceRoute(),
            SecurityRoute(),
            MediaRoute(),
        ]
        if self.settings.federation.admin_mode:
            self.logger.info("Adding additional admin routes.")
            result.extend([AdminInstanceRoute()])
        return result

    @override
    def version(self, major: bool = True, minor: bool = True, patch: bool = True) -> str:
        """API version string.

        The string consists of MAJOR.MINOR.PATCH version numbers. If any of the arguments is set to False, the version number is replaced by X.

        Examples:
          - version() = "1.0.0"
          - version(minor=False) = "1.X.0"
          - version(major=Fales, minor=False, patch=False) = "X.X.X"

        Args:
            major (bool, optional): Return major API version. Will only change if the entire API is changed. Defaults to True.
            minor (bool, optional): Return minor API version. Will change with milestones. Defaults to True.
            patch (bool, optional): Return patch API version. Will change on bugfixes, and should not break behavior of the API. Defaults to True.

        Returns:
            str: Version string.
        """
        v: list[str] = []
        if major:
            v.append("1")
        else:
            v.append("X")
        if minor:
            v.append("0")
        else:
            v.append("X")
        if patch:
            v.append("0")
        else:
            v.append("X")
        return ".".join(v)
