defmodule ToweropsWeb.SiteLive.Form do
  @moduledoc false
  use ToweropsWeb, :live_view

  alias Towerops.Agents
  alias Towerops.Sites
  alias Towerops.Sites.Site

  @impl true
  def mount(_params, _session, socket) do
    organization = socket.assigns.current_scope.organization

    {:ok,
     socket
     |> assign(:organization, organization)
     |> assign(:available_parent_sites, Sites.list_organization_sites(organization.id))
     |> assign(:available_agents, Agents.list_organization_agent_tokens(organization.id))}
  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
    changeset = Sites.change_site(%Site{organization_id: socket.assigns.organization.id})

    # Get inherited agent info from organization
    org_agent =
      if socket.assigns.organization.default_agent_token_id do
        Enum.find(socket.assigns.available_agents, fn a ->
          a.id == socket.assigns.organization.default_agent_token_id
        end)
      end

    socket
    |> assign(:page_title, "New Site")
    |> assign(:site, %Site{})
    |> assign(:form, to_form(changeset))
    |> assign(:org_agent, org_agent)
  end

  defp apply_action(socket, :edit, %{"id" => id}) do
    site = Sites.get_organization_site!(socket.assigns.organization.id, id)
    changeset = Sites.change_site(site)

    # Filter out the current site and its descendants from parent options
    available_parent_sites =
      Enum.reject(socket.assigns.available_parent_sites, fn s -> s.id == site.id end)

    # Get inherited agent info from organization
    org_agent =
      if socket.assigns.organization.default_agent_token_id do
        Enum.find(socket.assigns.available_agents, fn a ->
          a.id == socket.assigns.organization.default_agent_token_id
        end)
      end

    socket
    |> assign(:page_title, "Edit Site")
    |> assign(:site, site)
    |> assign(:form, to_form(changeset))
    |> assign(:available_parent_sites, available_parent_sites)
    |> assign(:org_agent, org_agent)
  end

  @impl true
  def handle_event("validate", %{"site" => site_params}, socket) do
    changeset =
      socket.assigns.site
      |> Sites.change_site(site_params)
      |> Map.put(:action, :validate)

    {:noreply, assign(socket, :form, to_form(changeset))}
  end

  @impl true
  def handle_event("save", %{"site" => site_params}, socket) do
    save_site(socket, socket.assigns.live_action, site_params)
  end

  @impl true
  def handle_event("delete", _params, socket) do
    case Sites.delete_site(socket.assigns.site) do
      {:ok, _} ->
        {:noreply,
         socket
         |> put_flash(:info, t_equipment("Site deleted successfully"))
         |> push_navigate(to: ~p"/sites")}

      {:error, _} ->
        {:noreply, put_flash(socket, :error, t_equipment("Unable to delete site"))}
    end
  end

  @impl true
  def handle_event("apply_snmp_to_all", _params, socket) do
    {count, _} = Sites.apply_snmp_config_to_all_equipment(socket.assigns.site.id)

    {:noreply,
     put_flash(
       socket,
       :info,
       t_equipment("Applied SNMP configuration to %{count} device records at this site", count: count)
     )}
  end

  @impl true
  def handle_event("apply_agent_to_all", _params, socket) do
    {count, _} = Sites.apply_agent_to_all_equipment(socket.assigns.site.id)

    {:noreply,
     put_flash(socket, :info, t_equipment("Applied agent to %{count} device records at this site", count: count))}
  end

  defp save_site(socket, :new, site_params) do
    site_params = Map.put(site_params, "organization_id", socket.assigns.organization.id)

    case Sites.create_site(site_params) do
      {:ok, site} ->
        {:noreply,
         socket
         |> put_flash(:info, t_equipment("Site created successfully! Now add your first device."))
         |> push_navigate(to: ~p"/sites/#{site.id}")}

      {:error, %Ecto.Changeset{} = changeset} ->
        {:noreply, assign(socket, :form, to_form(changeset))}
    end
  end

  defp save_site(socket, :edit, site_params) do
    case Sites.update_site(socket.assigns.site, site_params) do
      {:ok, _site} ->
        {:noreply,
         socket
         |> put_flash(:info, t_equipment("Site updated successfully"))
         |> push_navigate(to: ~p"/sites")}

      {:error, %Ecto.Changeset{} = changeset} ->
        {:noreply, assign(socket, :form, to_form(changeset))}
    end
  end
end
