defmodule Towerops.DashboardTest do
  use Towerops.DataCase, async: true

  import Towerops.AccountsFixtures
  import Towerops.DevicesFixtures
  import Towerops.OrganizationsFixtures

  alias Towerops.Dashboard
  alias Towerops.Gaiia

  setup do
    user = user_fixture()
    org = organization_fixture(user.id)

    %{org: org, user: user}
  end

  describe "get_dashboard_summary/1" do
    test "returns correct structure with empty org", %{org: org} do
      summary = Dashboard.get_dashboard_summary(org.id)

      assert is_map(summary)
      assert Map.has_key?(summary, :health_score)
      assert Map.has_key?(summary, :devices)
      assert Map.has_key?(summary, :alerts)
      assert Map.has_key?(summary, :subscribers)
      assert Map.has_key?(summary, :insights)
    end

    test "returns device counts", %{org: org} do
      device = device_fixture(%{organization_id: org.id})
      Towerops.Devices.update_device_status(device, :up)

      summary = Dashboard.get_dashboard_summary(org.id)

      assert summary.devices.total == 1
      assert summary.devices.up == 1
      assert summary.devices.down == 0
    end

    test "returns alert count", %{org: org} do
      device = device_fixture(%{organization_id: org.id})

      {:ok, _alert} =
        Towerops.Alerts.create_alert(%{
          device_id: device.id,
          alert_type: :device_down,
          triggered_at: DateTime.utc_now(),
          message: "Device is down"
        })

      summary = Dashboard.get_dashboard_summary(org.id)
      assert summary.alerts.active_count == 1
    end

    test "returns subscriber totals from Gaiia", %{org: org} do
      {:ok, _} =
        Gaiia.upsert_network_site(org.id, %{
          gaiia_id: "ns-dash",
          name: "Tower",
          account_count: 100,
          total_mrr: Decimal.new("5000.00")
        })

      summary = Dashboard.get_dashboard_summary(org.id)
      assert summary.subscribers.total == 100
      assert Decimal.equal?(summary.subscribers.total_mrr, Decimal.new("5000.00"))
    end

    test "returns zero subscribers when no Gaiia data", %{org: org} do
      summary = Dashboard.get_dashboard_summary(org.id)
      assert summary.subscribers.total == 0
    end

    test "returns insight counts by urgency", %{org: org} do
      summary = Dashboard.get_dashboard_summary(org.id)
      assert summary.insights.critical == 0
      assert summary.insights.warning == 0
      assert summary.insights.info == 0
    end
  end

  describe "compute_health_score/1" do
    test "returns 100 when all devices up, no alerts", %{org: org} do
      device = device_fixture(%{organization_id: org.id})
      Towerops.Devices.update_device_status(device, :up)

      score = Dashboard.compute_health_score(org.id)
      assert score == 100
    end

    test "returns lower score when devices down", %{org: org} do
      d1 = device_fixture(%{organization_id: org.id})
      d2 = device_fixture(%{organization_id: org.id})
      Towerops.Devices.update_device_status(d1, :up)
      Towerops.Devices.update_device_status(d2, :down)

      score = Dashboard.compute_health_score(org.id)
      assert score < 100
      assert score > 0
    end

    test "returns 100 when no devices exist", %{org: org} do
      score = Dashboard.compute_health_score(org.id)
      assert score == 100
    end

    test "penalizes for critical alerts", %{org: org} do
      device = device_fixture(%{organization_id: org.id})
      Towerops.Devices.update_device_status(device, :up)

      {:ok, _} =
        Towerops.Alerts.create_alert(%{
          device_id: device.id,
          alert_type: :device_down,
          triggered_at: DateTime.utc_now(),
          message: "Device down"
        })

      score = Dashboard.compute_health_score(org.id)
      assert score < 100
    end
  end

  describe "get_org_subscriber_summary/1" do
    test "returns totals from Gaiia network sites", %{org: org} do
      {:ok, _} =
        Gaiia.upsert_network_site(org.id, %{
          gaiia_id: "ns-sub1",
          name: "Tower A",
          account_count: 50,
          total_mrr: Decimal.new("2500.00")
        })

      {:ok, _} =
        Gaiia.upsert_network_site(org.id, %{
          gaiia_id: "ns-sub2",
          name: "Tower B",
          account_count: 30,
          total_mrr: Decimal.new("1500.00")
        })

      result = Dashboard.get_org_subscriber_summary(org.id)
      assert result.total == 80
      assert Decimal.equal?(result.total_mrr, Decimal.new("4000.00"))
    end

    test "returns zeros when no Gaiia data", %{org: org} do
      result = Dashboard.get_org_subscriber_summary(org.id)
      assert result.total == 0
      assert Decimal.equal?(result.total_mrr, Decimal.new(0))
    end
  end

  describe "list_site_summaries/1" do
    test "returns enriched site data", %{org: org} do
      {:ok, site} =
        Towerops.Sites.create_site(%{
          name: "Test Tower",
          organization_id: org.id
        })

      device = device_fixture(%{organization_id: org.id, site_id: site.id})
      Towerops.Devices.update_device_status(device, :up)

      summaries = Dashboard.list_site_summaries(org.id)
      assert summaries != []

      summary = Enum.find(summaries, &(&1.site_id == site.id))
      assert summary.name == "Test Tower"
      assert summary.device_count >= 1
    end
  end
end
