from __future__ import annotations
from dataclasses import dataclass
from typing import Dict, List, Any

from agent_sentinel import SentinelRunner, Guardrails, DecisionPolicy, ConfidenceInputs
from agent_sentinel.roi.report import build_finops_roi_report

@dataclass(frozen=True)
class Recommendation:
    resource_id: str
    resource_type: str
    action: str
    est_monthly_savings_usd: float
    risk: str
    rationale: str

def finops_agent(ctx, payload: Dict[str, Any]) -> Dict[str, Any]:
    resources: List[Dict[str, Any]] = payload["resources"]
    ctx.add_cost(payload.get("estimated_cost_usd", 0.01))

    recs: List[Recommendation] = []
    for r in resources:
        rtype = r["type"]
        rid = r["id"]
        cost = float(r.get("monthly_cost_usd", 0.0))
        util = float(r.get("utilization_pct", 0.0))
        days_idle = int(r.get("days_idle", 0))
        tagged_keep = bool(r.get("tag_keep", False))
        if tagged_keep:
            continue

        if rtype == "ec2_instance":
            if util < 10.0 and cost > 200:
                recs.append(Recommendation(rid, rtype, "rightsizing_recommendation", round(cost * 0.35, 2), "med",
                                           f"Low utilization ({util}%). Recommend downsizing."))
            elif days_idle >= 14 and cost > 50:
                recs.append(Recommendation(rid, rtype, "stop_instance_schedule", round(cost * 0.65, 2), "low",
                                           f"Idle for {days_idle} days. Recommend stop/schedule."))

        elif rtype == "ebs_volume":
            attached = bool(r.get("attached", False))
            if not attached and days_idle >= 7 and cost > 10:
                recs.append(Recommendation(rid, rtype, "snapshot_then_delete", round(cost * 0.90, 2), "low",
                                           "Unattached volume. Snapshot then delete."))

        elif rtype == "rds_instance":
            if util < 5.0 and cost > 300:
                recs.append(Recommendation(rid, rtype, "rightsizing_recommendation", round(cost * 0.30, 2), "high",
                                           f"Very low DB utilization ({util}%). Needs owner validation."))

        elif rtype == "s3_bucket":
            gb = float(r.get("storage_gb", 0.0))
            if gb > 5000:
                recs.append(Recommendation(rid, rtype, "lifecycle_to_infrequent_access", round(cost * 0.20, 2), "low",
                                           "Large bucket. Add lifecycle policy to cheaper storage class."))

    total_savings = round(sum(x.est_monthly_savings_usd for x in recs), 2)
    return {
        "summary": {
            "num_resources_scanned": len(resources),
            "num_recommendations": len(recs),
            "est_total_monthly_savings_usd": total_savings,
        },
        "recommendations": [x.__dict__ for x in recs],
    }

def main():
    runner = SentinelRunner(
        name="finops_cost_optimizer",
        guardrails=Guardrails(max_steps=3, max_tool_calls=5, max_cost_usd=0.25, deterministic=True),
        decision_policy=DecisionPolicy(min_confidence=0.80),
        metadata={"domain": "finops"},
    )

    payload = {
        "estimated_cost_usd": 0.02,
        "resources": [
            {"type": "ec2_instance", "id": "i-01", "monthly_cost_usd": 520, "utilization_pct": 6.2, "days_idle": 0},
            {"type": "ec2_instance", "id": "i-02", "monthly_cost_usd": 120, "utilization_pct": 1.0, "days_idle": 19},
            {"type": "ebs_volume", "id": "vol-01", "monthly_cost_usd": 45, "attached": False, "days_idle": 28},
            {"type": "rds_instance", "id": "db-01", "monthly_cost_usd": 860, "utilization_pct": 2.0, "days_idle": 0},
            {"type": "s3_bucket", "id": "bucket-logs", "monthly_cost_usd": 310, "storage_gb": 9200},
        ],
    }

    ci = ConfidenceInputs(prob=0.84, margin=0.25, z_score=1.8, entropy=0.30, llm_self_score=0.80)
    res = runner.run(finops_agent, payload, confidence_inputs=ci)

    print("\n=== Sentinel Result ===")
    print("Outcome:", res.outcome.value)
    print("Confidence:", round(res.confidence, 3))
    print("Agent output:", res.output)

    report = build_finops_roi_report(sentinel_result=res, agent_output=res.output, top_n=5)
    md = report.to_markdown()

    with open("ROI_REPORT.md", "w", encoding="utf-8") as f:
        f.write(md)

    print("\n=== ROI Report (written to ROI_REPORT.md) ===\n")
    print(md)

if __name__ == "__main__":
    main()
