"""WorkItem API views.

Endpoints
---------
GET    /workitems/                        list all work items (filterable)
GET    /workitems/my/                     my work — items needing action
GET    /workitems/{public_id}/            work item detail with timeline
POST   /workitems/                        create a canonical WorkItem
POST   /workitems/{public_id}/complete/   complete a WorkItem
POST   /workitems/{public_id}/cancel/     cancel a WorkItem
POST   /workitems/{public_id}/reassign/   reassign a WorkItem
GET    /workitems/pending-approvals/      pending approvals (compat)
GET    /workitems/delegated/              delegated items (compat)
GET    /workitems/overdue/                overdue items (compat)
GET    /workitems/completed/              completed items (compat)
GET    /workitems/dashboard/              dashboard widget counts
POST   /workitems/refresh/               refresh workbox for current user (compat)
"""

from __future__ import annotations

from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.response import Response

from simorgh.apps.workbox import services
from simorgh.apps.workbox.api.serializers import (
    WorkboxDashboardSerializer,
    WorkboxRefreshSerializer,
    WorkItemCancelSerializer,
    WorkItemCompleteSerializer,
    WorkItemCreateSerializer,
    WorkItemDetailSerializer,
    WorkItemReassignSerializer,
    WorkItemSerializer,
)
from simorgh.apps.workbox.models import WorkboxItem as WorkItem
from simorgh.apps.workbox.models import WorkboxItemStatus
from simorgh.apps.workbox.services import WorkItemService


def _get_tenant_id(request: Request) -> int | None:
    tenant = getattr(request, "tenant", None)
    return tenant.pk if tenant else None


def _get_org_node_id(request: Request) -> int | None:
    tenant = getattr(request, "tenant", None)
    if tenant is None:
        return None
    try:
        from simorgh.apps.organizations.models import OrganizationNode
        node = OrganizationNode.objects.filter(tenant=tenant).order_by("lft").first()
        return node.pk if node else None
    except Exception:
        return None


def _get_user_id(request: Request) -> int:
    return request.user.pk


def _get_base_queryset(request: Request):
    tenant_id = _get_tenant_id(request)
    user_id = _get_user_id(request)
    if tenant_id is None:
        return WorkItem.objects.none()
    return WorkItem.objects.filter(
        tenant_id=tenant_id,
        assigned_to_user_id=user_id,
    )


# ── WorkItem CRUD ──────────────────────────────────────────────────────────

