defmodule Towerops.Gaiia.Actions do
  @moduledoc """
  Write-back actions from Towerops to Gaiia.

  Handles:
  - Ticket creation from alerts
  - Subscriber notes during outages
  - Inventory item updates (IP, firmware, serial)
  """

  alias Towerops.Gaiia.Client
  alias Towerops.Integrations

  require Logger

  @doc """
  Create a Gaiia ticket for an alert.

  Returns `{:ok, ticket_id}` on success, or `{:error, reason}`.
  """
  def create_ticket_for_alert(organization_id, alert) do
    with {:ok, api_key} <- get_api_key(organization_id) do
      subject = "Device Down: #{alert.device.name}"

      description =
        "Alert: #{alert.message}\nTriggered: #{DateTime.to_iso8601(alert.triggered_at)}"

      variables = %{
        "subject" => subject,
        "description" => description
      }

      case Client.create_ticket(api_key, variables) do
        {:ok, %{"createExternalTicket" => %{"id" => ticket_id}}} ->
          {:ok, ticket_id}

        {:error, reason} ->
          Logger.warning("Failed to create Gaiia ticket for alert #{alert.id}: #{inspect(reason)}")
          {:error, reason}
      end
    end
  end

  @doc """
  Create a note on a Gaiia account (e.g., during an outage).

  Returns `{:ok, note_id}` on success, or `{:error, reason}`.
  """
  def create_subscriber_note(organization_id, account_gaiia_id, content) do
    with {:ok, api_key} <- get_api_key(organization_id) do
      case Client.create_note(api_key, "ACCOUNT", account_gaiia_id, content) do
        {:ok, %{"createNote" => %{"id" => note_id}}} ->
          {:ok, note_id}

        {:error, reason} ->
          Logger.warning("Failed to create Gaiia note for account #{account_gaiia_id}: #{inspect(reason)}")

          {:error, reason}
      end
    end
  end

  @doc """
  Update a Gaiia inventory item with field changes.

  Accepts a map of fields to update (e.g., `%{ip_address: "10.0.0.5"}`).
  Returns `{:ok, data}` on success, or `{:error, reason}`.
  """
  def update_inventory_item(organization_id, item_gaiia_id, fields) do
    with {:ok, api_key} <- get_api_key(organization_id) do
      input = build_inventory_input(fields)

      case Client.update_inventory_item(api_key, item_gaiia_id, input) do
        {:ok, %{"updateInventoryItem" => data}} ->
          {:ok, data}

        {:error, reason} ->
          Logger.warning("Failed to update Gaiia inventory item #{item_gaiia_id}: #{inspect(reason)}")

          {:error, reason}
      end
    end
  end

  defp get_api_key(organization_id) do
    case Integrations.get_integration(organization_id, "gaiia") do
      {:ok, %{credentials: %{"api_key" => api_key}}} when is_binary(api_key) ->
        {:ok, api_key}

      _ ->
        {:error, :no_integration}
    end
  end

  defp build_inventory_input(fields) do
    Enum.reduce(fields, %{}, fn
      {:ip_address, value}, acc -> Map.put(acc, "ipAddress", value)
      {:serial_number, value}, acc -> Map.put(acc, "serialNumber", value)
      {:mac_address, value}, acc -> Map.put(acc, "macAddress", value)
      {key, value}, acc -> Map.put(acc, to_string(key), value)
    end)
  end
end
