"""Handler for provisioning routes."""

import logging
from collections.abc import Sequence

from ai.backend.common.events.dispatcher import EventProducer
from ai.backend.logging import BraceStyleAdapter
from ai.backend.manager.data.deployment.types import RouteStatus, RouteStatusTransitions
from ai.backend.manager.defs import LockID
from ai.backend.manager.repositories.deployment.types import RouteData
from ai.backend.manager.sokovan.deployment.route.executor import RouteExecutor
from ai.backend.manager.sokovan.deployment.route.types import RouteExecutionResult

from .base import RouteHandler

log = BraceStyleAdapter(logging.getLogger(__name__))


class ProvisioningRouteHandler(RouteHandler):
    """Handler for provisioning routes (PROVISIONING -> UNHEALTHY)."""

    def __init__(
        self,
        route_executor: RouteExecutor,
        event_producer: EventProducer,
    ) -> None:
        self._route_executor = route_executor
        self._event_producer = event_producer

    @classmethod
    def name(cls) -> str:
        """Get the name of the handler."""
        return "provision-routes"

    @property
    def lock_id(self) -> LockID | None:
        """Lock for provisioning routes."""
        return LockID.LOCKID_DEPLOYMENT_PROVISIONING_ROUTES

    @classmethod
    def target_statuses(cls) -> list[RouteStatus]:
        """Get the target route statuses for this handler."""
        return [RouteStatus.PROVISIONING]

    @classmethod
    def next_status(cls) -> RouteStatus | None:
        """Get the next route status after this handler's operation."""
        return RouteStatus.DEGRADED

    @classmethod
    def failure_status(cls) -> RouteStatus | None:
        """Get the failure route status if applicable."""
        return RouteStatus.FAILED_TO_START

    @classmethod
    def stale_status(cls) -> RouteStatus | None:
        """Get the stale route status if applicable."""
        return None

    @classmethod
    def status_transitions(cls) -> RouteStatusTransitions:
        """Define state transitions for provisioning route handler (BEP-1030).

        - success: Route → DEGRADED (provisioned, needs health check)
        - failure: Route → FAILED_TO_START
        - stale: None
        """
        return RouteStatusTransitions(
            success=RouteStatus.DEGRADED,
            failure=RouteStatus.FAILED_TO_START,
            stale=None,
        )

    async def execute(self, routes: Sequence[RouteData]) -> RouteExecutionResult:
        """Execute provisioning for routes."""
        log.debug("Provisioning {} routes", len(routes))

        # Execute route provisioning logic via executor
        return await self._route_executor.provision_routes(routes)

    async def post_process(self, result: RouteExecutionResult) -> None:
        """Handle post-processing after provisioning routes."""
        log.info(
            "Provisioned {} routes successfully, {} failed",
            len(result.successes),
            len(result.errors),
        )
