defmodule MicrowavepropWeb.ContactLive.Index do
  @moduledoc false
  use MicrowavepropWeb, :live_view
  use LiveTable.LiveResource, schema: Microwaveprop.Radio.Contact

  alias Microwaveprop.Radio.Contact
  alias Microwaveprop.Repo

  def table_options do
    %{
      sorting: %{default_sort: [inserted_at: :desc]},
      exports: %{formats: [:csv]}
    }
  end

  def fields do
    [
      id: %{label: "ID", hidden: true},
      station1: %{label: "Station 1", sortable: true, searchable: true},
      grid1: %{label: "Grid 1", sortable: true, searchable: true},
      station2: %{label: "Station 2", sortable: true, searchable: true},
      grid2: %{label: "Grid 2", sortable: true, searchable: true},
      band: %{label: "Band", sortable: true, renderer: &band_cell/1},
      mode: %{label: "Mode", sortable: true, searchable: true},
      distance_km: %{label: "Distance (km)", sortable: true},
      hrrr_status: %{label: "Enriched", renderer: &enrichment_cell/2},
      flagged_invalid: %{label: "Flag", renderer: &flag_cell/1},
      qso_timestamp: %{label: "QSO (UTC)", sortable: true, renderer: &format_ts/1},
      inserted_at: %{label: "Added (UTC)", sortable: true, renderer: &format_ts/1}
    ]
  end

  def filters, do: []

  def actions do
    [
      view: fn %{record: contact} ->
        assigns = %{contact: contact}

        ~H"""
        <.link navigate={~p"/contacts/#{@contact.id}"} class="btn btn-xs btn-ghost">
          View
        </.link>
        """
      end
    ]
  end

  @impl true
  def mount(_params, _session, socket) do
    total = Repo.aggregate(Contact, :count, :id)

    {:ok,
     socket
     |> assign(:page_title, "Contacts")
     |> assign(:total_contacts, total)}
  end

  @enrichment_fields [
    {:hrrr_status, "HRRR"},
    {:weather_status, "Weather"},
    {:terrain_status, "Terrain"},
    {:iemre_status, "IEMRE"}
  ]
  @done_statuses [:complete, :unavailable]

  defp enrichment_cell(_value, contact) do
    details =
      Enum.map(@enrichment_fields, fn {field, name} ->
        {name, Map.get(contact, field)}
      end)

    done = Enum.count(details, fn {_, s} -> s in @done_statuses end)
    failed = Enum.count(details, fn {_, s} -> s == :failed end)

    {label, class} =
      cond do
        done == 4 -> {"Complete", "badge-success"}
        failed > 0 -> {"Failed", "badge-error"}
        done > 0 -> {"Partial", "badge-warning"}
        true -> {"Pending", "badge-ghost"}
      end

    tooltip = Enum.map_join(details, ", ", fn {name, status} -> "#{name}: #{status}" end)

    assigns = %{label: label, class: class, tooltip: tooltip}

    ~H"""
    <span class={["badge badge-xs", @class]} title={@tooltip}>{@label}</span>
    """
  end

  defp band_cell(nil), do: ""
  defp band_cell(%Decimal{} = d), do: Decimal.to_string(d, :normal)
  defp band_cell(other), do: to_string(other)

  defp flag_cell(true) do
    assigns = %{}

    ~H"""
    <span class="text-error">!</span>
    """
  end

  defp flag_cell(_), do: ""

  defp format_count(n) when is_integer(n) do
    n
    |> Integer.to_string()
    |> String.reverse()
    |> String.replace(~r/(\d{3})(?=\d)/, "\\1,")
    |> String.reverse()
  end

  defp format_ts(nil), do: ""
  defp format_ts(%DateTime{} = dt), do: Calendar.strftime(dt, "%Y-%m-%d %H:%M")
  defp format_ts(%NaiveDateTime{} = dt), do: Calendar.strftime(dt, "%Y-%m-%d %H:%M")
  defp format_ts(other), do: to_string(other)

  @impl true
  def render(assigns) do
    ~H"""
    <Layouts.app flash={@flash} current_scope={@current_scope} max_width="max-w-7xl">
      <.header>
        Contacts
        <:subtitle>
          {format_count(@total_contacts)} total — sort or search by callsign, grid, or mode.
        </:subtitle>
        <:actions>
          <.link navigate={~p"/submit"} class="btn btn-primary">
            <.icon name="hero-plus" class="w-5 h-5" /> Submit Contact
          </.link>
        </:actions>
      </.header>

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