defmodule Lucidboard.Card do
  @moduledoc "Schema for a board record"
  use Ecto.Schema
  import Ecto.Changeset
  alias Ecto.UUID
  alias Lucidboard.{CardSettings, Like, Pile, User}

  @primary_key {:id, :binary_id, autogenerate: false}
  @derive {Jason.Encoder, only: ~w(id pos body locked settings likes)a}

  schema "cards" do
    field(:pos, :integer)
    field(:body, :string)
    # field(:locked, :boolean)
    # field(:locked_by, User)
    embeds_one(:settings, CardSettings, on_replace: :update)
    belongs_to(:pile, Pile, type: :binary_id)
    belongs_to(:user, User)
    # many_to_many(:users_liked, User, join_through: Like)
    # No idea why this `on_delete` is needed when it seems to be set up
    # properly in the db migration
    has_many(:likes, Like, on_delete: :delete_all)
  end

  @spec new(keyword) :: Card.t()
  def new(fields \\ []) do
    defaults = [
      id: UUID.generate(),
      pos: 0,
      body: "",
      locked: false,
      settings: CardSettings.new(),
      likes: []
    ]

    struct(__MODULE__, Keyword.merge(defaults, fields))
  end

  def changeset(card, attrs \\ %{}) do
    settings =
      if attrs["color"] do
        %{color: attrs["color"]}
      else
        attrs[:settings]
      end

    if settings do
      card
      |> cast(attrs, [:body, :pile_id, :pos])
      |> put_change(:settings, settings)
    else
      card
      |> cast(attrs, [:body, :pile_id, :pos])
    end
  end

  @doc "Get the number of likes on a card"
  def like_count(%__MODULE__{likes: likes}) do
    length(likes)
  end
end