@api_view(["GET"])
@permission_classes([IsAuthenticated])
def workitem_list(request: Request) -> Response:
    """GET /workitems/ — list all work items with optional filters."""
    qs = _get_base_queryset(request)

    item_type = request.query_params.get("item_type")
    if item_type:
        qs = qs.filter(item_type=item_type)

    status_filter = request.query_params.get("status")
    if status_filter:
        qs = qs.filter(status=status_filter)

    priority = request.query_params.get("priority")
    if priority:
        qs = qs.filter(priority=priority)

    source_type = request.query_params.get("source_type")
    if source_type:
        qs = qs.filter(source_type=source_type)

    search = request.query_params.get("search")
    if search:
        from django.db.models import Q
        qs = qs.filter(
            Q(title__icontains=search)
            | Q(summary__icontains=search)
            | Q(description__icontains=search)
        )

    qs = qs.order_by("-created_at")
    items = qs[:200]
    serializer = WorkItemSerializer(items, many=True)
    return Response(serializer.data)


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def workitem_my(request: Request) -> Response:
    """GET /workitems/my/ — items needing action."""
    qs = _get_base_queryset(request).filter(
        status__in=(WorkboxItemStatus.PENDING, WorkboxItemStatus.IN_PROGRESS, WorkboxItemStatus.OVERDUE),
    ).order_by("due_date", "-created_at")

    items = qs[:200]
    serializer = WorkItemSerializer(items, many=True)
    return Response(serializer.data)


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def workitem_detail(request: Request, public_id: str) -> Response:
    """GET /workitems/{public_id}/ — detail with timeline."""
    tenant_id = _get_tenant_id(request)
    if tenant_id is None:
        return Response({"error": "Tenant required"}, status=status.HTTP_400_BAD_REQUEST)

    try:
        work_item = WorkItem.objects.get(tenant_id=tenant_id, public_id=public_id)
    except WorkItem.DoesNotExist:
        return Response({"error": "Not found"}, status=status.HTTP_404_NOT_FOUND)

    serializer = WorkItemDetailSerializer(work_item)
    return Response(serializer.data)


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def workitem_create(request: Request) -> Response:
    """POST /workitems/ — create a canonical WorkItem."""
    tenant_id = _get_tenant_id(request)
    org_node_id = _get_org_node_id(request)
    if tenant_id is None or org_node_id is None:
        return Response(
            {"error": "Tenant and organization node required"},
            status=status.HTTP_400_BAD_REQUEST,
        )

    serializer = WorkItemCreateSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    data = serializer.validated_data

    work_item = WorkItemService.create_work_item(
        tenant_id=tenant_id,
        organization_node_id=org_node_id,
        item_type=data["item_type"],
        title=data["title"],
        summary=data.get("summary", ""),
        description=data.get("description", ""),
        priority=data.get("priority", "medium"),
        assigned_to_user_id=data.get("assigned_to_user_id"),
        assigned_to_role_id=data.get("assigned_to_role_id"),
        assigned_to_unit_id=data.get("assigned_to_unit_id"),
        source_type=data.get("source_type", ""),
        source_entity=data.get("source_entity", ""),
        source_id=data.get("source_id", ""),
        source_url=data.get("source_url", ""),
        due_date=data.get("due_date"),
        is_delegated=data.get("is_delegated", False),
        metadata=data.get("metadata", {}),
    )

    response_serializer = WorkItemDetailSerializer(work_item)
    return Response(response_serializer.data, status=status.HTTP_201_CREATED)


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def workitem_complete(request: Request, public_id: str) -> Response:
    """POST /workitems/{public_id}/complete/ — complete a WorkItem."""
    tenant_id = _get_tenant_id(request)
    if tenant_id is None:
        return Response({"error": "Tenant required"}, status=status.HTTP_400_BAD_REQUEST)

    try:
        work_item = WorkItem.objects.get(tenant_id=tenant_id, public_id=public_id)
    except WorkItem.DoesNotExist:
        return Response({"error": "Not found"}, status=status.HTTP_404_NOT_FOUND)

    serializer = WorkItemCompleteSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)

    try:
        work_item = WorkItemService.complete_work_item(
            work_item,
            actor_id=_get_user_id(request),
            note=serializer.validated_data.get("note", ""),
        )
    except ValueError as e:
        return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

    response_serializer = WorkItemDetailSerializer(work_item)
    return Response(response_serializer.data)


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def workitem_cancel(request: Request, public_id: str) -> Response:
    """POST /workitems/{public_id}/cancel/ — cancel a WorkItem."""
    tenant_id = _get_tenant_id(request)
    if tenant_id is None:
        return Response({"error": "Tenant required"}, status=status.HTTP_400_BAD_REQUEST)

    try:
        work_item = WorkItem.objects.get(tenant_id=tenant_id, public_id=public_id)
    except WorkItem.DoesNotExist:
        return Response({"error": "Not found"}, status=status.HTTP_404_NOT_FOUND)

    serializer = WorkItemCancelSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)

    try:
        work_item = WorkItemService.cancel_work_item(
            work_item,
            actor_id=_get_user_id(request),
            note=serializer.validated_data.get("note", ""),
        )
    except ValueError as e:
        return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

    response_serializer = WorkItemDetailSerializer(work_item)
    return Response(response_serializer.data)


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def workitem_reassign(request: Request, public_id: str) -> Response:
    """POST /workitems/{public_id}/reassign/ — reassign a WorkItem."""
    tenant_id = _get_tenant_id(request)
    if tenant_id is None:
        return Response({"error": "Tenant required"}, status=status.HTTP_400_BAD_REQUEST)

    try:
        work_item = WorkItem.objects.get(tenant_id=tenant_id, public_id=public_id)
    except WorkItem.DoesNotExist:
        return Response({"error": "Not found"}, status=status.HTTP_404_NOT_FOUND)

    serializer = WorkItemReassignSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    data = serializer.validated_data

    try:
        work_item = WorkItemService.reassign_work_item(
            work_item,
            to_user_id=data.get("to_user_id"),
            to_role_id=data.get("to_role_id"),
            to_unit_id=data.get("to_unit_id"),
            actor_id=_get_user_id(request),
            note=data.get("note", ""),
        )
    except ValueError as e:
        return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

    response_serializer = WorkItemDetailSerializer(work_item)
    return Response(response_serializer.data)


