defmodule Towerops.Preseem.SyncLogTest do
  use Towerops.DataCase, async: true

  import Towerops.AccountsFixtures
  import Towerops.IntegrationsFixtures
  import Towerops.OrganizationsFixtures

  alias Towerops.Preseem.SyncLog

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

  describe "changeset/2" do
    test "valid changeset", %{organization: org, integration: integration} do
      attrs = %{
        organization_id: org.id,
        integration_id: integration.id,
        status: "success",
        records_synced: 42,
        duration_ms: 1500,
        inserted_at: DateTime.truncate(DateTime.utc_now(), :second)
      }

      changeset = SyncLog.changeset(%SyncLog{}, attrs)
      assert changeset.valid?
    end

    test "requires organization_id and integration_id" do
      attrs = %{status: "success", inserted_at: DateTime.truncate(DateTime.utc_now(), :second)}
      changeset = SyncLog.changeset(%SyncLog{}, attrs)
      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).organization_id
      assert "can't be blank" in errors_on(changeset).integration_id
    end

    test "requires status" do
      attrs = %{
        organization_id: Ecto.UUID.generate(),
        integration_id: Ecto.UUID.generate(),
        inserted_at: DateTime.truncate(DateTime.utc_now(), :second)
      }

      changeset = SyncLog.changeset(%SyncLog{}, attrs)
      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).status
    end

    test "validates status values" do
      base = %{
        organization_id: Ecto.UUID.generate(),
        integration_id: Ecto.UUID.generate(),
        inserted_at: DateTime.truncate(DateTime.utc_now(), :second)
      }

      for status <- ~w(success partial failed) do
        changeset = SyncLog.changeset(%SyncLog{}, Map.put(base, :status, status))
        assert changeset.valid?, "Expected #{status} to be valid"
      end

      changeset = SyncLog.changeset(%SyncLog{}, Map.put(base, :status, "bogus"))
      refute changeset.valid?
    end

    test "stores error details", %{organization: org, integration: integration} do
      errors = %{"message" => "API timeout", "code" => 504}

      attrs = %{
        organization_id: org.id,
        integration_id: integration.id,
        status: "failed",
        errors: errors,
        inserted_at: DateTime.truncate(DateTime.utc_now(), :second)
      }

      {:ok, log} = %SyncLog{} |> SyncLog.changeset(attrs) |> Repo.insert()
      reloaded = Repo.get!(SyncLog, log.id)
      assert reloaded.errors == errors
    end
  end
end
