"""SRE maturity assessment analyzer across 8 dimensions."""

from __future__ import annotations

from typing import List, Optional

import yaml

from sre_beacon.models import MaturityDimension, MaturityReport


# ---------------------------------------------------------------------------
# Dimensions
# ---------------------------------------------------------------------------

DIMENSIONS = [
    "slo_adoption",
    "incident_management",
    "monitoring_observability",
    "toil_reduction",
    "blameless_culture",
    "on_call_practices",
    "capacity_planning",
    "change_management",
]


# ---------------------------------------------------------------------------
# Loader
# ---------------------------------------------------------------------------

def load_maturity_assessment(path: str) -> dict:
    """Load maturity assessment answers from a YAML file.

    Expected format::

        assessment:
          slo_adoption:
            has_slos: true
            slo_count: 5
            error_budget_tracking: true
            slo_review_cadence: monthly
          incident_management:
            has_incident_process: true
            has_postmortems: true
            action_item_tracking: true
            severity_definitions: true
            on_call_rotation: true
          ...
    """
    with open(path, "r", encoding="utf-8") as fh:
        data = yaml.safe_load(fh)
    return data.get("assessment", {})


# ---------------------------------------------------------------------------
# Scorer
# ---------------------------------------------------------------------------

def assess_maturity(assessment: dict) -> MaturityReport:
    """Score each dimension and return a maturity report."""
    dimensions: List[MaturityDimension] = []

    dimensions.append(_score_slo_adoption(assessment.get("slo_adoption", {})))
    dimensions.append(_score_incident_management(assessment.get("incident_management", {})))
    dimensions.append(_score_monitoring(assessment.get("monitoring_observability", {})))
    dimensions.append(_score_toil_reduction(assessment.get("toil_reduction", {})))
    dimensions.append(_score_blameless_culture(assessment.get("blameless_culture", {})))
    dimensions.append(_score_on_call(assessment.get("on_call_practices", {})))
    dimensions.append(_score_capacity_planning(assessment.get("capacity_planning", {})))
    dimensions.append(_score_change_management(assessment.get("change_management", {})))

    return MaturityReport(dimensions=dimensions)


def assess_maturity_from_file(path: str) -> MaturityReport:
    """Load assessment YAML and score it."""
    assessment = load_maturity_assessment(path)
    return assess_maturity(assessment)


# ---------------------------------------------------------------------------
# Dimension scorers (0-5 scale)
# ---------------------------------------------------------------------------

def _score_slo_adoption(data: dict) -> MaturityDimension:
    score = 0.0
    findings = []
    recs = []

    if data.get("has_slos"):
        score += 1.0
        findings.append("SLOs are defined")
    else:
        recs.append("Define SLOs for your critical services")

    slo_count = data.get("slo_count", 0)
    if slo_count >= 10:
        score += 1.0
        findings.append(f"{slo_count} SLOs defined (comprehensive)")
    elif slo_count >= 3:
        score += 0.5
        findings.append(f"{slo_count} SLOs defined (partial)")
    else:
        recs.append("Increase SLO coverage to at least 5 services")

    if data.get("error_budget_tracking"):
        score += 1.0
        findings.append("Error budget tracking enabled")
    else:
        recs.append("Implement error budget tracking and alerting")

    cadence = data.get("slo_review_cadence", "")
    if cadence in ("weekly", "biweekly"):
        score += 1.0
        findings.append(f"SLO review cadence: {cadence}")
    elif cadence == "monthly":
        score += 0.5
        findings.append("SLO reviewed monthly")
    else:
        recs.append("Establish a regular SLO review cadence (weekly ideal)")

    if data.get("stakeholder_visibility"):
        score += 1.0
        findings.append("SLOs visible to stakeholders")
    else:
        recs.append("Share SLO dashboards with product/business stakeholders")

    return MaturityDimension(name="SLO Adoption", score=min(5.0, score),
                             findings=findings, recommendations=recs)


