from __future__ import annotations

from app.models.schemas import (
    WorkflowReviewEscalationTargetItem,
    WorkflowReviewFindingRequest,
    WorkflowReviewPolicyCheckResult,
    WorkflowReviewPolicyViolationItem,
    WorkflowReviewStartRequest,
)


class FindingPolicyMixin:
    """Finding-level guardrails, risk scores, and escalation logic."""

    def _evaluate_finding_policy(
        self,
        request: WorkflowReviewStartRequest,
        finding: WorkflowReviewFindingRequest,
    ) -> WorkflowReviewPolicyCheckResult:
        """Evaluate one finding for auto-assignment / auto-close safety."""
        violations: list[WorkflowReviewPolicyViolationItem] = []
        warnings: list[str] = []
        escalation_targets: list[WorkflowReviewEscalationTargetItem] = []
        applied_rules = [
            "finding_requires_responsible_department",
            "blocking_finding_requires_owner",
            "critical_finance_legal_findings_escalate",
            "high_risk_findings_require_manual_review",
            "conflicting_finding_metadata_triggers_circuit_breaker",
        ]

        if not finding.responsible_department_code:
            violations.append(
                WorkflowReviewPolicyViolationItem(
                    code="FINDING_NO_DEPARTMENT",
                    message="Finding chưa có responsible_department_code.",
                    severity="high",
                    field_name="responsible_department_code",
                    metadata={"finding_code": finding.finding_code},
                )
            )

        owner_employee_code = None
        if finding.assignment and finding.assignment.assigned_employee_code:
            owner_employee_code = finding.assignment.assigned_employee_code
        else:
            for action in finding.employee_actions:
                if action.employee_code:
                    owner_employee_code = action.employee_code
                    break

        if finding.is_blocking and not owner_employee_code:
            violations.append(
                WorkflowReviewPolicyViolationItem(
                    code="BLOCKING_FINDING_NO_OWNER",
                    message="Finding blocking phải có assigned_employee_code hoặc employee_actions có owner rõ ràng.",
                    severity="critical",
                    field_name="assignment.assigned_employee_code",
                    metadata={"finding_code": finding.finding_code},
                )
            )

        finding_flags = (
            finding.metadata.get("flags", {})
            if isinstance(finding.metadata.get("flags"), dict)
            else {}
        )
        if finding_flags.get("data_conflict") or finding_flags.get(
            "critical_data_missing"
        ):
            violations.append(
                WorkflowReviewPolicyViolationItem(
                    code="FINDING_DATA_CONFLICT",
                    message="Finding có metadata mâu thuẫn hoặc thiếu dữ liệu nghiêm trọng.",
                    severity="critical",
                    field_name="metadata.flags",
                    metadata={"finding_code": finding.finding_code},
                )
            )

        if finding.severity.lower() in {"high", "critical"}:
            warnings.append("Finding có severity cao, cần theo dõi escalation.")

        if finding.responsible_department_code in {"finance", "legal", "contracts"}:
            escalation_agent_map = {
                "finance": "nam",
                "legal": "thao",
                "contracts": "thao",
            }
            escalation_agent = escalation_agent_map[finding.responsible_department_code]
            escalation_targets.append(
                WorkflowReviewEscalationTargetItem(
                    agent_code=escalation_agent,
                    reason=f"Finding {finding.finding_code} thuộc nhóm {finding.responsible_department_code} cần escalation chuyên trách.",
                    priority="high" if finding.is_blocking else "medium",
                    metadata={
                        "finding_code": finding.finding_code,
                        "department_code": finding.responsible_department_code,
                    },
                )
            )

        risk_score = 0
        if violations:
            risk_score += 85
        if finding.is_blocking:
            risk_score += 20
        if finding.severity.lower() == "critical":
            risk_score += 10
        elif finding.severity.lower() == "high":
            risk_score += 5

        risk_level = "low"
        if risk_score >= 80:
            risk_level = "high"
        elif risk_score >= 20:
            risk_level = "medium"

        requires_manual_review = (
            risk_score >= 60 or finding.severity.lower() == "critical"
        )
        circuit_breaker_triggered = any(
            item.code == "FINDING_DATA_CONFLICT" for item in violations
        )

        return WorkflowReviewPolicyCheckResult(
            scope=f"finding:{finding.finding_code}",
            allowed=not violations,
            risk_level=risk_level,
            risk_score=risk_score,
            requires_escalation=bool(escalation_targets or violations),
            requires_manual_review=requires_manual_review,
            circuit_breaker_triggered=circuit_breaker_triggered,
            violations=violations,
            warnings=warnings,
            escalation_targets=escalation_targets,
            applied_rules=applied_rules,
            metadata={
                "project_code": request.project_code,
                "finding_code": finding.finding_code,
                "department_code": finding.responsible_department_code,
                "owner_employee_code": owner_employee_code,
                "flags": finding_flags,
            },
        )
