defmodule Towerops.Integrations.Integration do
  @moduledoc """
  Schema for per-organization third-party integrations.

  Each organization can have one integration per provider. Credentials
  are encrypted at rest using Cloak AES-256-GCM.
  """
  use Ecto.Schema

  import Ecto.Changeset

  alias Towerops.Encrypted

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

  @valid_providers ~w(preseem gaiia)
  @valid_sync_statuses ~w(never success partial failed)

  schema "integrations" do
    field :provider, :string
    field :enabled, :boolean, default: false
    field :credentials, Encrypted.Map
    field :sync_interval_minutes, :integer, default: 10
    field :last_synced_at, :utc_datetime
    field :last_sync_status, :string, default: "never"

    belongs_to :organization, Towerops.Organizations.Organization

    timestamps(type: :utc_datetime)
  end

  def changeset(integration, attrs) do
    integration
    |> cast(attrs, [
      :organization_id,
      :provider,
      :enabled,
      :credentials,
      :sync_interval_minutes,
      :last_synced_at,
      :last_sync_status
    ])
    |> validate_required([:organization_id, :provider])
    |> validate_inclusion(:provider, @valid_providers)
    |> validate_inclusion(:last_sync_status, @valid_sync_statuses)
    |> validate_number(:sync_interval_minutes, greater_than: 0)
    |> unique_constraint([:organization_id, :provider],
      error_key: :provider,
      message: "has already been taken"
    )
    |> foreign_key_constraint(:organization_id)
  end
end
