from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime
from typing import Any, Protocol


@dataclass(slots=True)
class ProvisionContext:
    instance: Any
    snapshot: dict[str, Any]
    product: Any | None
    order: Any | None
    user: Any | None
    db: Any
    settings: Any
    upstream_params: dict[str, Any] = field(default_factory=dict)
    interface_config: dict[str, Any] = field(default_factory=dict)
    plugin_fields: dict[str, Any] = field(default_factory=dict)
    product_config_values: list[dict[str, Any]] = field(default_factory=list)


@dataclass(slots=True)
class ProvisionResult:
    success: bool = True
    upstream_id: str | int | None = None
    task_id: str | int | None = None
    invoice_id: str | int | None = None
    hostname: str | None = None
    main_ip: str | None = None
    ssh_port: int | None = None
    root_password: str | None = None
    expires_at: datetime | None = None
    links: list[dict[str, Any]] = field(default_factory=list)
    payload: dict[str, Any] = field(default_factory=dict)
    message: str = "Provisioned by plugin"
    retryable: bool = True


@dataclass(slots=True)
class ManageResult:
    success: bool = True
    message: str = "Action completed"
    task_id: str | int | None = None
    payload: dict[str, Any] = field(default_factory=dict)
    retryable: bool = True


class ProvisionPlugin(Protocol):
    async def provision(self, context: ProvisionContext) -> ProvisionResult | dict[str, Any]:
        ...

    async def manage(
        self,
        action: str,
        context: ProvisionContext,
        payload: dict[str, Any] | None = None,
    ) -> ManageResult | dict[str, Any]:
        ...

    async def test(self, config: dict[str, Any] | None = None) -> dict[str, Any]:
        ...


class ProvisionPluginError(Exception):
    def __init__(self, message: str, *, retryable: bool = True):
        super().__init__(message)
        self.retryable = retryable
