"""Pydantic schemas for semantic tag structures."""

from datetime import datetime
from enum import Enum
from typing import Optional
from uuid import UUID

from pydantic import BaseModel, Field, field_validator


class TagSource(str, Enum):
    """Source of tag assignment."""

    AI = "ai"
    HUMAN = "human"
    INHERITANCE_DOC = "inheritance_doc"
    INHERITANCE_HEADER = "inheritance_header"


class TagStatus(str, Enum):
    """Tag verification status."""

    PENDING = "pending"
    VERIFIED = "verified"
    REJECTED = "rejected"
    DELETED = "deleted"


class TagHistoryAction(str, Enum):
    """Actions tracked in tag history."""

    SUGGESTED = "suggested"
    CONFIRMED = "confirmed"
    REJECTED = "rejected"
    EDITED = "edited"
    MIGRATED = "migrated"


class TagHistoryEntry(BaseModel):
    """Single history entry for a tag."""

    action: TagHistoryAction
    by: str = Field(..., description="User ID or 'system' or 'ai'")
    ts: int = Field(..., description="Unix timestamp (seconds)")

    model_config = {"frozen": True}


class TagAssignment(BaseModel):
    """Tag assignment with full metadata (spec Section 5.1B).

    This is the structure stored in extracted_records.tags JSONB column.
    """

    tag_id: str = Field(..., description="UUID for this specific tag assignment")
    name: str = Field(
        ...,
        description="Tag in namespace:value format (e.g., 'req:functional')",
        min_length=3,
    )
    source: TagSource = Field(..., description="Source of tag assignment")
    confidence: float = Field(
        ..., ge=0.0, le=1.0, description="Confidence score (0.0-1.0)"
    )
    status: TagStatus = Field(..., description="Verification status")
    history: list[TagHistoryEntry] = Field(
        default_factory=list, description="Audit trail"
    )

    @field_validator("name")
    @classmethod
    def validate_tag_format(cls, v: str) -> str:
        """Validate tag has namespace:value format."""
        if ":" not in v:
            raise ValueError("Tag must be in 'namespace:value' format (e.g., 'req:functional')")
        namespace, value = v.split(":", 1)
        if not namespace or not value:
            raise ValueError("Both namespace and value must be non-empty")
        return v

    model_config = {"frozen": False}


class TagCreate(BaseModel):
    """Schema for creating a new tag assignment."""

    name: str = Field(
        ...,
        description="Tag in namespace:value format",
        examples=["req:functional", "topic:authentication"],
    )
    replace_tag_id: Optional[str] = Field(
        None, description="If editing, UUID of tag to replace"
    )

    @field_validator("name")
    @classmethod
    def validate_tag_format(cls, v: str) -> str:
        """Validate tag has namespace:value format."""
        if ":" not in v:
            raise ValueError("Tag must be in 'namespace:value' format")
        return v


class TagReviewDecision(str, Enum):
    """Decision options for tag review."""

    CONFIRM = "confirm"
    REJECT = "reject"


class TagReview(BaseModel):
    """Schema for reviewing a pending tag (HITL workflow)."""

    tag_id: str = Field(..., description="UUID of tag to review")
    decision: TagReviewDecision = Field(..., description="Confirm or reject")
    reason: Optional[str] = Field(
        None, description="Optional reason for rejection", max_length=500
    )


class TagFilter(BaseModel):
    """Filter criteria for tag-based retrieval (spec Section 6.2)."""

    must_have: Optional[list[str]] = Field(
        None, description="Tags that must be present (exact match)"
    )
    min_confidence: Optional[float] = Field(
        None, ge=0.0, le=1.0, description="Minimum confidence threshold"
    )
    domain_profile: Optional[list[str]] = Field(
        None, description="Filter by domain profile (e.g., 'fintech')"
    )
    namespaces: Optional[list[str]] = Field(
        None, description="Filter by namespace (e.g., ['req', 'topic'])"
    )
    status: Optional[list[TagStatus]] = Field(
        None, description="Include specific statuses (default: verified only)"
    )


class RecordTagsResponse(BaseModel):
    """Response schema for GET /blocks/{id}/tags."""

    record_id: UUID
    tags: list[TagAssignment]


class TagReviewResponse(BaseModel):
    """Response schema for POST /blocks/{id}/tags/review."""

    success: bool
    tag_id: str
    new_status: TagStatus
    message: Optional[str] = None


class TagCreateResponse(BaseModel):
    """Response schema for POST /blocks/{id}/tags."""

    success: bool
    tag: TagAssignment
    validation_warnings: Optional[list[str]] = None
