from __future__ import annotations

"""Follow-up deduplication, normalization and matching utilities."""

from typing import Any


class FollowUpNormalizerMixin:
    """Follow-up deduplication, normalization and matching mixin."""

    def _deduplicate_follow_up_items(
        items: list[dict[str, Any]],
    ) -> list[dict[str, Any]]:
        """Return follow-up items with stable de-duplication by identifiers/content."""
        deduped: list[dict[str, Any]] = []
        seen: set[str] = set()

        for item in items:
            identity = "|".join(
                [
                    str(item.get("action_id") or ""),
                    str(item.get("reference_id") or ""),
                    str(item.get("title") or ""),
                    str(item.get("action_type") or ""),
                    str(item.get("trigger_phase") or ""),
                ]
            )
            if identity in seen:
                continue
            seen.add(identity)
            deduped.append(item)

        return deduped

    def _normalize_follow_up_item(
        item: dict[str, Any],
        *,
        review_id: str,
        finding_id: str,
        finding_code: str,
        default_trigger_phase: str,
    ) -> dict[str, Any]:
        """Normalize a generic follow-up payload into a stable internal shape."""
        title = (
            item.get("title")
            or item.get("action")
            or item.get("next_action")
            or item.get("name")
        )
        reference_id = str(item.get("reference_id") or item.get("action_id") or "")
        return {
            "action_id": item.get("action_id"),
            "action_code": item.get("action_code") or reference_id or None,
            "reference_id": reference_id
            or f"{review_id}:{finding_id or finding_code}:{default_trigger_phase}",
            "title": str(title or "Follow-up action"),
            "description": item.get("description") or item.get("note"),
            "reason": item.get("reason") or item.get("summary"),
            "priority": item.get("priority") or "medium",
            "status": item.get("status") or "pending",
            "due_date": item.get("due_date"),
            "department_code": item.get("department_code")
            or item.get("owner_department_code"),
            "owner_employee_code": item.get("owner_employee_code")
            or item.get("employee_code"),
            "action_type": item.get("action_type") or "follow_up",
            "expected_outcome": item.get("expected_outcome"),
            "success_criteria": item.get("success_criteria"),
            "requires_human_confirmation": item.get("requires_human_confirmation"),
            "completion_note": item.get("completion_note"),
            "completed_at": item.get("completed_at"),
            "created_at": item.get("created_at"),
            "trigger_phase": item.get("trigger_phase") or default_trigger_phase,
            "source": item.get("source") or "workflow_metadata",
            "source_type": item.get("source_type"),
            "blocking": item.get("blocking"),
            "is_blocking": item.get("is_blocking"),
            "metadata": OperationsCaseManagementService._ensure_dict(
                item.get("metadata")
            ),
        }

    def _coerce_follow_up_items(value: Any) -> list[dict[str, Any]]:
        """Coerce raw follow-up metadata into a list of dictionaries."""
        if isinstance(value, dict):
            return [value]
        if isinstance(value, list):
            return [item for item in value if isinstance(item, dict)]
        if isinstance(value, str) and value.strip():
            return [{"title": value.strip()}]
        return []

    def _action_matches_finding(
        *, action_payload: dict[str, Any], finding: dict[str, Any]
    ) -> bool:
        """Return True when an action payload references the provided finding or is generic."""
        payload_finding_id = str(action_payload.get("finding_id") or "")
        payload_finding_code = str(action_payload.get("finding_code") or "")
        finding_id = str(finding.get("finding_id") or "")
        finding_code = str(finding.get("finding_code") or "")

        if payload_finding_id and payload_finding_id != finding_id:
            return False
        if payload_finding_code and payload_finding_code != finding_code:
            return False
        return True