def _score_incident_management(data: dict) -> MaturityDimension:
    score = 0.0
    findings = []
    recs = []

    if data.get("has_incident_process"):
        score += 1.0
        findings.append("Incident management process exists")
    else:
        recs.append("Establish a formal incident management process")

    if data.get("has_postmortems"):
        score += 1.0
        findings.append("Post-mortems are conducted")
    else:
        recs.append("Conduct blameless post-mortems after P1/P2 incidents")

    if data.get("action_item_tracking"):
        score += 1.0
        findings.append("Action items are tracked after incidents")
    else:
        recs.append("Track and follow up on incident action items")

    if data.get("severity_definitions"):
        score += 1.0
        findings.append("Incident severity levels defined")
    else:
        recs.append("Define clear severity levels (P1-P4) with response expectations")

    if data.get("automated_detection"):
        score += 1.0
        findings.append("Automated incident detection enabled")
    else:
        recs.append("Automate incident detection via monitoring and alerting")

    return MaturityDimension(name="Incident Management", score=min(5.0, score),
                             findings=findings, recommendations=recs)


def _score_monitoring(data: dict) -> MaturityDimension:
    score = 0.0
    findings = []
    recs = []

    if data.get("has_metrics"):
        score += 1.0
        findings.append("Metrics collection in place")
    else:
        recs.append("Implement metrics collection (Prometheus, Datadog, etc.)")

    if data.get("has_logging"):
        score += 0.5
        findings.append("Centralized logging enabled")
    else:
        recs.append("Set up centralized logging (ELK, Loki, etc.)")

    if data.get("has_tracing"):
        score += 0.5
        findings.append("Distributed tracing enabled")
    else:
        recs.append("Implement distributed tracing (Jaeger, Zipkin, etc.)")

    if data.get("has_dashboards"):
        score += 1.0
        findings.append("Service dashboards exist")
    else:
        recs.append("Create dashboards for key services and SLIs")

    if data.get("has_alerting"):
        score += 1.0
        findings.append("Alerting configured")
    else:
        recs.append("Configure alerting for SLO violations")

    if data.get("golden_signals"):
        score += 1.0
        findings.append("Golden signals monitored (latency, traffic, errors, saturation)")
    else:
        recs.append("Monitor the four golden signals for all services")

    return MaturityDimension(name="Monitoring & Observability", score=min(5.0, score),
                             findings=findings, recommendations=recs)


def _score_toil_reduction(data: dict) -> MaturityDimension:
    score = 0.0
    findings = []
    recs = []

    if data.get("toil_tracked"):
        score += 1.0
        findings.append("Toil is measured and tracked")
    else:
        recs.append("Start measuring and tracking toil tasks")

    toil_pct = data.get("toil_percentage", 100)
    if toil_pct <= 15:
        score += 2.0
        findings.append(f"Toil at {toil_pct}% (excellent)")
    elif toil_pct <= 30:
        score += 1.0
        findings.append(f"Toil at {toil_pct}% (acceptable)")
    else:
        recs.append(f"Toil at {toil_pct}% — target below 30%")

    if data.get("automation_projects"):
        score += 1.0
        findings.append("Active automation projects in progress")
    else:
        recs.append("Create dedicated automation projects to reduce toil")

    if data.get("self_service_tools"):
        score += 1.0
        findings.append("Self-service tools available for developers")
    else:
        recs.append("Build self-service tools to eliminate manual toil")

    return MaturityDimension(name="Toil Reduction", score=min(5.0, score),
                             findings=findings, recommendations=recs)


