import json

from tfcost.engines.pricing_engine import calculate_resource_cost
from tfcost.pricing.service_detector import detect_service
from tfcost.history import save_cost_snapshot


def get_module_name(address):

    if address.startswith("module."):
        parts = address.split(".")
        return parts[1]

    return "root"


def calculate_cost(resources, region, summary=False, output="table"):

    has_changes = False

    show_resources = (not summary) and (output != "json")

    previous_cost = 0
    final_cost = 0

    service_costs = {}
    module_costs = {}

    # Header will be printed ONLY if changes exist
    printed_header = False

    for r in resources:

        actions = r.get("actions", [])

        before_config = r.get("before")
        after_config = r.get("config")

        before_cost = 0
        after_cost = 0

        # -----------------------------
        # BEFORE COST
        # -----------------------------
        if before_config:
            before_resource = {
                "type": r["type"],
                "config": before_config
            }

            before_result = calculate_resource_cost(before_resource, region)
            before_cost = before_result["cost"]

        # -----------------------------
        # AFTER COST
        # -----------------------------
        if after_config:
            after_result = calculate_resource_cost(r, region)
            after_cost = after_result["cost"]
            service = after_result["service"]
        else:
            service = detect_service(r["type"])

        diff = after_cost - before_cost

        if diff != 0:
            has_changes = True

        # -----------------------------
        # PRINT ONLY CHANGED RESOURCES
        # -----------------------------
        if show_resources and diff != 0:

            # Print header lazily (only when first change appears)
            if not printed_header:
                print("\nTerraform Cost Estimate")
                print("─" * 80)
                print(f"{'Resource':35} {'Before':>10} {'After':>10} {'Diff':>10}")
                print("─" * 80)
                printed_header = True

            if "create" in actions:
                symbol = "+"
            elif "delete" in actions:
                symbol = "-"
            elif "update" in actions:
                symbol = "~"
            else:
                symbol = " "

            print(
                f"{symbol} {r['address']:33} "
                f"${before_cost:>8.2f} → ${after_cost:>8.2f} "
                f"{diff:+10.2f}"
            )

        # -----------------------------
        # AGGREGATION
        # -----------------------------
        previous_cost += before_cost
        final_cost += after_cost

        service_costs[service] = service_costs.get(service, 0) + after_cost

        module = get_module_name(r["address"])
        module_costs[module] = module_costs.get(module, 0) + after_cost

    cost_change = final_cost - previous_cost

    result = {
        "previous_cost": round(previous_cost, 2),
        "estimated_cost": round(final_cost, 2),
        "cost_change": round(cost_change, 2),
        "services": {k: round(v, 2) for k, v in service_costs.items()},
        "modules": {k: round(v, 2) for k, v in module_costs.items()}
    }

    # -----------------------------
    # JSON OUTPUT
    # -----------------------------
    if output == "json":
        print(json.dumps(result, indent=2))
        return final_cost

    # -----------------------------
    # NO CHANGE CASE
    # -----------------------------
    if not has_changes:
        print("\nNo cost changes detected. Infrastructure cost is up-to-date.")
        save_cost_snapshot(final_cost)
        return final_cost

    # -----------------------------
    # SUMMARY
    # -----------------------------
    print("─" * 80)
    print(f"{'Previous Infrastructure Cost':45} ${previous_cost:>10.2f}")
    print(f"{'Estimated Infrastructure Cost':45} ${final_cost:>10.2f}")
    print(f"{'Cost Change':45} {cost_change:+10.2f}")
    print("─" * 80)

    # -----------------------------
    # SERVICE BREAKDOWN
    # -----------------------------
    print("\nCost Breakdown by Service")
    print("─" * 30)

    for service, cost in service_costs.items():
        if cost > 0:
            print(f"{service:20} ${cost:>8.2f}")

    print("─" * 30)

    # -----------------------------
    # MODULE BREAKDOWN
    # -----------------------------
    print("\nCost Breakdown by Module")
    print("─" * 30)

    for module, cost in module_costs.items():
        print(f"{module:20} ${cost:>8.2f}")

    print("─" * 30)

    # -----------------------------
    # SAVE HISTORY
    # -----------------------------
    save_cost_snapshot(final_cost)

    return final_cost