defmodule MicrowavepropWeb.Admin.ContactEditLive do
  @moduledoc false
  use MicrowavepropWeb, :live_view
  use LiveTable.LiveResource, schema: Microwaveprop.Radio.ContactEdit

  alias Microwaveprop.Radio
  alias Microwaveprop.Radio.EditNotifier

  def table_options do
    %{exports: %{formats: [:csv]}}
  end

  def fields do
    [
      id: %{label: "ID", hidden: true},
      contact_id: %{label: "Contact", renderer: &contact_cell/2},
      user_id: %{label: "Submitted By", renderer: &user_cell/2},
      proposed_changes: %{label: "Fields Changed", renderer: &changed_fields_cell/1},
      inserted_at: %{label: "Submitted", sortable: true, renderer: &format_ts/1}
    ]
  end

  def filters, do: []

  def actions do
    [
      review: fn %{record: edit} ->
        assigns = %{edit: edit}

        ~H"""
        <button
          phx-click="review"
          phx-value-id={@edit.id}
          class="btn btn-primary btn-xs"
        >
          Review
        </button>
        """
      end
    ]
  end

  @impl true
  def mount(_params, _session, socket) do
    {:ok,
     socket
     |> assign(:page_title, "Review Contact Edits")
     |> assign(:reviewing, nil)
     |> assign(:admin_note, "")
     |> assign(:pending_count, Radio.pending_edit_count())
     |> assign(:flagged_contacts, Radio.list_flagged_contacts())
     |> assign(:data_provider, {Radio, :pending_edits_query, []})}
  end

  @impl true
  def handle_event("review", %{"id" => id}, socket) do
    edit = Radio.get_contact_edit!(id)
    {:noreply, assign(socket, reviewing: edit, admin_note: "")}
  end

  def handle_event("cancel_review", _params, socket) do
    {:noreply, assign(socket, reviewing: nil, admin_note: "")}
  end

  def handle_event("update_note", %{"note" => note}, socket) do
    {:noreply, assign(socket, admin_note: note)}
  end

  def handle_event("approve", _params, socket) do
    edit = socket.assigns.reviewing
    admin = socket.assigns.current_scope.user
    note = normalize_note(socket.assigns.admin_note)

    case Radio.approve_edit(edit, admin, note) do
      {:ok, approved} ->
        EditNotifier.deliver_edit_approved(approved)

        {:noreply,
         socket
         |> assign(reviewing: nil, admin_note: "", pending_count: Radio.pending_edit_count())
         |> put_flash(:info, "Edit approved and applied.")
         |> push_patch(to: "/" <> (socket.assigns[:current_path] || "admin/contact-edits"))}

      {:error, _} ->
        {:noreply, put_flash(socket, :error, "Failed to approve edit.")}
    end
  end

  def handle_event("reject", _params, socket) do
    edit = socket.assigns.reviewing
    admin = socket.assigns.current_scope.user
    note = normalize_note(socket.assigns.admin_note)

    case Radio.reject_edit(edit, admin, note) do
      {:ok, rejected} ->
        EditNotifier.deliver_edit_rejected(rejected)

        {:noreply,
         socket
         |> assign(reviewing: nil, admin_note: "", pending_count: Radio.pending_edit_count())
         |> put_flash(:info, "Edit rejected.")
         |> push_patch(to: "/" <> (socket.assigns[:current_path] || "admin/contact-edits"))}

      {:error, _} ->
        {:noreply, put_flash(socket, :error, "Failed to reject edit.")}
    end
  end

  defp normalize_note(""), do: nil
  defp normalize_note(note), do: String.trim(note)

  defp format_band(nil), do: "?"

  defp format_band(band) do
    mhz = Decimal.to_integer(band)
    if mhz >= 1000, do: "#{div(mhz, 1000)} GHz", else: "#{mhz} MHz"
  end

  defp format_ts(nil), do: "?"
  defp format_ts(ts), do: Calendar.strftime(ts, "%Y-%m-%d %H:%M UTC")

  defp changed_fields_summary(proposed_changes) do
    proposed_changes
    |> Map.keys()
    |> Enum.sort()
    |> Enum.join(", ")
  end

  defp field_label("station1"), do: "Station 1"
  defp field_label("station2"), do: "Station 2"
  defp field_label("grid1"), do: "Grid 1"
  defp field_label("grid2"), do: "Grid 2"
  defp field_label("band"), do: "Band"
  defp field_label("mode"), do: "Mode"
  defp field_label("qso_timestamp"), do: "Timestamp"
  defp field_label(other), do: other

  defp current_value(contact, "station1"), do: contact.station1
  defp current_value(contact, "station2"), do: contact.station2
  defp current_value(contact, "grid1"), do: contact.grid1
  defp current_value(contact, "grid2"), do: contact.grid2
  defp current_value(contact, "band"), do: if(contact.band, do: Decimal.to_string(contact.band))
  defp current_value(contact, "mode"), do: contact.mode

  defp current_value(contact, "qso_timestamp"), do: if(contact.qso_timestamp, do: format_ts(contact.qso_timestamp))

  defp current_value(_contact, _), do: "?"

  defp format_proposed("band", val), do: to_string(val)
  defp format_proposed("qso_timestamp", val) when is_binary(val), do: val
  defp format_proposed(_field, val), do: to_string(val)

  defp contact_cell(_value, %{contact: contact}) when not is_nil(contact) do
    assigns = %{contact: contact}

    ~H"""
    <.link navigate={~p"/contacts/#{@contact.id}"} class="link link-primary">
      {@contact.station1} / {@contact.station2}
    </.link>
    <div class="text-xs opacity-60">{format_band(@contact.band)}</div>
    """
  end

  defp contact_cell(_value, _record), do: "—"

  defp user_cell(_value, %{user: %{callsign: callsign}}), do: callsign
  defp user_cell(_value, _record), do: "—"

  defp changed_fields_cell(changes) when is_map(changes), do: changed_fields_summary(changes)
  defp changed_fields_cell(_), do: "—"

  @impl true
  def render(assigns) do
    ~H"""
    <Layouts.app flash={@flash} current_scope={@current_scope}>
      <.header>
        Review Contact Edits
        <:subtitle>{@pending_count} pending</:subtitle>
        <:actions>
          <.link navigate={~p"/status"} class="btn btn-sm btn-ghost">
            <.icon name="hero-arrow-left" class="w-4 h-4" /> Status
          </.link>
        </:actions>
      </.header>

      <%= if @reviewing do %>
        <div class="bg-base-200 rounded-box p-6 mb-6">
          <div class="flex items-center justify-between mb-4">
            <h3 class="font-semibold text-lg">
              Review Edit from {@reviewing.user.callsign}
            </h3>
            <button phx-click="cancel_review" class="btn btn-ghost btn-sm">
              <.icon name="hero-x-mark" class="w-4 h-4" /> Close
            </button>
          </div>

          <div class="text-sm opacity-70 mb-4">
            Contact:
            <.link navigate={~p"/contacts/#{@reviewing.contact.id}"} class="link link-primary">
              {@reviewing.contact.station1} / {@reviewing.contact.station2}
            </.link>
            &middot; {format_band(@reviewing.contact.band)} &middot; {format_ts(
              @reviewing.contact.qso_timestamp
            )}
          </div>

          <div class="overflow-x-auto rounded-box border border-base-300 mb-4">
            <table class="table table-sm">
              <thead>
                <tr>
                  <th>Field</th>
                  <th>Current</th>
                  <th>Proposed</th>
                </tr>
              </thead>
              <tbody>
                <%= for {field, proposed_val} <- Enum.sort(@reviewing.proposed_changes) do %>
                  <tr>
                    <td class="font-semibold">{field_label(field)}</td>
                    <td class="opacity-70">{current_value(@reviewing.contact, field)}</td>
                    <td class="text-primary font-semibold">{format_proposed(field, proposed_val)}</td>
                  </tr>
                <% end %>
              </tbody>
            </table>
          </div>

          <div class="mb-4">
            <label class="label text-sm">Note (optional)</label>
            <textarea
              class="textarea textarea-bordered w-full"
              rows="2"
              placeholder="Reason for decision..."
              phx-change="update_note"
              name="note"
            >{@admin_note}</textarea>
          </div>

          <div class="flex gap-2">
            <button phx-click="approve" class="btn btn-success btn-sm">
              <.icon name="hero-check" class="w-4 h-4" /> Approve
            </button>
            <button phx-click="reject" class="btn btn-error btn-sm">
              <.icon name="hero-x-mark" class="w-4 h-4" /> Reject
            </button>
          </div>
        </div>
      <% end %>

      <.live_table
        fields={fields()}
        filters={filters()}
        options={@options}
        streams={@streams}
        actions={actions()}
      />

      <%= if @flagged_contacts != [] do %>
        <div class="mt-10">
          <h2 class="text-lg font-semibold mb-2">
            Flagged contacts <span class="text-sm opacity-60">({length(@flagged_contacts)})</span>
          </h2>
          <div class="overflow-x-auto rounded-box border border-base-300">
            <table class="table table-sm">
              <thead>
                <tr>
                  <th>Stations</th>
                  <th>Band</th>
                  <th>QSO (UTC)</th>
                  <th>Added (UTC)</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                <%= for c <- @flagged_contacts do %>
                  <tr>
                    <td class="font-semibold">{c.station1} / {c.station2}</td>
                    <td>{format_band(c.band)}</td>
                    <td class="opacity-70">{format_ts(c.qso_timestamp)}</td>
                    <td class="opacity-70">{format_ts(c.inserted_at)}</td>
                    <td>
                      <.link navigate={~p"/contacts/#{c.id}"} class="btn btn-xs btn-ghost">
                        View
                      </.link>
                    </td>
                  </tr>
                <% end %>
              </tbody>
            </table>
          </div>
        </div>
      <% end %>
    </Layouts.app>
    """
  end
end
