from __future__ import annotations

from typing import Any

from app.models.schemas import (
    CompanyOperationalBacklogItem,
)

from .helpers import (
    derive_priority,
    ensure_list,
    is_assignment_open,
    is_open_status,
)


def build_backlog(
    service: Any,
    *,
    projects: list[Any],
    dossier_reviews: list[dict[str, Any]],
    operations_actions: list[Any],
) -> list[CompanyOperationalBacklogItem]:
    """Tạo backlog tổng."""
    items: list[CompanyOperationalBacklogItem] = []
    for project in projects:
        for task in project.upcoming_tasks:
            items.append(
                CompanyOperationalBacklogItem(
                    project_code=project.project_code,
                    project_name=project.project_name,
                    title=task.title,
                    assignee=task.assignee,
                    status=task.status,
                    priority=task.priority,
                    due_date=task.due_date,
                    source_type="project_task",
                    reference_id=None,
                    note=task.note,
                    metadata={
                        "current_phase": project.current_phase,
                        "budget_status": project.budget_status,
                    },
                )
            )
    for review in dossier_reviews:
        items.extend(service._build_backlog_from_review(review))
    for action in operations_actions:
        if is_open_status(action.status):
            items.append(
                CompanyOperationalBacklogItem(
                    project_code=action.project_code,
                    project_name=None,
                    review_session_id=action.review_session_id,
                    finding_code=action.finding_code,
                    employee_code=action.owner_employee_code,
                    department_code=action.owner_department_code,
                    title=action.title,
                    assignee=action.owner_employee_code or action.owner_department_code,
                    status=action.status,
                    priority=action.priority,
                    due_date=action.due_date,
                    source_type=action.action_type,
                    reference_id=action.action_id,
                    note=action.description,
                    metadata={
                        "case_id": action.case_id,
                        "review_session_id": action.review_session_id,
                        "finding_code": action.finding_code,
                        "requires_human_confirmation": action.requires_human_confirmation,
                    },
                )
            )
    return items


def build_backlog_from_review(
    service: Any, review: dict[str, Any]
) -> list[CompanyOperationalBacklogItem]:
    """Tạo backlog từ review."""
    items: list[CompanyOperationalBacklogItem] = []
    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")):
        finding_status = str(finding.get("status") or "")
        assignments = ensure_list(finding.get("assignments"))
        if is_open_status(finding_status) and not assignments:
            items.append(
                CompanyOperationalBacklogItem(
                    project_code=project_code,
                    project_name=project_name,
                    review_session_id=review_id,
                    finding_code=str(finding.get("finding_code") or "") or None,
                    department_code=finding.get("responsible_department_code"),
                    title=f"Phân công xử lý: {finding.get('title') or 'Dossier finding'}",
                    assignee=finding.get("responsible_department_code"),
                    status="pending",
                    priority=derive_priority(
                        finding.get("severity"),
                        finding.get("impact_level"),
                        finding.get("is_blocking"),
                    ),
                    due_date=finding.get("due_date"),
                    source_type="dossier_review_triage",
                    reference_id=str(finding.get("finding_id") or "") or None,
                    note=finding.get("description"),
                    metadata={
                        "finding_status": finding.get("status"),
                        "supplement_status": finding.get("supplement_status"),
                    },
                )
            )
        for assignment in assignments:
            if is_assignment_open(assignment.get("status")):
                items.append(
                    CompanyOperationalBacklogItem(
                        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=assignment.get("assigned_employee_code"),
                        department_code=assignment.get("assigned_department_code"),
                        title=str(finding.get("title") or "Theo dõi bổ sung hồ sơ"),
                        assignee=assignment.get("assigned_employee_code")
                        or assignment.get("assigned_department_code"),
                        status=str(assignment.get("status") or "pending"),
                        priority=str(
                            assignment.get("priority")
                            or derive_priority(
                                finding.get("severity"),
                                finding.get("impact_level"),
                                finding.get("is_blocking"),
                            )
                        ),
                        due_date=assignment.get("due_date") or finding.get("due_date"),
                        source_type="dossier_review_assignment",
                        reference_id=str(
                            assignment.get("assignment_id")
                            or finding.get("finding_id")
                            or ""
                        )
                        or None,
                        note=assignment.get("assignment_note")
                        or finding.get("description"),
                        metadata={
                            "finding_id": finding.get("finding_id"),
                            "finding_status": finding.get("status"),
                            "supplement_status": finding.get("supplement_status"),
                        },
                    )
                )
        for index, follow_up in enumerate(
            service._collect_review_follow_ups(review=review, finding=finding), start=1
        ):
            if not is_open_status(follow_up.get("status")):
                continue
            items.append(
                CompanyOperationalBacklogItem(
                    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 "Follow-up action"),
                    assignee=follow_up.get("owner_employee_code")
                    or follow_up.get("department_code"),
                    status=str(follow_up.get("status") or "pending"),
                    priority=str(follow_up.get("priority") or "medium"),
                    due_date=follow_up.get("due_date"),
                    source_type=str(
                        follow_up.get("action_type") or "dossier_review_follow_up"
                    ),
                    reference_id=str(
                        follow_up.get("reference_id") or f"{review_id}:{index}"
                    )
                    or None,
                    note=follow_up.get("description") or follow_up.get("reason"),
                    metadata={
                        "finding_id": finding.get("finding_id"),
                        "finding_status": finding.get("status"),
                        "trigger_phase": follow_up.get("trigger_phase"),
                    },
                )
            )
    return items
