defmodule SimpleshopTheme.Orders.Order do
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id

  @payment_statuses ~w(pending paid failed refunded)
  @fulfilment_statuses ~w(unfulfilled submitted processing shipped delivered failed cancelled)

  def fulfilment_statuses, do: @fulfilment_statuses

  schema "orders" do
    field :order_number, :string
    field :stripe_session_id, :string
    field :stripe_payment_intent_id, :string
    field :payment_status, :string, default: "pending"
    field :customer_email, :string
    field :shipping_address, :map, default: %{}
    field :subtotal, :integer
    field :total, :integer
    field :currency, :string, default: "gbp"
    field :metadata, :map, default: %{}

    # Fulfilment
    field :fulfilment_status, :string, default: "unfulfilled"
    field :provider_order_id, :string
    field :provider_status, :string
    field :fulfilment_error, :string
    field :tracking_number, :string
    field :tracking_url, :string
    field :submitted_at, :utc_datetime
    field :shipped_at, :utc_datetime
    field :delivered_at, :utc_datetime

    has_many :items, SimpleshopTheme.Orders.OrderItem

    timestamps(type: :utc_datetime)
  end

  def changeset(order, attrs) do
    order
    |> cast(attrs, [
      :order_number,
      :stripe_session_id,
      :stripe_payment_intent_id,
      :payment_status,
      :customer_email,
      :shipping_address,
      :subtotal,
      :total,
      :currency,
      :metadata
    ])
    |> validate_required([:order_number, :subtotal, :total, :currency])
    |> validate_inclusion(:payment_status, @payment_statuses)
    |> validate_number(:subtotal, greater_than_or_equal_to: 0)
    |> validate_number(:total, greater_than_or_equal_to: 0)
    |> unique_constraint(:order_number)
    |> unique_constraint(:stripe_session_id)
  end

  def fulfilment_changeset(order, attrs) do
    order
    |> cast(attrs, [
      :fulfilment_status,
      :provider_order_id,
      :provider_status,
      :fulfilment_error,
      :tracking_number,
      :tracking_url,
      :submitted_at,
      :shipped_at,
      :delivered_at
    ])
    |> validate_inclusion(:fulfilment_status, @fulfilment_statuses)
  end
end
