from typing import Annotated, List, Optional, Literal

from pydantic import BaseModel, ConfigDict, Field, model_validator

from .generics import ResourceItem, ResourceList
from .types import VehicleType


class RuleProvider(BaseModel):
    """Rule Provider"""
    model_config = ConfigDict(
        str_strip_whitespace=True,
        validate_assignment=True,
    )

    type: VehicleType = Field(..., description="Provider type")
    url: Optional[str] = Field(default=None, description="Must be configured if the type is http")
    path: Optional[str] = Field(default=None, description="Optional, file path, must be unique.")
    interval: Optional[int] = Field(default=None, ge=0, description="The update interval for the provider, in seconds.")
    proxy: Optional[str] = Field(default=None, description="Download/update through the specified proxy.")
    behavior: Optional[Literal["domain", "ipcidr", "classical"]] = Field(None,
                                                                         description="Behavior of the rule provider")
    format: Literal["yaml", "text", "mrs"] = Field("yaml", description="Format of the rule provider file")
    size_limit: Annotated[int, Field(
        default=0, ge=0, validation_alias="size-limit", serialization_alias="size-limit",
        description="The maximum size of downloadable files in bytes (0 for no limit)")
    ] = 0
    payload: Optional[List[str]] = Field(default=None, description="Content, only effective when type is inline")

    @model_validator(mode="before")
    @classmethod
    def validate_type_relationships(cls, values):
        """Perform cross-field validation before the model is created."""
        type_ = values.get('type')
        url = values.get('url')
        path = values.get('path')
        payload = values.get('payload')
        format_ = values.get('format', 'yaml')
        behavior = values.get('behavior')

        # url check
        if type_ == "http" and url is None:
            raise ValueError("url must be configured if the type is 'http'")
        if type_ != "http" and 'url' in values:
            values['url'] = None

        # path check
        if type_ == "file" and path is None:
            raise ValueError("path must be configured if the type is 'file'")
        if type_ != "file" and 'path' in values:
            values['path'] = None

        # payload handling
        if type_ == "inline":
            if payload is None:
                raise ValueError("payload must be configured if the type is 'inline'")
            if not isinstance(payload, list):
                raise ValueError("payload must be a list of strings when type is 'inline'")
        elif 'payload' in values:
            values['payload'] = None

        # format-behavior rule
        if format_ == "mrs" and behavior not in {"domain", "ipcidr"}:
            raise ValueError("mrs format only supports 'domain' or 'ipcidr' behavior")

        return values


class RuleProviderData(ResourceItem[RuleProvider]):
    """Rule Provider Data"""
    pass


class RuleProviders(ResourceList[RuleProviderData]):
    """Rule Providers Collection"""
    pass
