defmodule Towerops.Gaiia.ReconciliationTest do
  use Towerops.DataCase, async: true

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

  alias Towerops.Gaiia
  alias Towerops.Gaiia.Reconciliation

  setup do
    user = user_fixture()
    org = organization_fixture(user.id)
    %{org: org}
  end

  describe "reconcile/1" do
    test "returns empty report when no inventory items exist", %{org: org} do
      result = Reconciliation.reconcile(org.id)

      assert result.ghost_devices == []
      assert result.untracked_devices == []
      assert result.data_mismatches == []
      assert result.missing_mappings == []
      assert result.summary.total_mapped == 0
    end

    test "detects ghost devices (in Gaiia but not discovered by Towerops)", %{org: org} do
      {:ok, _item} =
        Gaiia.upsert_inventory_item(org.id, %{
          gaiia_id: "gaiia-inv-1",
          name: "Ghost Router",
          ip_address: "10.0.0.99",
          status: "active"
        })

      # No matching Towerops device exists
      result = Reconciliation.reconcile(org.id)

      assert length(result.missing_mappings) == 1
      [missing] = result.missing_mappings
      assert missing.inventory_item.name == "Ghost Router"
    end

    test "detects untracked devices (in Towerops but not in Gaiia)", %{org: org} do
      _device = device_fixture(%{organization_id: org.id, name: "Untracked AP"})

      result = Reconciliation.reconcile(org.id)

      assert length(result.untracked_devices) == 1
      [untracked] = result.untracked_devices
      assert untracked.device.name == "Untracked AP"
    end

    test "detects IP address mismatches on mapped devices", %{org: org} do
      device =
        device_fixture(%{
          organization_id: org.id,
          name: "Tower Router",
          ip_address: "10.0.0.1"
        })

      {:ok, _item} =
        Gaiia.upsert_inventory_item(org.id, %{
          gaiia_id: "gaiia-inv-1",
          name: "Tower Router",
          ip_address: "10.0.0.99"
        })

      Gaiia.update_inventory_item_mapping(
        Gaiia.get_inventory_item(org.id, "gaiia-inv-1"),
        %{device_id: device.id}
      )

      result = Reconciliation.reconcile(org.id)

      assert length(result.data_mismatches) == 1
      [mismatch] = result.data_mismatches
      assert mismatch.field == :ip_address
      assert mismatch.towerops_value == "10.0.0.1"
      assert mismatch.gaiia_value == "10.0.0.99"
    end

    test "does not flag matched devices with matching data", %{org: org} do
      device =
        device_fixture(%{
          organization_id: org.id,
          name: "Tower Router",
          ip_address: "10.0.0.1"
        })

      {:ok, _item} =
        Gaiia.upsert_inventory_item(org.id, %{
          gaiia_id: "gaiia-inv-1",
          name: "Tower Router",
          ip_address: "10.0.0.1"
        })

      Gaiia.update_inventory_item_mapping(
        Gaiia.get_inventory_item(org.id, "gaiia-inv-1"),
        %{device_id: device.id}
      )

      result = Reconciliation.reconcile(org.id)

      assert result.data_mismatches == []
      assert result.untracked_devices == []
      assert result.missing_mappings == []
      assert result.summary.total_mapped == 1
    end

    test "summary counts are correct", %{org: org} do
      device1 =
        device_fixture(%{organization_id: org.id, name: "Mapped Router", ip_address: "10.0.0.1"})

      _device2 = device_fixture(%{organization_id: org.id, name: "Untracked AP"})

      {:ok, _item1} =
        Gaiia.upsert_inventory_item(org.id, %{
          gaiia_id: "gaiia-inv-1",
          name: "Mapped Router",
          ip_address: "10.0.0.1"
        })

      Gaiia.update_inventory_item_mapping(
        Gaiia.get_inventory_item(org.id, "gaiia-inv-1"),
        %{device_id: device1.id}
      )

      {:ok, _item2} =
        Gaiia.upsert_inventory_item(org.id, %{
          gaiia_id: "gaiia-inv-2",
          name: "Unmapped Item",
          status: "active"
        })

      result = Reconciliation.reconcile(org.id)

      assert result.summary.total_mapped == 1
      assert result.summary.untracked_count == 1
      assert result.summary.missing_mapping_count == 1
    end
  end
end
