defmodule MicrowavepropWeb.LiveTableResource do
  @moduledoc """
  Thin wrapper around `LiveTable.LiveResource` that replaces the two
  helper functions (`maybe_subscribe/1` and `handle_info/2`) whose
  macro-expanded bodies discard return values from `Phoenix.PubSub.subscribe/2`,
  `File.mkdir_p!/1`, `File.cp!/2`, `File.rm/1`, and `Process.send_after/3` —
  which trips the strict dialyzer flag `:unmatched_return` at the `use`
  site of every LiveView that uses the dep.

  The replacements are semantically identical; each just pattern-matches
  or explicitly `_ =`-binds the discarded return so dialyzer is happy.
  No functional change.

  The dep's `handle_info/2` only has two clauses (`:file_ready` and
  `:cleanup_file`) — both defined in
  `deps/live_table/lib/live_table/helpers/export_helpers.ex`. Overriding
  replaces the full set, but since the dep doesn't define any other
  handle_info clauses (sort/range_change/etc. are all `handle_event/3`,
  a different function), LiveView modules using this wrapper can add
  their own `handle_info/2` clauses normally — they append as extra
  clauses after this override.

  Upstream fix opportunity: submit a PR to
  https://github.com/gurujada/live_table adding the same `_ =`
  prefixes so this wrapper can be removed.
  """

  defmacro __using__(opts) do
    quote location: :keep do
      use LiveTable.LiveResource, unquote(opts)

      defoverridable maybe_subscribe: 1, handle_info: 2

      defp maybe_subscribe(socket) do
        case socket.assigns[:export_topic] do
          nil ->
            client_id = Ecto.UUID.generate()
            export_topic = "exports:#{client_id}"
            updated_socket = assign(socket, export_topic: export_topic)

            if connected?(socket) do
              :ok =
                Phoenix.PubSub.subscribe(
                  Application.fetch_env!(:live_table, :pubsub),
                  export_topic
                )
            end

            {export_topic, updated_socket}

          export_topic ->
            {export_topic, socket}
        end
      end

      @impl true
      def handle_info({:file_ready, file_path}, socket) do
        app_name = Application.fetch_env!(:live_table, :app)
        static_path = Path.join([:code.priv_dir(app_name), "static", "exports"])
        File.mkdir_p!(static_path)

        filename = Path.basename(file_path)
        dest_path = Path.join(static_path, filename)
        File.cp!(file_path, dest_path)

        updated_socket =
          socket
          |> push_event("download", %{path: "/exports/#{filename}"})
          |> put_flash(:info, "File downloaded successfully.")

        _timer_ref =
          Process.send_after(self(), {:cleanup_file, dest_path}, to_timeout(second: 20))

        _rm_result = File.rm(file_path)
        {:noreply, updated_socket}
      end

      def handle_info({:cleanup_file, file_path}, socket) do
        _rm_result = File.rm(file_path)
        {:noreply, socket}
      end
    end
  end
end
