"""
maintenance.py
Defines additional objects that can be used for maintenance of Phederation instances.
These objects are *not* based on the ActivityStreams vocabulary, they extend the specification.
"""

from abc import ABC
import enum
from typing import override

from pydantic import Field

from phederation.models.activities import APActivity
from phederation.models.objects import APObject
from phederation.utils import ActivityType
from phederation.utils.base import APDateTime, ObjectId


class MaintenanceCommandType(enum.Enum):
    """A subset of types that concern instance maintenance."""

    MAINTENANCE_MODE = "MaintenanceMode"
    MAINTENANCE_MODE_CANCEL = "MaintenanceModeCancel"
    ASSEMBLE_USER_DATA = "AssembleUserData"

    @override
    def __str__(self):
        return str(self.value)


class APMaintenance(APActivity):
    """
    Represents a maintenance activity.
    This extends the ActivityStreams vocabulary to include maintenance information.
    Sending this activity (by an admin, to an instance in admin_mode) executes maintenance commands.
    """

    type: str = ActivityType.MAINTENANCE.value


class APMaintenanceCommand(ABC, APObject):
    """
    Represents an abstract maintenance command.
    """


class APMaintenanceMode(APMaintenanceCommand):
    """
    Represents a maintenance mode command.
    Sending this activity (by an admin, to an instance in admin_mode) will set the related main instance into "maintenance mode".
    The start_time and end_time can be set to start and end the maintenance mode. If they are not set, the mode is started immediately and does not end automatically (must be ended by sending APDelete for the APMaintenance object).
    """

    type: str = MaintenanceCommandType.MAINTENANCE_MODE.value
    start_time: APDateTime | None = Field(default=None, description="Start datetime of the maintenance mode")
    end_time: APDateTime | None = Field(default=None, description="End datetime of the maintenance mode")


class APMaintenanceModeCancel(APMaintenanceCommand):
    """
    Cancels a specific maintenance mode command that was issued earlier.
    This is different from a maintenance mode running over its end_time; the cancel command can stop maintenance mode that is currently running.
    """

    type: str = MaintenanceCommandType.MAINTENANCE_MODE_CANCEL.value
    command_to_cancel: ObjectId = Field(..., description="The id of the command object that should be cancelled")
