defmodule Tarakan.Credits.Entry do
  @moduledoc """
  One append-only credit ledger line.

  Entries are never updated or deleted; corrections are new entries. Mint
  entries carry a subject (`subject_type`/`subject_id`) so the partial unique
  index can reject double-mints at the database level.
  """

  use Ecto.Schema
  import Ecto.Changeset

  alias Tarakan.Accounts.Account

  @kinds ~w(mint_finding_verified mint_check_correct mint_fix_settled
            spend_bounty_escrow spend_priority_boost spend_review_job
            receive_bounty adjustment)

  schema "credit_entries" do
    field :amount, :integer
    field :kind, :string
    field :subject_type, :string
    field :subject_id, :integer
    field :balance_after, :integer

    belongs_to :account, Account

    timestamps(type: :utc_datetime_usec, updated_at: false)
  end

  def kinds, do: @kinds

  @doc false
  def changeset(entry, attrs) do
    entry
    |> cast(attrs, [:account_id, :amount, :kind, :subject_type, :subject_id, :balance_after])
    |> validate_required([:account_id, :amount, :kind, :balance_after])
    |> validate_inclusion(:kind, @kinds)
    |> unique_constraint(:kind, name: :credit_entries_mint_unique_index)
  end
end
