"""Pydantic configuration models."""

from __future__ import annotations

from typing import ClassVar, Literal

from pydantic import BaseModel, ConfigDict, Field


def _default_manifest_history() -> list[ManifestHistoryEntry]:
    """Return default manifest history entries.

    Returns:
        Default manifest history list.
    """
    return []


def _default_manifest_dependencies() -> list[ManifestDependency]:
    """Return default manifest dependencies.

    Returns:
        Default dependency list.
    """
    return []


class ManifestExactMatchMode(BaseModel):
    """Represents exact replacement mode."""

    model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")

    type: Literal["exact"]


class ManifestPatternMatchMode(BaseModel):
    """Represents pattern-based replacement mode."""

    model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")

    type: Literal["pattern"]
    value: str


class ManifestAnchorMatchMode(BaseModel):
    """Represents anchor-delimited replacement mode."""

    model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")

    type: Literal["anchor"]
    start_pattern: str
    end_pattern: str


MatchMode = (
    ManifestExactMatchMode
    | ManifestPatternMatchMode
    | ManifestAnchorMatchMode
)


class ManifestDependency(BaseModel):
    """Represents a dependency required by a manifest."""

    model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")

    type: str
    id: str


class ManifestEntry(BaseModel):
    """Represents a single entry in a manifest file."""

    model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")

    id: str
    description: str | None = None
    ref_type: Literal["git", "git_branch", "git_tag", "url"] | None = None
    ref_value: str | None = None
    artifact_path: str
    target_path: str | None = None
    action: Literal["add", "add_overwrite", "append_replace", "append_if_missing"]
    match_mode: MatchMode | None = None


class ManifestHistoryEntry(BaseModel):
    """Represents a manifest history entry."""

    model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")

    version: str
    manifest_url: str


class ManifestIndex(BaseModel):
    """Represents yaml file for a modules manifest."""

    model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")

    version: str
    dependencies: list[ManifestDependency] = Field(
        default_factory=_default_manifest_dependencies,
    )
    entries: list[ManifestEntry]
    manifest_history: list[ManifestHistoryEntry] = Field(
        default_factory=_default_manifest_history,
    )
