defmodule BerrypodWeb.CartControllerTest do
  use BerrypodWeb.ConnCase, async: false

  import Berrypod.AccountsFixtures

  alias Berrypod.ProductsFixtures

  setup do
    user_fixture()
    {:ok, _} = Berrypod.Settings.set_site_live(true)
    :ok
  end

  defp create_variant(_context) do
    product = ProductsFixtures.complete_product_fixture(%{title: "Test Print"})
    variant = List.first(product.variants)
    %{product: product, variant: variant}
  end

  defp conn_with_cart(conn, variant_id, qty) do
    Phoenix.ConnTest.init_test_session(conn, %{"cart" => [{variant_id, qty}]})
  end

  describe "POST /cart/add" do
    setup [:create_variant]

    test "adds item to session cart and redirects to /cart", %{conn: conn, variant: variant} do
      conn = post(conn, ~p"/cart/add", %{"variant_id" => variant.id, "quantity" => "1"})

      assert redirected_to(conn) == "/cart"
      assert Phoenix.Flash.get(conn.assigns.flash, :info) == "Added to basket"

      cart = get_session(conn, "cart")
      assert [{variant_id, 1}] = cart
      assert variant_id == variant.id
    end

    test "increments quantity if item already in cart", %{conn: conn, variant: variant} do
      conn =
        conn
        |> conn_with_cart(variant.id, 2)
        |> post(~p"/cart/add", %{"variant_id" => variant.id, "quantity" => "3"})

      cart = get_session(conn, "cart")
      assert [{_, 5}] = cart
    end

    test "defaults quantity to 1 for invalid values", %{conn: conn, variant: variant} do
      conn = post(conn, ~p"/cart/add", %{"variant_id" => variant.id, "quantity" => "abc"})

      cart = get_session(conn, "cart")
      assert [{_, 1}] = cart
    end

    test "handles missing params gracefully", %{conn: conn} do
      conn = post(conn, ~p"/cart/add", %{})

      assert redirected_to(conn) == "/cart"
      assert Phoenix.Flash.get(conn.assigns.flash, :error) == "Could not add item to basket"
    end
  end

  describe "POST /cart/remove" do
    setup [:create_variant]

    test "removes item from session cart", %{conn: conn, variant: variant} do
      conn =
        conn
        |> conn_with_cart(variant.id, 2)
        |> post(~p"/cart/remove", %{"variant_id" => variant.id})

      assert redirected_to(conn) == "/cart"
      assert Phoenix.Flash.get(conn.assigns.flash, :info) == "Removed from basket"

      cart = get_session(conn, "cart")
      assert cart == []
    end

    test "handles removing non-existent item", %{conn: conn} do
      conn = post(conn, ~p"/cart/remove", %{"variant_id" => Ecto.UUID.generate()})

      assert redirected_to(conn) == "/cart"
    end
  end

  describe "POST /cart/update" do
    setup [:create_variant]

    test "updates quantity in session cart", %{conn: conn, variant: variant} do
      conn =
        conn
        |> conn_with_cart(variant.id, 1)
        |> post(~p"/cart/update", %{"variant_id" => variant.id, "quantity" => "5"})

      assert redirected_to(conn) == "/cart"

      cart = get_session(conn, "cart")
      assert [{_, 5}] = cart
    end

    test "removes item when quantity is 0 or less", %{conn: conn, variant: variant} do
      conn =
        conn
        |> conn_with_cart(variant.id, 3)
        |> post(~p"/cart/update", %{"variant_id" => variant.id, "quantity" => "0"})

      cart = get_session(conn, "cart")
      assert cart == []
    end
  end

  describe "POST /cart/country" do
    test "saves country to session and redirects to /cart", %{conn: conn} do
      conn = post(conn, ~p"/cart/country", %{"country" => "DE"})

      assert redirected_to(conn) == "/cart"
      assert get_session(conn, "country_code") == "DE"
    end

    test "handles missing country param", %{conn: conn} do
      conn = post(conn, ~p"/cart/country", %{})

      assert redirected_to(conn) == "/cart"
    end
  end
end
