defmodule SimpleshopThemeWeb.CheckoutController do
  use SimpleshopThemeWeb, :controller

  alias SimpleshopTheme.Cart
  alias SimpleshopTheme.Orders

  require Logger

  def create(conn, _params) do
    cart_items = Cart.get_from_session(get_session(conn))
    hydrated = Cart.hydrate(cart_items)

    if hydrated == [] do
      conn
      |> put_flash(:error, "Your basket is empty")
      |> redirect(to: ~p"/cart")
    else
      create_checkout(conn, hydrated)
    end
  end

  defp create_checkout(conn, hydrated_items) do
    # Create a pending order with price snapshots
    case Orders.create_order(%{items: hydrated_items}) do
      {:ok, order} ->
        create_stripe_session(conn, order, hydrated_items)

      {:error, _changeset} ->
        Logger.error("Failed to create order")

        conn
        |> put_flash(:error, "Something went wrong. Please try again.")
        |> redirect(to: ~p"/cart")
    end
  end

  defp create_stripe_session(conn, order, hydrated_items) do
    line_items =
      Enum.map(hydrated_items, fn item ->
        product_name =
          if item.variant,
            do: "#{item.name} — #{item.variant}",
            else: item.name

        %{
          price_data: %{
            currency: "gbp",
            unit_amount: item.price,
            product_data: %{name: product_name}
          },
          quantity: item.quantity
        }
      end)

    base_url = SimpleshopThemeWeb.Endpoint.url()

    params = %{
      mode: "payment",
      line_items: line_items,
      success_url: "#{base_url}/checkout/success?session_id={CHECKOUT_SESSION_ID}",
      cancel_url: "#{base_url}/cart",
      metadata: %{"order_id" => order.id},
      shipping_address_collection: %{
        allowed_countries: ["GB", "US", "CA", "AU", "DE", "FR", "NL", "IE", "AT", "BE"]
      }
    }

    case Stripe.Checkout.Session.create(params) do
      {:ok, session} ->
        {:ok, _order} = Orders.set_stripe_session(order, session.id)

        conn
        |> redirect(external: session.url)

      {:error, %Stripe.Error{message: message}} ->
        Logger.error("Stripe session creation failed: #{message}")
        Orders.mark_failed(order)

        conn
        |> put_flash(:error, "Payment setup failed. Please try again.")
        |> redirect(to: ~p"/cart")

      {:error, reason} ->
        Logger.error("Stripe session creation failed: #{inspect(reason)}")
        Orders.mark_failed(order)

        conn
        |> put_flash(:error, "Payment setup failed. Please try again.")
        |> redirect(to: ~p"/cart")
    end
  end
end
