defmodule SimpleshopThemeWeb.WebhookControllerTest do
  use SimpleshopThemeWeb.ConnCase

  import SimpleshopTheme.ProductsFixtures

  @webhook_secret "test_webhook_secret_123"

  setup do
    _conn =
      provider_connection_fixture(%{
        provider_type: "printify",
        config: %{"shop_id" => "12345", "webhook_secret" => @webhook_secret}
      })

    :ok
  end

  describe "POST /webhooks/printify" do
    test "returns 401 without signature", %{conn: conn} do
      conn =
        conn
        |> put_req_header("content-type", "application/json")
        |> post(~p"/webhooks/printify", %{type: "product:updated"})

      assert json_response(conn, 401)["error"] == "Invalid signature"
    end

    test "returns 401 with invalid signature", %{conn: conn} do
      body = Jason.encode!(%{type: "product:updated", resource: %{id: "123"}})

      conn =
        conn
        |> put_req_header("content-type", "application/json")
        |> put_req_header("x-pfy-signature", "sha256=invalid")
        |> post(~p"/webhooks/printify", body)

      assert json_response(conn, 401)["error"] == "Invalid signature"
    end

    test "accepts valid signature and returns 200", %{conn: conn} do
      body = Jason.encode!(%{type: "product:updated", resource: %{id: "123", shop_id: "12345"}})
      signature = compute_signature(body, @webhook_secret)

      conn =
        conn
        |> put_req_header("content-type", "application/json")
        |> put_req_header("x-pfy-signature", "sha256=#{signature}")
        |> post(~p"/webhooks/printify", body)

      assert json_response(conn, 200)["status"] == "ok"
    end

    test "handles product:updated event", %{conn: conn} do
      body = Jason.encode!(%{type: "product:updated", resource: %{id: "123", shop_id: "12345"}})
      signature = compute_signature(body, @webhook_secret)

      conn =
        conn
        |> put_req_header("content-type", "application/json")
        |> put_req_header("x-pfy-signature", "sha256=#{signature}")
        |> post(~p"/webhooks/printify", body)

      # Should return 200 even if job processing fails (inline mode tries to execute)
      assert json_response(conn, 200)["status"] == "ok"
    end

    test "handles product:deleted event", %{conn: conn} do
      body = Jason.encode!(%{type: "product:deleted", resource: %{id: "456"}})
      signature = compute_signature(body, @webhook_secret)

      conn =
        conn
        |> put_req_header("content-type", "application/json")
        |> put_req_header("x-pfy-signature", "sha256=#{signature}")
        |> post(~p"/webhooks/printify", body)

      assert json_response(conn, 200)["status"] == "ok"
    end

    test "returns 401 when no webhook secret configured", %{conn: conn} do
      # Remove the provider connection to simulate no secret
      SimpleshopTheme.Repo.delete_all(SimpleshopTheme.Products.ProviderConnection)

      body = Jason.encode!(%{type: "product:updated", resource: %{id: "123"}})
      signature = compute_signature(body, @webhook_secret)

      conn =
        conn
        |> put_req_header("content-type", "application/json")
        |> put_req_header("x-pfy-signature", "sha256=#{signature}")
        |> post(~p"/webhooks/printify", body)

      assert json_response(conn, 401)["error"] == "Invalid signature"
    end
  end

  defp compute_signature(body, secret) do
    :crypto.mac(:hmac, :sha256, secret, body)
    |> Base.encode16(case: :lower)
  end
end
