from __future__ import annotations

from typing import Any

from app.models.schemas import (
    CompanyOperationalBlockedItem,
)

from .helpers import (
    ensure_dict,
    ensure_list,
    extract_string_list,
    is_blocking_review_follow_up,
    is_high_severity,
    is_open_status,
)


def build_blocked_items(
    service: Any,
    *,
    projects: list[Any],
    dossier_reviews: list[dict[str, Any]],
    operations_blockers: list[CompanyOperationalBlockedItem],
) -> list[CompanyOperationalBlockedItem]:
    """Tạo blocked items tổng."""
    items: list[CompanyOperationalBlockedItem] = []
    for project in projects:
        for risk in project.risks:
            if is_high_severity(risk.severity) and is_open_status(risk.status):
                items.append(
                    CompanyOperationalBlockedItem(
                        project_code=project.project_code,
                        project_name=project.project_name,
                        title=risk.title,
                        status=risk.status,
                        owner=risk.owner,
                        reason=risk.mitigation,
                        source_type="project_risk",
                        reference_id=None,
                        due_date=None,
                        metadata={
                            "severity": risk.severity,
                            "current_phase": project.current_phase,
                        },
                    )
                )
    for review in dossier_reviews:
        items.extend(service._build_blocked_items_from_review(review))
    for blocker in operations_blockers:
        if is_open_status(blocker.status):
            items.append(blocker)
    return items


def build_blocked_items_from_review(
    service: Any, review: dict[str, Any]
) -> list[CompanyOperationalBlockedItem]:
    """Tạo blocked items từ review."""
    items: list[CompanyOperationalBlockedItem] = []
    project_code = str(review.get("project_code") or "") or None
    project_name = str(review.get("project_name") or "") or None
    review_id = str(review.get("review_id") or "") or None
    for finding in ensure_list(review.get("findings")):
        metadata = ensure_dict(finding.get("metadata"))
        assignments = ensure_list(finding.get("assignments"))
        primary_assignment = assignments[0] if assignments else {}
        blocker_reasons = extract_string_list(
            metadata.get("blocked_reasons")
        ) + extract_string_list(metadata.get("blocking_reasons"))
        needs_blocker = (
            bool(finding.get("is_blocking"))
            or is_open_status(finding.get("status"))
            and bool(blocker_reasons)
        )
        if not needs_blocker:
            continue
        items.append(
            CompanyOperationalBlockedItem(
                project_code=project_code,
                project_name=project_name,
                review_session_id=review_id,
                finding_code=str(finding.get("finding_code") or "") or None,
                employee_code=primary_assignment.get("assigned_employee_code"),
                department_code=finding.get("responsible_department_code")
                or primary_assignment.get("assigned_department_code"),
                title=str(finding.get("title") or "Blocking dossier finding"),
                status=str(finding.get("status") or "open"),
                owner=primary_assignment.get("assigned_employee_name")
                or primary_assignment.get("assigned_employee_code"),
                reason="; ".join(blocker_reasons)
                or finding.get("description")
                or finding.get("resolution_note"),
                source_type="dossier_review_finding",
                reference_id=str(finding.get("finding_id") or "") or None,
                due_date=primary_assignment.get("due_date") or finding.get("due_date"),
                metadata={
                    "supplement_status": finding.get("supplement_status"),
                    "severity": finding.get("severity"),
                    "impact_level": finding.get("impact_level"),
                    "blocker_reasons": blocker_reasons,
                },
            )
        )
        for index, follow_up in enumerate(
            service._collect_review_follow_ups(review=review, finding=finding), start=1
        ):
            if not is_blocking_review_follow_up(follow_up):
                continue
            items.append(
                CompanyOperationalBlockedItem(
                    project_code=project_code,
                    project_name=project_name,
                    review_session_id=review_id,
                    finding_code=str(finding.get("finding_code") or "") or None,
                    employee_code=str(follow_up.get("owner_employee_code") or "")
                    or None,
                    department_code=follow_up.get("department_code")
                    or finding.get("responsible_department_code"),
                    title=str(
                        follow_up.get("title")
                        or f"Blocking follow-up: {finding.get('title') or 'Dossier finding'}"
                    ),
                    status=str(follow_up.get("status") or "pending"),
                    owner=follow_up.get("owner_employee_code")
                    or follow_up.get("department_code"),
                    reason=follow_up.get("reason") or follow_up.get("description"),
                    source_type=str(
                        follow_up.get("source_type") or "dossier_review_follow_up"
                    ),
                    reference_id=str(
                        follow_up.get("reference_id") or f"{review_id}:{index}"
                    )
                    or None,
                    due_date=follow_up.get("due_date"),
                    metadata={
                        "finding_id": finding.get("finding_id"),
                        "finding_status": finding.get("status"),
                        "trigger_phase": follow_up.get("trigger_phase"),
                    },
                )
            )
    return items
