"""Execution result models for tracking task execution."""

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


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

    PENDING = "pending"
    IN_PROGRESS = "in_progress"
    COMPLETED = "completed"
    FAILED = "failed"
    SKIPPED = "skipped"


class RunStatus(str, Enum):
    """Status of an entire run."""

    PENDING = "pending"
    IN_PROGRESS = "in_progress"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELLED = "cancelled"


@dataclass
class HookResult:
    """Result of executing a hook command."""

    command: str
    exit_code: int
    output: str
    duration_seconds: float
    success: bool = field(init=False)

    def __post_init__(self) -> None:
        """Set success based on exit code."""
        self.success = self.exit_code == 0

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary representation.

        Returns:
            Dictionary containing hook result data.
        """
        return {
            "command": self.command,
            "exit_code": self.exit_code,
            "output": self.output,
            "duration_seconds": self.duration_seconds,
        }


@dataclass
class TaskAttempt:
    """Record of a single task execution attempt."""

    attempt_number: int
    started_at: datetime
    completed_at: datetime | None = None
    duration_seconds: float = 0.0
    prompt: str = ""
    claude_code_output: str = ""
    tokens_used: int = 0
    cost_usd: float = 0.0
    pre_task_hooks: list[HookResult] = field(default_factory=list)
    post_task_hooks: list[HookResult] = field(default_factory=list)
    outcome: str = ""  # "success", "failure", "error"
    error: str | None = None

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary representation.

        Returns:
            Dictionary containing attempt data.
        """
        return {
            "attempt_number": self.attempt_number,
            "started_at": self.started_at.isoformat(),
            "completed_at": self.completed_at.isoformat() if self.completed_at else None,
            "duration_seconds": self.duration_seconds,
            "prompt": self.prompt,
            "claude_code_output": self.claude_code_output,
            "tokens_used": self.tokens_used,
            "cost_usd": self.cost_usd,
            "pre_task_hooks": [h.to_dict() for h in self.pre_task_hooks],
            "post_task_hooks": [h.to_dict() for h in self.post_task_hooks],
            "outcome": self.outcome,
            "error": self.error,
        }


@dataclass
class GitInfo:
    """Git information for a task execution."""

    branch: str | None = None
    commits: list[dict[str, str]] = field(default_factory=list)
    pr_url: str | None = None

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary representation.

        Returns:
            Dictionary containing git info.
        """
        return {
            "branch": self.branch,
            "commits": self.commits,
            "pr_url": self.pr_url,
        }


@dataclass
class ExecutionResult:
    """Complete result of executing a task."""

    task_id: str
    title: str
    run_id: str
    status: TaskStatus
    attempts: list[TaskAttempt] = field(default_factory=list)
    files_changed: list[str] = field(default_factory=list)
    git_info: GitInfo = field(default_factory=GitInfo)
    summary: str = ""

    @property
    def total_tokens(self) -> int:
        """Calculate total tokens used across all attempts.

        Returns:
            Total number of tokens used.
        """
        return sum(a.tokens_used for a in self.attempts)

    @property
    def total_cost(self) -> float:
        """Calculate total cost across all attempts.

        Returns:
            Total cost in USD.
        """
        return sum(a.cost_usd for a in self.attempts)

    @property
    def total_duration(self) -> float:
        """Calculate total duration across all attempts.

        Returns:
            Total duration in seconds.
        """
        return sum(a.duration_seconds for a in self.attempts)

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary representation.

        Returns:
            Dictionary containing all execution result data.
        """
        return {
            "version": "1.0",
            "task_id": self.task_id,
            "title": self.title,
            "run_id": self.run_id,
            "status": self.status.value,
            "attempts": [a.to_dict() for a in self.attempts],
            "final_status": self.status.value,
            "files_changed": self.files_changed,
            "git": self.git_info.to_dict(),
            "summary": self.summary,
        }


@dataclass
class RunSummary:
    """Summary of an entire execution run."""

    run_id: str
    started_at: datetime
    completed_at: datetime | None = None
    status: RunStatus = RunStatus.PENDING
    tasks_file: str = ""
    git_strategy: str = "none"
    total_tasks: int = 0
    completed_tasks: int = 0
    failed_tasks: int = 0
    skipped_tasks: int = 0
    total_duration_seconds: float = 0.0
    total_tokens_used: int = 0
    total_cost_usd: float = 0.0
    task_results: list[ExecutionResult] = field(default_factory=list)

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary representation.

        Returns:
            Dictionary containing run summary data.
        """
        return {
            "run_id": self.run_id,
            "started_at": self.started_at.isoformat(),
            "completed_at": self.completed_at.isoformat() if self.completed_at else None,
            "status": self.status.value,
            "tasks_file": self.tasks_file,
            "git_strategy": self.git_strategy,
            "total_tasks": self.total_tasks,
            "completed_tasks": self.completed_tasks,
            "failed_tasks": self.failed_tasks,
            "skipped_tasks": self.skipped_tasks,
            "total_duration_seconds": self.total_duration_seconds,
            "total_tokens_used": self.total_tokens_used,
            "total_cost_usd": self.total_cost_usd,
            "task_refs": [
                {
                    "task_id": r.task_id,
                    "status": r.status.value,
                    "log_file": f"runs/{self.run_id}/{r.task_id}.json",
                }
                for r in self.task_results
            ],
        }