def _score_blameless_culture(data: dict) -> MaturityDimension:
    score = 0.0
    findings = []
    recs = []

    if data.get("blameless_postmortems"):
        score += 1.5
        findings.append("Blameless post-mortems are the norm")
    else:
        recs.append("Adopt blameless post-mortem culture")

    if data.get("learning_reviews"):
        score += 1.0
        findings.append("Learning reviews conducted regularly")
    else:
        recs.append("Conduct regular learning reviews from incidents")

    if data.get("psychological_safety"):
        score += 1.5
        findings.append("Team reports high psychological safety")
    else:
        recs.append("Foster psychological safety — people should feel safe reporting issues")

    if data.get("knowledge_sharing"):
        score += 1.0
        findings.append("Knowledge sharing practices in place")
    else:
        recs.append("Establish knowledge sharing (tech talks, internal docs, etc.)")

    return MaturityDimension(name="Blameless Culture", score=min(5.0, score),
                             findings=findings, recommendations=recs)


def _score_on_call(data: dict) -> MaturityDimension:
    score = 0.0
    findings = []
    recs = []

    if data.get("has_rotation"):
        score += 1.0
        findings.append("On-call rotation exists")
    else:
        recs.append("Establish an on-call rotation schedule")

    rotation_size = data.get("rotation_size", 0)
    if rotation_size >= 5:
        score += 1.0
        findings.append(f"Rotation has {rotation_size} people (healthy)")
    elif rotation_size >= 3:
        score += 0.5
        findings.append(f"Rotation has {rotation_size} people (minimum)")
    else:
        recs.append("Expand on-call rotation to at least 4-5 people")

    if data.get("compensation"):
        score += 1.0
        findings.append("On-call compensation provided")
    else:
        recs.append("Provide compensation or time-off for on-call duty")

    if data.get("runbooks"):
        score += 1.0
        findings.append("Runbooks available for on-call")
    else:
        recs.append("Create runbooks for common on-call scenarios")

    if data.get("handoff_process"):
        score += 1.0
        findings.append("Formal handoff process between rotations")
    else:
        recs.append("Establish a handoff process for rotation transitions")

    return MaturityDimension(name="On-Call Practices", score=min(5.0, score),
                             findings=findings, recommendations=recs)


def _score_capacity_planning(data: dict) -> MaturityDimension:
    score = 0.0
    findings = []
    recs = []

    if data.get("resource_monitoring"):
        score += 1.0
        findings.append("Resource utilization is monitored")
    else:
        recs.append("Monitor CPU, memory, disk, and network utilization")

    if data.get("growth_projections"):
        score += 1.5
        findings.append("Growth projections inform capacity planning")
    else:
        recs.append("Create growth projections based on business metrics")

    if data.get("auto_scaling"):
        score += 1.0
        findings.append("Auto-scaling configured")
    else:
        recs.append("Implement auto-scaling for variable workloads")

    if data.get("load_testing"):
        score += 1.0
        findings.append("Regular load testing performed")
    else:
        recs.append("Perform regular load testing to validate capacity")

    if data.get("cost_optimization"):
        score += 0.5
        findings.append("Cost optimization practices in place")
    else:
        recs.append("Implement cost optimization for cloud resources")

    return MaturityDimension(name="Capacity Planning", score=min(5.0, score),
                             findings=findings, recommendations=recs)


def _score_change_management(data: dict) -> MaturityDimension:
    score = 0.0
    findings = []
    recs = []

    if data.get("ci_cd_pipeline"):
        score += 1.0
        findings.append("CI/CD pipeline in place")
    else:
        recs.append("Implement CI/CD pipeline for automated deployments")

    if data.get("canary_deployments"):
        score += 1.0
        findings.append("Canary/progressive deployments used")
    else:
        recs.append("Use canary or blue-green deployments for safety")

    if data.get("rollback_automation"):
        score += 1.0
        findings.append("Automated rollback capability exists")
    else:
        recs.append("Automate rollback procedures")

    if data.get("feature_flags"):
        score += 1.0
        findings.append("Feature flags used for safe rollouts")
    else:
        recs.append("Implement feature flags for controlled rollouts")

    if data.get("change_review"):
        score += 1.0
        findings.append("Changes reviewed before deployment")
    else:
        recs.append("Require change reviews (PR reviews, deployment approvals)")

    return MaturityDimension(name="Change Management", score=min(5.0, score),
                             findings=findings, recommendations=recs)
