defmodule Berrypod.Sync.ProductSyncWorkerTest do
  use Berrypod.DataCase, async: false
  use Oban.Testing, repo: Berrypod.Repo

  alias Berrypod.Products
  alias Berrypod.Sync.ProductSyncWorker

  import Berrypod.ProductsFixtures

  describe "perform/1" do
    test "cancels for missing connection" do
      fake_id = Ecto.UUID.generate()

      assert {:cancel, :connection_not_found} =
               perform_job(ProductSyncWorker, %{provider_connection_id: fake_id})
    end

    test "cancels for disabled connection" do
      conn = provider_connection_fixture(%{enabled: false})

      assert {:cancel, :connection_disabled} =
               perform_job(ProductSyncWorker, %{provider_connection_id: conn.id})
    end

    test "sets status to syncing then updates on completion or failure" do
      conn = provider_connection_fixture(%{enabled: true})

      # The job will fail because we don't have a real API connection
      # but it should still update the status properly
      _result = perform_job(ProductSyncWorker, %{provider_connection_id: conn.id})

      # Reload the connection
      updated_conn = Products.get_provider_connection!(conn.id)

      # Status should be either "completed" or "failed", not stuck at "syncing"
      assert updated_conn.sync_status in ["completed", "failed"]
    end
  end

  describe "enqueue/1" do
    test "creates a job with correct args" do
      # Temporarily switch to manual mode to avoid inline execution
      Oban.Testing.with_testing_mode(:manual, fn ->
        conn = provider_connection_fixture()

        assert {:ok, %Oban.Job{} = job} = ProductSyncWorker.enqueue(conn.id)
        # In manual mode, args use atom keys
        assert job.args == %{provider_connection_id: conn.id}
        assert job.queue == "sync"
      end)
    end
  end

  describe "enqueue/2 with delay" do
    test "schedules a job for later" do
      Oban.Testing.with_testing_mode(:manual, fn ->
        conn = provider_connection_fixture()

        assert {:ok, %Oban.Job{} = job} = ProductSyncWorker.enqueue(conn.id, 60)
        # In manual mode, args use atom keys
        assert job.args == %{provider_connection_id: conn.id}

        # Job should be scheduled in the future
        assert DateTime.compare(job.scheduled_at, DateTime.utc_now()) == :gt
      end)
    end
  end

  describe "job creation" do
    test "new/1 creates job changeset with provider_connection_id" do
      changeset = ProductSyncWorker.new(%{provider_connection_id: "test-id"})

      assert changeset.changes.args == %{provider_connection_id: "test-id"}
      assert changeset.changes.queue == "sync"
    end

    test "new/2 with scheduled_at creates scheduled job" do
      future = DateTime.add(DateTime.utc_now(), 60, :second)

      changeset =
        ProductSyncWorker.new(%{provider_connection_id: "test-id"}, scheduled_at: future)

      assert changeset.changes.scheduled_at == future
    end
  end
end
