defmodule ToweropsWeb.EquipmentLive.Form do @moduledoc false use ToweropsWeb, :live_view alias Towerops.Equipment alias Towerops.Equipment.Equipment, as: EquipmentSchema alias Towerops.Sites alias Towerops.Snmp @impl true def mount(params, _session, socket) do organization = socket.assigns.current_organization sites = Sites.list_organization_sites(organization.id) {:ok, socket |> assign(:organization, organization) |> assign(:available_sites, sites) |> assign(:preselected_site_id, params["site_id"]) |> assign(:snmp_test_result, nil)} end @impl true def handle_params(params, _url, socket) do {:noreply, apply_action(socket, socket.assigns.live_action, params)} end defp apply_action(socket, :new, _params) do equipment_attrs = %{ monitoring_enabled: true, check_interval_seconds: 300, snmp_enabled: true, snmp_version: "2c", snmp_port: 161 } equipment_attrs = if socket.assigns.preselected_site_id do Map.put(equipment_attrs, :site_id, socket.assigns.preselected_site_id) else equipment_attrs end changeset = Equipment.change_equipment(%EquipmentSchema{}, equipment_attrs) socket |> assign(:page_title, "New Equipment") |> assign(:equipment, %EquipmentSchema{}) |> assign(:form, to_form(changeset)) end defp apply_action(socket, :edit, %{"id" => id}) do equipment = Equipment.get_equipment!(id) changeset = Equipment.change_equipment(equipment) socket |> assign(:page_title, "Edit Equipment") |> assign(:equipment, equipment) |> assign(:form, to_form(changeset)) end @impl true def handle_event("validate", %{"equipment" => equipment_params}, socket) do changeset = socket.assigns.equipment |> Equipment.change_equipment(equipment_params) |> Map.put(:action, :validate) {:noreply, assign(socket, :form, to_form(changeset))} end @impl true def handle_event("save", %{"equipment" => equipment_params}, socket) do save_equipment(socket, socket.assigns.live_action, equipment_params) end @impl true def handle_event("test_snmp", _params, socket) do form_data = socket.assigns.form.data params = socket.assigns.form.params ip_address = params["ip_address"] || form_data.ip_address snmp_community = params["snmp_community"] || form_data.snmp_community snmp_version = params["snmp_version"] || form_data.snmp_version snmp_port = params["snmp_port"] || form_data.snmp_port || 161 snmp_port = case snmp_port do port when is_integer(port) -> port port when is_binary(port) -> String.to_integer(port) _ -> 161 end result = case Snmp.test_connection(ip_address, snmp_community, snmp_version, snmp_port) do {:ok, message} -> %{success: true, message: message} {:error, reason} -> %{success: false, message: "Connection failed: #{inspect(reason)}"} end {:noreply, assign(socket, :snmp_test_result, result)} end defp save_equipment(socket, :new, equipment_params) do case Equipment.create_equipment(equipment_params) do {:ok, equipment} -> # Start SNMP discovery in background if enabled flash_message = if equipment.snmp_enabled do Task.start(fn -> Snmp.discover_equipment(equipment) end) "Equipment created successfully. SNMP discovery started in background." else "Equipment created successfully" end {:noreply, socket |> put_flash(:info, flash_message) |> push_navigate(to: ~p"/orgs/#{socket.assigns.organization.slug}/equipment/#{equipment.id}")} {:error, %Ecto.Changeset{} = changeset} -> {:noreply, assign(socket, :form, to_form(changeset))} end end defp save_equipment(socket, :edit, equipment_params) do old_equipment = socket.assigns.equipment case Equipment.update_equipment(old_equipment, equipment_params) do {:ok, equipment} -> # Start SNMP discovery if SNMP was just enabled or configuration changed flash_message = if equipment.snmp_enabled and (!old_equipment.snmp_enabled or equipment.snmp_community != old_equipment.snmp_community or equipment.snmp_version != old_equipment.snmp_version or equipment.snmp_port != old_equipment.snmp_port or equipment.ip_address != old_equipment.ip_address) do Task.start(fn -> Snmp.discover_equipment(equipment) end) "Equipment updated successfully. SNMP discovery started in background." else "Equipment updated successfully" end {:noreply, socket |> put_flash(:info, flash_message) |> push_navigate(to: ~p"/orgs/#{socket.assigns.organization.slug}/equipment/#{equipment.id}")} {:error, %Ecto.Changeset{} = changeset} -> {:noreply, assign(socket, :form, to_form(changeset))} end end end