"""Worktree domain models."""

from __future__ import annotations

from datetime import datetime
from enum import StrEnum
from pathlib import Path
from typing import Any

from pydantic import BaseModel, Field, field_serializer, field_validator

from .base import DataResult


class WorktreeStatus(StrEnum):
    """Worktree status states."""

    ACTIVE = "active"
    LOCKED = "locked"
    PRUNABLE = "prunable"
    MISSING = "missing"


class Worktree(BaseModel):
    """Represents a git worktree."""

    id: str = Field(..., description="Unique identifier")
    name: str = Field(..., description="Worktree name")
    branch: str = Field(..., description="Associated git branch")
    path: Path = Field(..., description="Absolute path to worktree")
    head_sha: str = Field(..., description="Current HEAD commit SHA")
    status: WorktreeStatus = Field(..., description="Current status")
    is_current: bool = Field(default=False, description="Is this the current worktree")
    is_base: bool = Field(default=False, description="Is this the base/main worktree")
    created_at: datetime | None = Field(None, description="Creation timestamp")
    last_accessed: datetime | None = Field(None, description="Last access time")

    model_config = {"frozen": True, "extra": "forbid"}

    @field_validator("id", "name", "branch")
    @classmethod
    def validate_strings_not_empty(cls, v: str) -> str:
        """Validate string fields are not empty or contain only whitespace."""
        if not v or not v.strip():
            raise ValueError("Field cannot be empty or whitespace")
        return v.strip()

    @field_validator("head_sha")
    @classmethod
    def validate_sha(cls, v: str) -> str:
        """Validate SHA is a valid git commit hash."""
        if not v or len(v) < 7 or len(v) > 40:
            raise ValueError("Invalid SHA format")
        if not all(c in "0123456789abcdefABCDEF" for c in v):
            raise ValueError("SHA must contain only hexadecimal characters")
        return v.lower()

    @field_validator("path")
    @classmethod
    def validate_path(cls, v: Path) -> Path:
        """Validate path is absolute and safe."""
        if not v.is_absolute():
            raise ValueError("Worktree path must be absolute")

        # Prevent path traversal attacks
        resolved_path = v.resolve()
        if ".." in str(resolved_path):
            raise ValueError("Path contains invalid traversal components")

        return resolved_path

    @field_serializer("path")
    def serialize_path(self, path: Path) -> str:
        """Serialize Path to string."""
        return str(path)

    @field_serializer("created_at", "last_accessed", when_used="json")
    def serialize_datetime(self, dt: datetime | None) -> str | None:
        """Serialize datetime to ISO format."""
        return dt.isoformat() if dt else None


class WorktreeSafetyResult(BaseModel):
    """Result of worktree safety checks."""

    is_safe: bool = Field(..., description="Whether the worktree is safe to delete")
    issues: list[str] = Field(default_factory=list, description="Safety issues found")

    model_config = {"extra": "forbid"}


class WorktreeResult(DataResult[Worktree]):
    """Result of worktree operations."""

    color: Any | None = Field(None, description="Assigned color if applicable")
    hook_info: dict[str, Any] | None = Field(None, description="Hook execution information")

    @classmethod
    def create_success_with_color(
        cls, worktree: Worktree, color: Any = None, hook_info: dict[str, Any] | None = None
    ) -> WorktreeResult:
        """Create a successful result with worktree and color data."""
        return cls(success=True, data=worktree, color=color, hook_info=hook_info)

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

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


class WorktreeListResult(DataResult[list[Worktree]]):
    """Result of listing worktrees."""

    total: int = Field(..., description="Total count of worktrees")

    @classmethod
    def create_success(cls, worktrees: list[Worktree]) -> WorktreeListResult:
        """Create a successful result with worktrees list."""
        return cls(success=True, data=worktrees, total=len(worktrees))

    @property
    def worktrees(self) -> list[Worktree]:
        """Get the worktrees list (alias for data)."""
        return self.data or []
