"""Task command handler — business logic for task/ticket write operations.

Delegates to TicketManager for persistence and emits domain events
to the EventStore for SSE streaming and audit trail.
"""

from __future__ import annotations

from typing import Any

import structlog

from proxym.domain.commands.task_commands import (
    AssignTaskCommand,
    CompleteTaskCommand,
    CreateTaskCommand,
)
from proxym.domain.events import (
    EventStore,
    TaskAssigned,
    TaskCompleted,
    TaskCreated,
    TaskFailed,
)

logger = structlog.get_logger()


class TaskCommandHandler:
    """Handles task commands — the single write-side handler for tasks.

    Each command creates/mutates a ticket via TicketManager, then
    emits a domain event to the EventStore.
    """

    def __init__(self, ticket_manager, event_store: EventStore) -> None:
        self._tickets = ticket_manager
        self._event_store = event_store

    async def handle(self, cmd) -> dict[str, Any]:
        if isinstance(cmd, CreateTaskCommand):
            return await self._handle_create(cmd)
        if isinstance(cmd, AssignTaskCommand):
            return await self._handle_assign(cmd)
        if isinstance(cmd, CompleteTaskCommand):
            return await self._handle_complete(cmd)
        raise ValueError(f"Unknown command: {type(cmd).__name__}")

    async def _handle_create(self, cmd: CreateTaskCommand) -> dict[str, Any]:
        """Create a ticket and emit TaskCreated event."""
        from proxym.dashboard.tickets import (
            Ticket,
            TicketPriority,
            TicketType,
        )

        ticket = Ticket(
            task=cmd.task,
            project_id=cmd.project_id,
            priority=TicketPriority(cmd.priority),
            type=TicketType(cmd.ticket_type),
        )
        created = self._tickets.create_ticket(ticket)
        result = created.summary()

        self._event_store.append(TaskCreated(
            aggregate_id=created.id,
            actor=cmd.actor,
            data={"task": cmd.task, "project_id": cmd.project_id, "priority": cmd.priority},
        ))

        return result

    async def _handle_assign(self, cmd: AssignTaskCommand) -> dict[str, Any]:
        """Assign a tool to a ticket and emit TaskAssigned event."""
        from proxym.dashboard.tickets import ToolAssignment

        assignment = ToolAssignment(tool=cmd.tool)
        success = self._tickets.assign_tool(cmd.ticket_id, assignment)
        if not success:
            raise ValueError(f"Ticket '{cmd.ticket_id}' not found")

        ticket = self._tickets.get_ticket(cmd.ticket_id)
        result = ticket.summary() if ticket else {"id": cmd.ticket_id}

        self._event_store.append(TaskAssigned(
            aggregate_id=cmd.ticket_id,
            actor=cmd.actor,
            data={"tool": cmd.tool, "assignee_type": cmd.assignee_type},
        ))

        return result

    async def _handle_complete(self, cmd: CompleteTaskCommand) -> dict[str, Any]:
        """Mark a ticket as completed and emit TaskCompleted/TaskFailed event."""
        success = cmd.exit_code == 0
        status = "done" if success else "failed"
        ticket = self._tickets.update_ticket(cmd.ticket_id, {"status": status})

        if not ticket:
            raise ValueError(f"Ticket '{cmd.ticket_id}' not found")

        result = ticket.summary()

        event_cls = TaskCompleted if success else TaskFailed
        self._event_store.append(event_cls(
            aggregate_id=cmd.ticket_id,
            actor=cmd.actor,
            data={
                "result": cmd.result[:500] if cmd.result else "",
                "exit_code": cmd.exit_code,
                "status": status,
            },
        ))

        return result
