from __future__ import annotations

"""Follow-up action item collection from review sessions."""

from typing import Any

from .follow_up_normalizer import FollowUpNormalizerMixin


class FollowUpCollectorMixin(FollowUpNormalizerMixin):
    """Follow-up action collection mixin."""

    def _collect_follow_up_actions(
        self,
        *,
        session: dict[str, Any],
        finding: dict[str, Any],
        metadata_keys: tuple[str, ...],
        action_types: set[str],
        default_trigger_phase: str,
    ) -> list[dict[str, Any]]:
        """Extract structured follow-up actions from metadata blobs and audit actions."""
        items: list[dict[str, Any]] = []
        review_id = str(session.get("review_id") or "")
        finding_id = str(finding.get("finding_id") or "")
        finding_code = str(finding.get("finding_code") or "")

        metadata_sources = [
            self._ensure_dict(session.get("metadata")),
            self._ensure_dict(finding.get("metadata")),
        ]

        for assignment in self._ensure_list(finding.get("assignments")):
            metadata_sources.append(self._ensure_dict(assignment.get("metadata")))
            for submission in self._ensure_list(assignment.get("submissions")):
                metadata_sources.append(self._ensure_dict(submission.get("metadata")))
                metadata_sources.append(
                    self._ensure_dict(submission.get("submitted_payload"))
                )

        for source in metadata_sources:
            for key in metadata_keys:
                for raw_item in self._coerce_follow_up_items(source.get(key)):
                    items.append(
                        self._normalize_follow_up_item(
                            raw_item,
                            review_id=review_id,
                            finding_id=finding_id,
                            finding_code=finding_code,
                            default_trigger_phase=default_trigger_phase,
                        )
                    )

        for action in self._ensure_list(session.get("actions")):
            action_type = str(action.get("action_type") or "").strip()
            if action_type not in action_types:
                continue

            action_payload = self._ensure_dict(action.get("action_payload"))
            if not self._action_matches_finding(
                action_payload=action_payload, finding=finding
            ):
                continue

            for key in metadata_keys:
                for raw_item in self._coerce_follow_up_items(action_payload.get(key)):
                    items.append(
                        self._normalize_follow_up_item(
                            self._merge_metadata(
                                raw_item,
                                {
                                    "action_id": action.get("action_id"),
                                    "created_at": action.get("created_at"),
                                },
                            ),
                            review_id=review_id,
                            finding_id=finding_id,
                            finding_code=finding_code,
                            default_trigger_phase=default_trigger_phase,
                        )
                    )

            explicit_item = self._build_follow_up_from_action_payload(
                action_payload=action_payload,
                action=action,
                review_id=review_id,
                finding_id=finding_id,
                finding_code=finding_code,
                default_trigger_phase=default_trigger_phase,
            )
            if explicit_item:
                items.append(explicit_item)

        return self._deduplicate_follow_up_items(items)

    def _build_follow_up_from_action_payload(
        self,
        *,
        action_payload: dict[str, Any],
        action: dict[str, Any],
        review_id: str,
        finding_id: str,
        finding_code: str,
        default_trigger_phase: str,
    ) -> dict[str, Any] | None:
        """Build a follow-up item from a directly structured action payload when present."""
        if not any(
            action_payload.get(key) is not None
            for key in (
                "follow_up_action",
                "next_action",
                "post_action",
                "title",
                "reason",
            )
        ):
            return None

        if action_payload.get("follow_up_action") is not None:
            candidate = action_payload.get("follow_up_action")
        elif action_payload.get("next_action") is not None:
            candidate = {"title": action_payload.get("next_action")}
        elif action_payload.get("post_action") is not None:
            candidate = {"title": action_payload.get("post_action")}
        else:
            candidate = {
                "title": action_payload.get("title") or action.get("action_summary"),
                "reason": action_payload.get("reason") or action.get("action_summary"),
                "priority": action_payload.get("priority"),
                "status": action_payload.get("status"),
                "due_date": action_payload.get("due_date"),
                "department_code": action_payload.get("target_department_code"),
                "owner_employee_code": action_payload.get("target_employee_code"),
            }

        if not isinstance(candidate, dict):
            candidate = {"title": str(candidate)}

        return self._normalize_follow_up_item(
            self._merge_metadata(
                candidate,
                {
                    "action_id": action.get("action_id"),
                    "created_at": action.get("created_at"),
                },
            ),
            review_id=review_id,
            finding_id=finding_id,
            finding_code=finding_code,
            default_trigger_phase=default_trigger_phase,
        )
