defmodule BDS.Desktop.ShellLive.SidebarDelete do
  @moduledoc false

  import Phoenix.Component, only: [assign: 3]

  alias BDS.{AI, ImportDefinitions, Media, Posts, Scripts, Templates}
  use Gettext, backend: BDS.Gettext

  @spec request_delete(
          Phoenix.LiveView.Socket.t(),
          String.t(),
          String.t(),
          String.t() | nil,
          map()
        ) ::
          Phoenix.LiveView.Socket.t()
  def request_delete(socket, route, id, fallback_title, callbacks) do
    case delete_target(socket, route, id, fallback_title) do
      {:ok, entity_name} ->
        assign(socket, :shell_overlay, %{
          kind: :confirm_delete,
          title: delete_title(route),
          entity_name: entity_name,
          entity_type: route,
          reference_count: 0,
          reference_list: [],
          delete_action: %{source: :sidebar, route: route, id: id}
        })

      {:error, reason} ->
        socket
        |> assign(:shell_overlay, nil)
        |> callbacks.append_output.(delete_title(route), inspect(reason), nil, "error")
        |> callbacks.refresh_content.(socket.assigns.workbench)
    end
  end

  @spec execute_delete(Phoenix.LiveView.Socket.t(), String.t(), String.t(), map()) ::
          Phoenix.LiveView.Socket.t()
  def execute_delete(socket, route, id, callbacks) do
    case route do
      "post" ->
        delete_entity(socket, :post, id, &Posts.delete_post/1, callbacks)

      "media" ->
        delete_entity(socket, :media, id, &Media.delete_media/1, callbacks)

      "scripts" ->
        delete_entity(socket, :scripts, id, &Scripts.delete_script/1, callbacks)

      "templates" ->
        delete_entity(
          socket,
          :templates,
          id,
          fn tid ->
            Templates.delete_template(tid, force: true)
          end,
          callbacks
        )

      "chat" ->
        delete_entity(socket, :chat, id, &AI.delete_chat_conversation/1, callbacks)

      "import" ->
        delete_entity(socket, :import, id, &ImportDefinitions.delete_definition/1, callbacks)

      _other ->
        socket
        |> assign(:shell_overlay, nil)
        |> callbacks.append_output.(
          dgettext("ui", "Delete"),
          inspect(:unsupported_route),
          nil,
          "error"
        )
        |> callbacks.refresh_content.(socket.assigns.workbench)
    end
  end

  # ── Private helpers ────────────────────────────────────────────────────────

  defp delete_entity(socket, type, id, delete_fn, callbacks) do
    case delete_fn.(id) do
      {:ok, :deleted} ->
        workbench = BDS.UI.Workbench.close_tab(socket.assigns.workbench, type, id)

        socket
        |> assign(:shell_overlay, nil)
        |> assign(:tab_meta, Map.delete(socket.assigns.tab_meta, {type, id}))
        |> callbacks.refresh_content.(workbench)

      {:error, reason} ->
        socket
        |> assign(:shell_overlay, nil)
        |> callbacks.append_output.(
          delete_title(Atom.to_string(type)),
          inspect(reason),
          nil,
          "error"
        )
        |> callbacks.refresh_content.(socket.assigns.workbench)
    end
  end

  @spec delete_target(Phoenix.LiveView.Socket.t(), String.t(), String.t(), String.t() | nil) ::
          {:ok, String.t()} | {:error, atom()}
  defp delete_target(socket, route, id, fallback_title) do
    active_project_id = socket.assigns.projects.active_project_id

    case route do
      "post" ->
        case Posts.get_post(id) do
          %{project_id: ^active_project_id} = post ->
            {:ok,
             present_title(fallback_title) || present_title(post.title) ||
               present_title(post.slug) || id}

          _other ->
            {:error, :not_found}
        end

      "media" ->
        case Media.get_media(id) do
          %{project_id: ^active_project_id} = media ->
            {:ok,
             present_title(fallback_title) || present_title(media.title) ||
               present_title(media.original_name) || id}

          _other ->
            {:error, :not_found}
        end

      "scripts" ->
        case Scripts.get_script(id) do
          %{project_id: ^active_project_id} = script ->
            {:ok, present_title(fallback_title) || present_title(script.title) || id}

          _other ->
            {:error, :not_found}
        end

      "templates" ->
        case Templates.get_template(id) do
          %{project_id: ^active_project_id} = template ->
            {:ok, present_title(fallback_title) || present_title(template.title) || id}

          _other ->
            {:error, :not_found}
        end

      "chat" ->
        case AI.get_chat_conversation(id) do
          %{title: title} -> {:ok, present_title(fallback_title) || present_title(title) || id}
          _other -> {:error, :not_found}
        end

      "import" ->
        case ImportDefinitions.get_definition(id) do
          %{project_id: ^active_project_id} = definition ->
            {:ok, present_title(fallback_title) || present_title(definition.name) || id}

          _other ->
            {:error, :not_found}
        end

      _other ->
        {:error, :unsupported_route}
    end
  end

  @spec delete_title(String.t()) :: String.t()
  defp delete_title("chat"), do: dgettext("ui", "Delete conversation")
  defp delete_title("post"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Post")
  defp delete_title("media"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Media")
  defp delete_title("scripts"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Script")

  defp delete_title("templates"),
    do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Template")

  defp delete_title("import"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Import")
  defp delete_title(_route), do: dgettext("ui", "Delete")

  @spec present_title(String.t() | nil) :: String.t() | nil
  defp present_title(value) when is_binary(value) do
    case String.trim(value) do
      "" -> nil
      trimmed -> trimmed
    end
  end

  defp present_title(_value), do: nil
end
