defmodule Towerops.Vault do
  @moduledoc """
  Encryption vault for sensitive data using Cloak.

  Encrypts data using AES-256-GCM encryption. The encryption key is loaded
  from the CLOAK_KEY environment variable (base64-encoded).

  ## Usage

  Fields that use this vault are automatically encrypted/decrypted by Ecto.
  See `Towerops.Encrypted.Binary` for the custom Ecto type.

  ## Key Generation

  Generate a new encryption key:

      openssl rand -base64 32

  Store this key securely in 1Password and set it as the CLOAK_KEY
  environment variable in production.
  """
  use Cloak.Vault, otp_app: :towerops

  @impl GenServer
  def init(config) do
    # In dev/test, the key is already configured in config files
    # In production (runtime.exs), we override with env var
    config =
      if System.get_env("CLOAK_KEY") do
        Keyword.put(config, :ciphers,
          default: {
            Cloak.Ciphers.AES.GCM,
            tag: "AES.GCM.V1", key: decode_env!("CLOAK_KEY")
          }
        )
      else
        # Use the key from config (dev/test)
        config
      end

    {:ok, config}
  end

  defp decode_env!(var) do
    var
    |> System.get_env()
    |> case do
      nil ->
        raise """
        Environment variable #{var} is missing.
        Generate a key with: openssl rand -base64 32
        """

      value ->
        Base.decode64!(value)
    end
  end
end
