"""
Task Context Type.

Represents the current task or objective for the agent.
"""

from dataclasses import dataclass, field
from datetime import UTC, datetime
from enum import Enum
from typing import Any

from .base import BaseContext, ContextPriority, ContextType


class TaskStatus(str, Enum):
    """Status of a task."""

    PENDING = "pending"
    IN_PROGRESS = "in_progress"
    BLOCKED = "blocked"
    COMPLETED = "completed"
    FAILED = "failed"


class TaskComplexity(str, Enum):
    """Complexity level of a task."""

    TRIVIAL = "trivial"
    SIMPLE = "simple"
    MODERATE = "moderate"
    COMPLEX = "complex"
    VERY_COMPLEX = "very_complex"


@dataclass(eq=False)
class TaskContext(BaseContext):
    """
    Context for the current task or objective.

    Task context provides information about what the agent
    should accomplish, including:
    - Task description and goals
    - Acceptance criteria
    - Constraints and requirements
    - Related issue/ticket information
    """

    # Task-specific fields
    title: str = field(default="")
    status: TaskStatus = field(default=TaskStatus.PENDING)
    complexity: TaskComplexity = field(default=TaskComplexity.MODERATE)
    issue_id: str | None = field(default=None)
    project_id: str | None = field(default=None)
    acceptance_criteria: list[str] = field(default_factory=list)
    constraints: list[str] = field(default_factory=list)
    parent_task_id: str | None = field(default=None)

    # Note: TaskContext should typically have HIGH priority,
    # but we don't auto-promote to allow explicit priority setting.
    # Use TaskContext.create() for default HIGH priority behavior.

    def get_type(self) -> ContextType:
        """Return TASK context type."""
        return ContextType.TASK

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary with task-specific fields."""
        base = super().to_dict()
        base.update(
            {
                "title": self.title,
                "status": self.status.value,
                "complexity": self.complexity.value,
                "issue_id": self.issue_id,
                "project_id": self.project_id,
                "acceptance_criteria": self.acceptance_criteria,
                "constraints": self.constraints,
                "parent_task_id": self.parent_task_id,
            }
        )
        return base

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> "TaskContext":
        """Create TaskContext from dictionary."""
        status = data.get("status", "pending")
        if isinstance(status, str):
            status = TaskStatus(status)

        complexity = data.get("complexity", "moderate")
        if isinstance(complexity, str):
            complexity = TaskComplexity(complexity)

        return cls(
            id=data.get("id", ""),
            content=data["content"],
            source=data.get("source", "task"),
            timestamp=datetime.fromisoformat(data["timestamp"])
            if isinstance(data.get("timestamp"), str)
            else data.get("timestamp", datetime.now(UTC)),
            priority=data.get("priority", ContextPriority.HIGH.value),
            metadata=data.get("metadata", {}),
            title=data.get("title", ""),
            status=status,
            complexity=complexity,
            issue_id=data.get("issue_id"),
            project_id=data.get("project_id"),
            acceptance_criteria=data.get("acceptance_criteria", []),
            constraints=data.get("constraints", []),
            parent_task_id=data.get("parent_task_id"),
        )

    @classmethod
    def create(
        cls,
        title: str,
        description: str,
        acceptance_criteria: list[str] | None = None,
        constraints: list[str] | None = None,
        issue_id: str | None = None,
        project_id: str | None = None,
        complexity: TaskComplexity | str = TaskComplexity.MODERATE,
    ) -> "TaskContext":
        """
        Create a task context.

        Args:
            title: Task title
            description: Task description
            acceptance_criteria: List of acceptance criteria
            constraints: List of constraints
            issue_id: Related issue ID
            project_id: Project ID
            complexity: Task complexity

        Returns:
            TaskContext instance
        """
        if isinstance(complexity, str):
            complexity = TaskComplexity(complexity)

        return cls(
            content=description,
            source=f"task:{issue_id}" if issue_id else "task",
            title=title,
            status=TaskStatus.IN_PROGRESS,
            complexity=complexity,
            issue_id=issue_id,
            project_id=project_id,
            acceptance_criteria=acceptance_criteria or [],
            constraints=constraints or [],
        )

    def format_for_prompt(self) -> str:
        """
        Format task for inclusion in prompt.

        Returns:
            Formatted task string
        """
        parts = []

        if self.title:
            parts.append(f"Task: {self.title}")
            parts.append("")

        parts.append(self.content)

        if self.acceptance_criteria:
            parts.append("")
            parts.append("Acceptance Criteria:")
            for criterion in self.acceptance_criteria:
                parts.append(f"- {criterion}")

        if self.constraints:
            parts.append("")
            parts.append("Constraints:")
            for constraint in self.constraints:
                parts.append(f"- {constraint}")

        return "\n".join(parts)

    def is_active(self) -> bool:
        """Check if task is currently active."""
        return self.status in (TaskStatus.PENDING, TaskStatus.IN_PROGRESS)

    def is_complete(self) -> bool:
        """Check if task is complete."""
        return self.status == TaskStatus.COMPLETED

    def is_blocked(self) -> bool:
        """Check if task is blocked."""
        return self.status == TaskStatus.BLOCKED
