"""Hook models for automated environment setup."""

from __future__ import annotations

from enum import StrEnum
from typing import Any

from pydantic import BaseModel, Field, field_validator


class HookType(StrEnum):
    """Supported hook types."""

    COPY = "copy"
    COMMAND = "command"
    TEMPLATE = "template"
    SYMLINK = "symlink"
    MKDIR = "mkdir"
    ENV_UPDATE = "env_update"
    SCRIPT = "script"
    GIT = "git"


class HookErrorStrategy(StrEnum):
    """How to handle hook errors."""

    FAIL = "fail"
    WARN = "warn"
    IGNORE = "ignore"


class Hook(BaseModel):
    """Single hook definition."""

    type: HookType = Field(..., description="Type of hook operation")
    config: dict[str, Any] = Field(..., description="Hook-specific configuration")
    name: str | None = Field(None, description="Human-readable hook name")
    condition: str | None = Field(None, description="Condition for execution")
    on_error: HookErrorStrategy = Field(
        HookErrorStrategy.WARN, description="Error handling strategy"
    )
    timeout: int | None = Field(30, description="Timeout in seconds")

    @field_validator("config")
    @classmethod
    def validate_config(cls, v: dict[str, Any], info: Any) -> dict[str, Any]:
        """Validate config based on hook type."""
        values = info.data
        hook_type = values.get("type")

        if hook_type == HookType.COPY:
            required = ["from", "to"]
            if not all(key in v for key in required):
                raise ValueError(f"Copy hooks require: {required}")

        elif hook_type == HookType.COMMAND:
            if "command" not in v:
                raise ValueError("Command hooks require 'command'")

        elif hook_type == HookType.TEMPLATE:
            required = ["template", "output"]
            if not all(key in v for key in required):
                raise ValueError(f"Template hooks require: {required}")

        elif hook_type == HookType.ENV_UPDATE:
            required = ["file", "updates"]
            if not all(key in v for key in required):
                raise ValueError(f"Env update hooks require: {required}")

        elif hook_type == HookType.SYMLINK:
            required = ["source", "target"]
            if not all(key in v for key in required):
                raise ValueError(f"Symlink hooks require: {required}")

        elif hook_type == HookType.MKDIR:
            if "path" not in v and "paths" not in v:
                raise ValueError("Mkdir hooks require either 'path' or 'paths'")

        elif hook_type == HookType.SCRIPT:
            if "script" not in v:
                raise ValueError("Script hooks require 'script'")

        elif hook_type == HookType.GIT:
            if "operation" not in v:
                raise ValueError("Git hooks require 'operation'")

        return v

    model_config = {"extra": "forbid"}


class HookResult(BaseModel):
    """Result of hook execution."""

    success: bool = Field(..., description="Overall success status")
    executed: list[str] = Field(default_factory=list, description="Successfully executed hooks")
    skipped: list[str] = Field(
        default_factory=list, description="Skipped hooks (condition not met)"
    )
    failed: list[str] = Field(default_factory=list, description="Failed hooks")
    errors: list[str] = Field(default_factory=list, description="Error messages")
    warnings: list[str] = Field(default_factory=list, description="Warning messages")
    duration_ms: int = Field(0, description="Total execution time in milliseconds")

    model_config = {"extra": "forbid"}
