"""Expert overrides and feedback models."""

from datetime import datetime, timezone
from enum import Enum
from typing import Any

from pydantic import Field

from semantic_model.base import SemanticBaseModel, JsonPath, SourceId
from semantic_model.confidence import ConfidenceObjectType


class OverrideStatus(str, Enum):
    """Status of an expert override."""

    ACTIVE = "active"
    SUPERSEDED = "superseded"
    REVERTED = "reverted"


class ReindexScope(str, Enum):
    """Scope of reindexing triggered by an override."""

    THIS_OBJECT = "this_object"
    THIS_SOURCE = "this_source"
    DEPENDENT_SOURCES = "dependent_sources"
    FULL = "full"


class ExpertOverride(SemanticBaseModel):
    """An override made by a domain expert to correct or enhance agent output."""

    id: str = Field(..., description="Unique override ID")
    created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
    created_by: str = Field(..., description="Expert identifier")

    # Target object
    object_type: ConfidenceObjectType = Field(..., description="Type of object being overridden")
    object_id: str = Field(..., description="ID of the object being overridden")

    # What was overridden
    field_path: JsonPath = Field(
        ...,
        description="JSON path to field: 'description', 'semantic_type.category'",
    )
    original_value: Any = Field(..., description="Value before override")
    override_value: Any = Field(..., description="New value set by expert")

    # Context
    reason: str = Field(..., description="Why the expert made this change")
    additional_context: str = Field(
        default="",
        description="Extra context for the reindexing agent",
    )

    # Impact
    should_trigger_reindex: bool = Field(default=True)
    reindex_scope: ReindexScope = Field(default=ReindexScope.THIS_OBJECT)

    # Status
    status: OverrideStatus = Field(default=OverrideStatus.ACTIVE)
    superseded_by: str | None = Field(
        default=None,
        description="ID of override that replaced this one",
    )

    def supersede(self, new_override_id: str) -> "ExpertOverride":
        """Mark this override as superseded by a new one."""
        return self.model_copy(
            update={
                "status": OverrideStatus.SUPERSEDED,
                "superseded_by": new_override_id,
            }
        )

    def revert(self) -> "ExpertOverride":
        """Mark this override as reverted."""
        return self.model_copy(update={"status": OverrideStatus.REVERTED})


class FeedbackType(str, Enum):
    """Types of feedback an expert can provide."""

    CORRECTION = "correction"
    CLARIFICATION = "clarification"
    ENHANCEMENT = "enhancement"
    APPROVAL = "approval"


class FeedbackPriority(str, Enum):
    """Priority of a feedback item."""

    CRITICAL = "critical"
    HIGH = "high"
    MEDIUM = "medium"
    LOW = "low"


class FeedbackItem(SemanticBaseModel):
    """A single item of feedback from a domain expert."""

    object_type: ConfidenceObjectType
    object_id: str = Field(..., description="ID of the object")
    feedback_type: FeedbackType
    field_path: JsonPath = Field(..., description="Path to the field")
    current_value: Any = Field(..., description="Current agent-generated value")
    suggested_value: Any = Field(..., description="Expert's suggested value")
    explanation: str = Field(..., description="Why this change is needed")
    priority: FeedbackPriority = Field(default=FeedbackPriority.MEDIUM)


class FeedbackAssessment(str, Enum):
    """Overall assessment of a source by an expert."""

    APPROVED = "approved"
    NEEDS_WORK = "needs_work"
    REJECTED = "rejected"


class ExpertFeedback(SemanticBaseModel):
    """Structured feedback from a domain expert during review."""

    id: str = Field(..., description="Unique feedback ID")
    source_id: SourceId = Field(..., description="Source being reviewed")
    created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
    expert_id: str = Field(..., description="Expert who provided feedback")

    items: list[FeedbackItem] = Field(default_factory=list)

    overall_assessment: FeedbackAssessment
    general_notes: str = Field(default="", description="General notes about the source")

    processed: bool = Field(default=False, description="Whether feedback has been processed")
    reindex_job_id: str | None = Field(
        default=None,
        description="ID of reindex job triggered by this feedback",
    )
    processed_at: datetime | None = Field(default=None)

    def mark_processed(self, reindex_job_id: str) -> "ExpertFeedback":
        """Mark feedback as processed."""
        return self.model_copy(
            update={
                "processed": True,
                "reindex_job_id": reindex_job_id,
                "processed_at": datetime.now(timezone.utc),
            }
        )

    @property
    def critical_items(self) -> list[FeedbackItem]:
        """Get critical priority items."""
        return [i for i in self.items if i.priority == FeedbackPriority.CRITICAL]

    @property
    def correction_count(self) -> int:
        """Count of correction items."""
        return len([i for i in self.items if i.feedback_type == FeedbackType.CORRECTION])
