"""
Progress reporting system for real-time task execution visibility.

This module provides progress reporting during task execution, allowing
users and systems to track the status of running tasks in real-time.

Requirements: AGENT-07 (progress reporting)
"""

from typing import Callable, Optional, List, Dict, Any
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
import logging

logger = logging.getLogger(__name__)


class ProgressStatus(str, Enum):
    """Status of a task or step."""

    PENDING = "pending"
    STARTING = "starting"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"
    RETRYING = "retrying"


@dataclass
class ProgressEvent:
    """A progress event emitted during execution.

    Events capture the state change, task information, and any
    relevant details for logging or display.
    """

    status: ProgressStatus
    task: str
    detail: str
    timestamp: str = field(default_factory=lambda: datetime.utcnow().isoformat())
    metadata: Dict[str, Any] = field(default_factory=dict)


# Type alias for progress callback functions
ProgressCallback = Callable[[ProgressEvent], None]


class ProgressReporter:
    """Report progress during execution (AGENT-07).

    This class provides a centralized way to report progress events
    during task execution. It supports:

    - Logging progress to the standard logging system
    - Calling custom callbacks for real-time updates
    - Tracking history for debugging and summary

    Example:
        ```python
        from gsd_rlm.execution.progress import ProgressReporter, ProgressStatus

        def my_callback(event):
            print(f"[{event.status.value}] {event.task}: {event.detail}")

        reporter = ProgressReporter(callback=my_callback)

        reporter.starting("task-1", "Beginning analysis")
        # ... do work ...
        reporter.completed("task-1", "Analysis complete")
        ```
    """

    def __init__(
        self,
        callback: Optional[ProgressCallback] = None,
        log_level: int = logging.INFO,
    ):
        """Initialize the progress reporter.

        Args:
            callback: Optional callback invoked on each event
            log_level: Logging level for progress messages
        """
        self.callback = callback
        self.log_level = log_level
        self._events: List[ProgressEvent] = []

    def report(
        self,
        status: ProgressStatus,
        task: str,
        detail: str = "",
        **metadata,
    ) -> ProgressEvent:
        """Report a progress event.

        Args:
            status: The status to report
            task: Task identifier or description
            detail: Additional detail message
            **metadata: Additional metadata to include

        Returns:
            The created ProgressEvent
        """
        event = ProgressEvent(
            status=status,
            task=task,
            detail=detail,
            metadata=metadata,
        )

        self._events.append(event)

        # Log the event
        logger.log(self.log_level, f"[{status.value}] {task}: {detail}")

        # Call callback if provided
        if self.callback:
            self.callback(event)

        return event

    def starting(self, task: str, detail: str = "", **metadata) -> ProgressEvent:
        """Report task starting."""
        return self.report(ProgressStatus.STARTING, task, detail, **metadata)

    def pending(self, task: str, detail: str = "", **metadata) -> ProgressEvent:
        """Report task pending."""
        return self.report(ProgressStatus.PENDING, task, detail, **metadata)

    def running(self, task: str, detail: str = "", **metadata) -> ProgressEvent:
        """Report task running."""
        return self.report(ProgressStatus.RUNNING, task, detail, **metadata)

    def completed(self, task: str, detail: str = "", **metadata) -> ProgressEvent:
        """Report task completed."""
        return self.report(ProgressStatus.COMPLETED, task, detail, **metadata)

    def failed(self, task: str, detail: str = "", **metadata) -> ProgressEvent:
        """Report task failed."""
        return self.report(ProgressStatus.FAILED, task, detail, **metadata)

    def retrying(self, task: str, detail: str = "", **metadata) -> ProgressEvent:
        """Report task retrying."""
        return self.report(ProgressStatus.RETRYING, task, detail, **metadata)

    def get_history(self) -> List[ProgressEvent]:
        """Get all progress events.

        Returns:
            Copy of the event history list
        """
        return self._events.copy()

    def get_summary(self) -> Dict[str, Any]:
        """Get execution summary.

        Returns:
            Dictionary with total events, completed count, failed count,
            and success rate
        """
        completed = sum(1 for e in self._events if e.status == ProgressStatus.COMPLETED)
        failed = sum(1 for e in self._events if e.status == ProgressStatus.FAILED)

        return {
            "total_events": len(self._events),
            "completed": completed,
            "failed": failed,
            "success_rate": (
                completed / (completed + failed) if (completed + failed) > 0 else 0
            ),
        }

    def clear_history(self) -> None:
        """Clear the event history."""
        self._events.clear()


def simple_progress_callback(event: ProgressEvent) -> None:
    """Simple callback that prints to stdout.

    This is a convenience callback for quick debugging or CLI output.

    Args:
        event: The progress event to display

    Example:
        ```python
        from gsd_rlm.execution.progress import (
            ProgressReporter, simple_progress_callback
        )

        reporter = ProgressReporter(callback=simple_progress_callback)
        reporter.starting("task-1", "Working...")
        # Output: [2024-01-15T10:30:00] starting: task-1 - Working...
        ```
    """
    print(f"[{event.timestamp}] {event.status.value}: {event.task} - {event.detail}")
