"""Helpdesk workflow action handlers.

This module is auto-discovered by ``WorkflowConfig.ready()`` via
``autodiscover_modules("workflows")``.  It registers:

1. The helpdesk ticket FSM (re-exported from ``helpdesk.workflow``).
2. Named workflow *action handlers* used by ``ProcessDefinition`` rules.

Action handler naming convention: ``helpdesk.<verb>``
These names appear in ``ProcessDefinition.actions[*].name`` in the DB and
in ``.seed/`` JSON files.

Available actions
-----------------
helpdesk_assign_to_user      — set ticket.assigned_to_id from params["user_id"]
helpdesk_set_priority        — set ticket.priority from params["priority"]
helpdesk_add_tag             — add a tag (by name) to ticket from params["tag"]
helpdesk_remove_tag          — remove a tag (by name) from ticket params["tag"]
helpdesk_change_status       — transition ticket status via TicketService
helpdesk_send_notification   — dispatch a notification event (future)
"""

from __future__ import annotations

import structlog

from simorgh.apps.workflow.registry import ActionContext, register_action

# ---------------------------------------------------------------------------
# Re-register the ticket FSM (already loaded in apps.py, but workflows.py
# autodiscovery also needs it idempotently).
# ---------------------------------------------------------------------------
from simorgh.apps.helpdesk import workflow as _ticket_workflow  # noqa: F401

_log = structlog.get_logger("simorgh.helpdesk.workflows")


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

def _get_ticket(ctx: ActionContext):
    """Resolve the subject as a helpdesk Ticket (or None)."""
    subject = getattr(getattr(ctx, "instance", None), "subject", None)
    if subject is None:
        # Fall back to payload["ticket_id"]
        ticket_id = ctx.payload.get("ticket_id")
        if ticket_id:
            from simorgh.apps.helpdesk.models import Ticket
            try:
                return Ticket.objects.get(pk=ticket_id)
            except Ticket.DoesNotExist:
                return None
    return subject


# ---------------------------------------------------------------------------
# Action: assign_to_user
# ---------------------------------------------------------------------------

@register_action("helpdesk_assign_to_user")
def action_assign_to_user(ctx: ActionContext) -> None:
    """Assign ticket to a specific user.

    params:
        user_id (int): PK of the user to assign.
    """
    ticket = _get_ticket(ctx)
    if ticket is None:
        _log.warning("helpdesk.assign_to_user: no ticket in context")
        return
    user_id = ctx.payload.get("user_id")
    if not user_id:
        _log.warning("helpdesk.assign_to_user: missing user_id param")
        return
    from simorgh.apps.helpdesk.services import TicketService
    TicketService.assign(ticket, assigned_to_id=int(user_id))


# ---------------------------------------------------------------------------
# Action: set_priority
# ---------------------------------------------------------------------------

@register_action("helpdesk_set_priority")
def action_set_priority(ctx: ActionContext) -> None:
    """Set ticket priority.

    params:
        priority (str): One of low / normal / high / urgent / critical.
    """
    ticket = _get_ticket(ctx)
    if ticket is None:
        return
    priority = ctx.payload.get("priority")
    if not priority:
        return
    from simorgh.apps.helpdesk.models import TicketPriority
    if priority not in TicketPriority.values:
        _log.warning("helpdesk.set_priority: invalid priority %r", priority)
        return
    ticket.priority = priority
    ticket.save(update_fields=["priority", "updated_at"])


# ---------------------------------------------------------------------------
# Action: add_tag
# ---------------------------------------------------------------------------

@register_action("helpdesk_add_tag")
def action_add_tag(ctx: ActionContext) -> None:
    """Add a tag (by name) to the ticket.

    params:
        tag (str): Tag name.
    """
    ticket = _get_ticket(ctx)
    if ticket is None:
        return
    tag_name = ctx.payload.get("tag")
    if not tag_name:
        return
    from simorgh.apps.helpdesk.models import Tag, TicketTag
    tag = Tag.objects.filter(
        tenant_id=ticket.tenant_id, name=tag_name, is_active=True
    ).first()
    if tag:
        TicketTag.objects.get_or_create(ticket=ticket, tag=tag)
    else:
        _log.warning("helpdesk.add_tag: tag %r not found for tenant %s", tag_name, ticket.tenant_id)


# ---------------------------------------------------------------------------
# Action: remove_tag
# ---------------------------------------------------------------------------

@register_action("helpdesk_remove_tag")
def action_remove_tag(ctx: ActionContext) -> None:
    """Remove a tag (by name) from the ticket.

    params:
        tag (str): Tag name.
    """
    ticket = _get_ticket(ctx)
    if ticket is None:
        return
    tag_name = ctx.payload.get("tag")
    if not tag_name:
        return
    from simorgh.apps.helpdesk.models import Tag, TicketTag
    tag = Tag.objects.filter(
        tenant_id=ticket.tenant_id, name=tag_name
    ).first()
    if tag:
        TicketTag.objects.filter(ticket=ticket, tag=tag).delete()


# ---------------------------------------------------------------------------
# Action: change_status
# ---------------------------------------------------------------------------

@register_action("helpdesk_change_status")
def action_change_status(ctx: ActionContext) -> None:
    """Transition the ticket to a new status via TicketService.

    params:
        status (str): Target status (new / open / pending / on_hold / solved / closed).
    """
    ticket = _get_ticket(ctx)
    if ticket is None:
        return
    new_status = ctx.payload.get("status")
    if not new_status:
        return
    from simorgh.apps.helpdesk.services import TicketService
    TicketService.transition(ticket, new_status=new_status)


# ---------------------------------------------------------------------------
# Action: send_notification  (stub — wired to the notification service)
# ---------------------------------------------------------------------------

@register_action("helpdesk_send_notification")
def action_send_notification(ctx: ActionContext) -> None:
    """Dispatch a notification event for the ticket.

    params:
        template (str): Notification template key.
        channel  (str): Delivery channel (email / push / sms).
    """
    ticket = _get_ticket(ctx)
    if ticket is None:
        return
    template = ctx.payload.get("template", "helpdesk.ticket.generic")
    channel = ctx.payload.get("channel", "email")
    from simorgh.apps.events.bus import dispatch
    dispatch("helpdesk.notification.requested", {
        "ticket_id": ticket.pk,
        "tenant_id": ticket.tenant_id,
        "template": template,
        "channel": channel,
    })
