from backend.core.models import DocumentRiskControl
from backend.core.utils import calculate_aggregate_likelihood, calculate_aggregate_weight, map_weight_to_impact_likelihood


def risk_matrix_table():
    impact_labels = [
        "Insignificant (1)",
        "Significant (2)",
        "Severe (3)",
        "Material (4)",
        "Major (5)"
    ]
    header = ["Likelihood ↓ / Impact →"] + impact_labels

    matrix = [
        ["Almost Certain (5)",
            (5, "bg-medium"), (10, "bg-high"), (15, "bg-critical"), (20, "bg-critical"), (25, "bg-critical")
        ],
        ["Likely (4)",
            (4, "bg-low"), (8, "bg-medium"), (12, "bg-high"), (16, "bg-high"), (20, "bg-critical")
        ],
        ["Probable (3)",
            (3, "bg-low"), (6, "bg-low"), (9, "bg-medium"), (12, "bg-high"), (15, "bg-high")
        ],
        ["Unlikely (2)",
            (2, "bg-very-low"), (4, "bg-low"), (6, "bg-medium"), (8, "bg-medium"), (10, "bg-medium")
        ],
        ["Rare (1)",
            (1, "bg-very-low"), (2, "bg-very-low"), (3, "bg-low"), (4, "bg-low"), (5, "bg-medium")
        ],
    ]

    table = [header] + matrix
    return table

def get_risk_table(document):
    risks = (
        DocumentRiskControl.objects
        .filter(document=document)
        .values('risk', 'risk__risk_name')
        .distinct()
    )

    risks_with_controls = []

    for risk_entry in risks:
        risk = {
            'id': risk_entry['risk'],
            'name': risk_entry['risk__risk_name']
        }

        controls = (
            DocumentRiskControl.objects
            .filter(document=document, risk_id=risk['id'])
            .values('control', 'control__name', 'weight', 'likelihood')
            .distinct()
        )
        max_weight = 10*5
        total_weight = calculate_aggregate_weight(controls)
        total_likelihood = calculate_aggregate_likelihood(controls)
        impact, likelihood = map_weight_to_impact_likelihood(total_weight, total_likelihood, max_weight)
        r_impact = round(impact)
        r_likelihood = round(likelihood)
        residua_impact = r_impact - 1 if r_impact > 2 else r_impact
        residual_likelihood = r_likelihood - 1 if r_likelihood > 2 else r_likelihood
        risks_with_controls.append({
            'risk': risk,
            'controls': list(controls),
            'total_weight': total_weight,
            'impact': impact,
            'likelihood': likelihood,
            'r_impact': r_impact,
            'r_likelihood': r_likelihood,
            'risk_score': r_impact * r_likelihood,
            'residual_impact': residua_impact,
            'residual_likelihood': residual_likelihood,
            'residual_risk_score': residua_impact * residual_likelihood,
        })
    risks_with_controls.sort(key=lambda x: x['risk_score'], reverse=True)

    return risks_with_controls

def get_safeguard_summary_table(risks_with_controls):
    from collections import Counter
    from backend.core.models import Control

    safeguard_counter = Counter()
    safeguard_names = {}

    for risk in risks_with_controls:
        for control in risk.get('controls', []):
            control_id = control.get('control')
            control_name = control.get('control__name')
            if control_id:
                safeguard_counter[control_id] += 1
                safeguard_names[control_id] = control_name

    summary = []
    controls = Control.objects.filter(id__in=safeguard_counter.keys())
    controls_map = {c.id: c for c in controls}

    for control_id, count in safeguard_counter.items():
        control = controls_map.get(control_id)
        summary.append({
            'id': control_id,
            'safeguard_id': control.safeguard_id if control else '',
            'name': safeguard_names.get(control_id, ''),
            'description': control.description if control else '',
            'count': count,
        })
    summary.sort(key=lambda x: x['count'], reverse=True)
    return summary