# ── Backward-compatible workbox views ───────────────────────────────────────

@api_view(["GET"])
@permission_classes([IsAuthenticated])
def workbox_list(request: Request) -> Response:
    """List all work items with optional filters (backward compat)."""
    return workitem_list(request)


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def workbox_my_work(request: Request) -> Response:
    """Items needing action (backward compat)."""
    return workitem_my(request)


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def workbox_pending_approvals(request: Request) -> Response:
    """Pending approval items."""
    qs = _get_base_queryset(request).filter(
        item_type="approval",
        status__in=(WorkboxItemStatus.PENDING, WorkboxItemStatus.IN_PROGRESS, WorkboxItemStatus.OVERDUE),
    ).order_by("due_date", "-created_at")

    items = qs[:200]
    serializer = WorkItemSerializer(items, many=True)
    return Response(serializer.data)


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def workbox_delegated(request: Request) -> Response:
    """Delegated items."""
    qs = _get_base_queryset(request).filter(
        is_delegated=True,
        status__in=(WorkboxItemStatus.PENDING, WorkboxItemStatus.IN_PROGRESS, WorkboxItemStatus.OVERDUE),
    ).order_by("due_date", "-created_at")

    items = qs[:200]
    serializer = WorkItemSerializer(items, many=True)
    return Response(serializer.data)


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def workbox_overdue(request: Request) -> Response:
    """Overdue items."""
    qs = _get_base_queryset(request).filter(
        status=WorkboxItemStatus.OVERDUE,
    ).order_by("due_date", "-created_at")

    items = qs[:200]
    serializer = WorkItemSerializer(items, many=True)
    return Response(serializer.data)


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def workbox_completed(request: Request) -> Response:
    """Completed items."""
    qs = _get_base_queryset(request).filter(
        status=WorkboxItemStatus.COMPLETED,
    ).order_by("-completed_at", "-created_at")

    items = qs[:200]
    serializer = WorkItemSerializer(items, many=True)
    return Response(serializer.data)


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def workbox_dashboard(request: Request) -> Response:
    """Dashboard widget counts."""
    tenant_id = _get_tenant_id(request)
    user_id = _get_user_id(request)
    if tenant_id is None:
        return Response({"error": "Tenant required"}, status=status.HTTP_400_BAD_REQUEST)

    counts = services.get_dashboard_counts(tenant_id=tenant_id, user_id=user_id)
    serializer = WorkboxDashboardSerializer(counts)
    return Response(serializer.data)


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def workbox_refresh(request: Request) -> Response:
    """Refresh the workbox for the current user from all source services."""
    tenant_id = _get_tenant_id(request)
    org_node_id = _get_org_node_id(request)
    user_id = _get_user_id(request)

    if tenant_id is None or org_node_id is None:
        return Response(
            {"error": "Tenant and organization node required"},
            status=status.HTTP_400_BAD_REQUEST,
        )

    stats = services.refresh_user_workbox(
        tenant_id=tenant_id,
        organization_node_id=org_node_id,
        user_id=user_id,
    )
    serializer = WorkboxRefreshSerializer({"stats": stats})
    return Response(serializer.data)
