"""Base domain models for Portal."""

from __future__ import annotations

from typing import Any, Generic, TypeVar

from pydantic import BaseModel, Field

T = TypeVar("T")


class BaseResult(BaseModel):
    """Base result for all service operations."""

    success: bool = Field(..., description="Whether the operation succeeded")
    errors: list[str] = Field(default_factory=list, description="Error messages")
    warnings: list[str] = Field(default_factory=list, description="Warning messages")

    model_config = {"extra": "forbid"}

    def add_error(self, message: str) -> None:
        """Add an error message to the result."""
        self.errors.append(message)
        self.success = False

    def add_warning(self, message: str) -> None:
        """Add a warning message to the result."""
        self.warnings.append(message)

    def has_errors(self) -> bool:
        """Check if the result has any errors."""
        return len(self.errors) > 0

    def has_warnings(self) -> bool:
        """Check if the result has any warnings."""
        return len(self.warnings) > 0


class SuccessResult(BaseResult):
    """Success result without data."""

    success: bool = Field(default=True, description="Always True for success results")


class DataResult(BaseResult, Generic[T]):
    """Result that includes data of generic type T."""

    data: T | None = Field(default=None, description="Result data")

    @classmethod
    def create_success(cls, data: T) -> DataResult[T]:
        """Create a successful result with data."""
        return cls(success=True, data=data)

    @classmethod
    def create_failure(cls, error: str) -> DataResult[T]:
        """Create a failed result with error message."""
        return cls(success=False, errors=[error])

    @classmethod
    def create_failure_with_errors(cls, errors: list[str]) -> DataResult[T]:
        """Create a failed result with multiple error messages."""
        return cls(success=False, errors=errors)


class HookExecutionResult(BaseResult):
    """Result containing hook execution details."""

    hook_details: dict[str, Any] | None = Field(None, description="Hook execution details")

    model_config = {"extra": "forbid"}
