defmodule BerrypodWeb.Admin.Newsletter do
  use BerrypodWeb, :live_view

  alias Berrypod.Newsletter

  @impl true
  def mount(_params, _session, socket) do
    counts = Newsletter.count_subscribers_by_status()
    sub_page = Newsletter.list_subscribers_paginated(page: 1)
    camp_page = Newsletter.list_campaigns_paginated(page: 1)

    {:ok,
     socket
     |> assign(:page_title, "Newsletter")
     |> assign(:tab, "overview")
     |> assign(:newsletter_enabled, Newsletter.newsletter_enabled?())
     |> assign(:status_counts, counts)
     |> assign(:subscriber_pagination, sub_page)
     |> assign(:subscriber_count, sub_page.total_count)
     |> assign(:campaign_pagination, camp_page)
     |> assign(:campaign_count, camp_page.total_count)
     |> assign(:status_filter, "all")
     |> assign(:search, "")
     |> stream(:subscribers, sub_page.items)
     |> stream(:campaigns, camp_page.items)}
  end

  @impl true
  def handle_params(params, _uri, socket) do
    tab =
      if params["tab"] in ~w(overview subscribers campaigns), do: params["tab"], else: "overview"

    page_num = Berrypod.Pagination.parse_page(params)

    socket = assign(socket, :tab, tab)

    socket =
      case tab do
        "subscribers" ->
          page =
            Newsletter.list_subscribers_paginated(
              status: socket.assigns.status_filter,
              search: socket.assigns.search,
              page: page_num
            )

          socket
          |> assign(:subscriber_pagination, page)
          |> assign(:subscriber_count, page.total_count)
          |> stream(:subscribers, page.items, reset: true)

        "campaigns" ->
          page = Newsletter.list_campaigns_paginated(page: page_num)

          socket
          |> assign(:campaign_pagination, page)
          |> assign(:campaign_count, page.total_count)
          |> stream(:campaigns, page.items, reset: true)

        _ ->
          socket
      end

    {:noreply, socket}
  end

  @impl true
  def handle_event("toggle_enabled", _params, socket) do
    new_value = !socket.assigns.newsletter_enabled
    Newsletter.set_newsletter_enabled(new_value)

    msg = if new_value, do: "Newsletter signups enabled", else: "Newsletter signups disabled"

    {:noreply,
     socket
     |> assign(:newsletter_enabled, new_value)
     |> put_flash(:info, msg)}
  end

  def handle_event("filter_subscribers", %{"status" => status}, socket) do
    {:noreply,
     socket
     |> assign(:status_filter, status)
     |> push_patch(to: ~p"/admin/newsletter?tab=subscribers")}
  end

  def handle_event("search_subscribers", %{"search" => term}, socket) do
    {:noreply,
     socket
     |> assign(:search, term)
     |> push_patch(to: ~p"/admin/newsletter?tab=subscribers")}
  end

  def handle_event("delete_subscriber", %{"id" => id}, socket) do
    sub = Newsletter.get_subscriber!(id)
    {:ok, _} = Newsletter.delete_subscriber(sub)

    counts = Newsletter.count_subscribers_by_status()

    {:noreply,
     socket
     |> assign(:status_counts, counts)
     |> assign(:subscriber_count, socket.assigns.subscriber_count - 1)
     |> stream_delete(:subscribers, sub)
     |> put_flash(:info, "Subscriber deleted")}
  end

  def handle_event("delete_campaign", %{"id" => id}, socket) do
    campaign = Newsletter.get_campaign!(id)

    case Newsletter.delete_campaign(campaign) do
      {:ok, _} ->
        {:noreply,
         socket
         |> assign(:campaign_count, socket.assigns.campaign_count - 1)
         |> stream_delete(:campaigns, campaign)
         |> put_flash(:info, "Campaign deleted")}

      {:error, :not_draft} ->
        {:noreply, put_flash(socket, :error, "Only draft campaigns can be deleted")}
    end
  end

  @impl true
  def render(assigns) do
    ~H"""
    <.header>
      Newsletter
      <:subtitle>Manage subscribers and email campaigns</:subtitle>
    </.header>

    <div class="admin-tabs">
      <.tab_link label="Overview" tab="overview" active={@tab} />
      <.tab_link
        label="Subscribers"
        tab="subscribers"
        active={@tab}
        count={total_subs(@status_counts)}
      />
      <.tab_link label="Campaigns" tab="campaigns" active={@tab} count={@campaign_count} />
    </div>

    <div :if={@tab == "overview"}>
      <.overview_tab
        newsletter_enabled={@newsletter_enabled}
        status_counts={@status_counts}
      />
    </div>

    <div :if={@tab == "subscribers"}>
      <.subscribers_tab
        streams={@streams}
        status_filter={@status_filter}
        status_counts={@status_counts}
        subscriber_count={@subscriber_count}
        subscriber_pagination={@subscriber_pagination}
        search={@search}
      />
    </div>

    <div :if={@tab == "campaigns"}>
      <.campaigns_tab
        streams={@streams}
        campaign_count={@campaign_count}
        campaign_pagination={@campaign_pagination}
      />
    </div>
    """
  end

  # ── Tab navigation ──────────────────────────────────────────────

  attr :label, :string, required: true
  attr :tab, :string, required: true
  attr :active, :string, required: true
  attr :count, :integer, default: nil

  defp tab_link(assigns) do
    ~H"""
    <.link
      patch={~p"/admin/newsletter?tab=#{@tab}"}
      class={["admin-tab", @tab == @active && "admin-tab-active"]}
    >
      {@label}
      <span :if={@count} class="admin-tab-count">{@count}</span>
    </.link>
    """
  end

  # ── Overview tab ────────────────────────────────────────────────

  attr :newsletter_enabled, :boolean, required: true
  attr :status_counts, :map, required: true

  defp overview_tab(assigns) do
    ~H"""
    <div class="admin-stack admin-stack-lg">
      <div class="admin-card">
        <div class="admin-card-body admin-row admin-row-xl">
          <div class="admin-input-fill">
            <h3 class="admin-text-medium">Newsletter signups</h3>
            <p class="admin-section-desc">
              When enabled, the newsletter signup block on your shop pages will collect email addresses with double opt-in confirmation.
            </p>
          </div>
          <button
            phx-click="toggle_enabled"
            class={[
              "admin-switch",
              if(@newsletter_enabled, do: "admin-switch-on", else: "admin-switch-off")
            ]}
            role="switch"
            aria-checked={to_string(@newsletter_enabled)}
            aria-label="Toggle newsletter signups"
          >
            <span class={["admin-switch-thumb", @newsletter_enabled && "admin-switch-thumb-on"]} />
          </button>
        </div>
      </div>

      <div class="admin-stats-grid">
        <div class="admin-stat-card">
          <p class="admin-stat-value">{@status_counts["confirmed"] || 0}</p>
          <p class="admin-stat-label">Confirmed</p>
        </div>
        <div class="admin-stat-card">
          <p class="admin-stat-value">{@status_counts["pending"] || 0}</p>
          <p class="admin-stat-label">Pending</p>
        </div>
        <div class="admin-stat-card">
          <p class="admin-stat-value">{@status_counts["unsubscribed"] || 0}</p>
          <p class="admin-stat-label">Unsubscribed</p>
        </div>
      </div>

      <div class="admin-row admin-row-lg">
        <.link
          navigate={~p"/admin/newsletter?tab=subscribers"}
          class="admin-link admin-text-medium"
        >
          View subscribers
        </.link>
        <.link
          navigate={~p"/admin/newsletter?tab=campaigns"}
          class="admin-link admin-text-medium"
        >
          View campaigns
        </.link>
      </div>
    </div>
    """
  end

  # ── Subscribers tab ─────────────────────────────────────────────

  attr :streams, :any, required: true
  attr :status_filter, :string, required: true
  attr :status_counts, :map, required: true
  attr :subscriber_count, :integer, required: true
  attr :subscriber_pagination, Berrypod.Pagination, required: true
  attr :search, :string, required: true

  defp subscribers_tab(assigns) do
    ~H"""
    <div>
      <div class="admin-filter-row admin-filter-row-between">
        <div class="admin-cluster">
          <.filter_pill
            status="all"
            label="All"
            count={total_subs(@status_counts)}
            active={@status_filter}
          />
          <.filter_pill
            status="confirmed"
            label="Confirmed"
            count={@status_counts["confirmed"]}
            active={@status_filter}
          />
          <.filter_pill
            status="pending"
            label="Pending"
            count={@status_counts["pending"]}
            active={@status_filter}
          />
          <.filter_pill
            status="unsubscribed"
            label="Unsubscribed"
            count={@status_counts["unsubscribed"]}
            active={@status_filter}
          />
        </div>
        <.link href={~p"/admin/newsletter/export"} class="admin-btn admin-btn-sm admin-btn-ghost">
          <.icon name="hero-arrow-down-tray" class="size-4" /> Export CSV
        </.link>
      </div>

      <form phx-change="search_subscribers" class="admin-filter-row">
        <.input
          name="search"
          value={@search}
          type="search"
          placeholder="Search by email..."
          phx-debounce="300"
        />
      </form>

      <.table
        :if={@subscriber_count > 0}
        id="subscribers"
        rows={@streams.subscribers}
        row_item={fn {_id, sub} -> sub end}
      >
        <:col :let={sub} label="Email">{sub.email}</:col>
        <:col :let={sub} label="Status"><.subscriber_status status={sub.status} /></:col>
        <:col :let={sub} label="Subscribed">{format_date(sub.inserted_at)}</:col>
        <:col :let={sub} label="Source">{sub.source}</:col>
        <:action :let={sub}>
          <button
            phx-click="delete_subscriber"
            phx-value-id={sub.id}
            data-confirm="Permanently delete this subscriber? This cannot be undone."
            class="admin-link-danger"
          >
            Delete
          </button>
        </:action>
      </.table>

      <.admin_pagination
        :if={@subscriber_count > 0}
        page={@subscriber_pagination}
        patch={~p"/admin/newsletter"}
        params={%{"tab" => "subscribers"}}
      />

      <div :if={@subscriber_count == 0} class="admin-empty-state">
        <.icon name="hero-envelope" class="admin-empty-state-icon" />
        <p class="admin-empty-state-title">No subscribers yet</p>
        <p class="admin-empty-state-text">
          Subscribers will appear here when people sign up via your shop.
        </p>
      </div>
    </div>
    """
  end

  # ── Campaigns tab ───────────────────────────────────────────────

  attr :streams, :any, required: true
  attr :campaign_count, :integer, required: true
  attr :campaign_pagination, Berrypod.Pagination, required: true

  defp campaigns_tab(assigns) do
    ~H"""
    <div>
      <div class="admin-tab-actions">
        <.link navigate={~p"/admin/newsletter/campaigns/new"} class="admin-btn admin-btn-primary">
          <.icon name="hero-plus" class="size-4" /> New campaign
        </.link>
      </div>

      <.table
        :if={@campaign_count > 0}
        id="campaigns"
        rows={@streams.campaigns}
        row_item={fn {_id, c} -> c end}
        row_click={fn {_id, c} -> JS.navigate(~p"/admin/newsletter/campaigns/#{c.id}") end}
      >
        <:col :let={c} label="Subject">{c.subject}</:col>
        <:col :let={c} label="Status"><.campaign_status status={c.status} /></:col>
        <:col :let={c} label="Sent">{c.sent_count}</:col>
        <:col :let={c} label="Created">{format_date(c.inserted_at)}</:col>
        <:action :let={c}>
          <button
            :if={c.status == "draft"}
            phx-click="delete_campaign"
            phx-value-id={c.id}
            data-confirm="Delete this draft campaign?"
            class="admin-link-danger"
          >
            Delete
          </button>
        </:action>
      </.table>

      <.admin_pagination
        :if={@campaign_count > 0}
        page={@campaign_pagination}
        patch={~p"/admin/newsletter"}
        params={%{"tab" => "campaigns"}}
      />

      <div :if={@campaign_count == 0} class="admin-empty-state">
        <.icon name="hero-megaphone" class="admin-empty-state-icon" />
        <p class="admin-empty-state-title">No campaigns yet</p>
        <p class="admin-empty-state-text">Create your first campaign to reach your subscribers.</p>
      </div>
    </div>
    """
  end

  # ── Components ──────────────────────────────────────────────────

  attr :status, :string, required: true
  attr :label, :string, required: true
  attr :count, :integer, default: nil
  attr :active, :string, required: true

  defp filter_pill(assigns) do
    count = assigns[:count] || 0
    active = assigns.status == assigns.active

    assigns = assign(assigns, count: count, active: active)

    ~H"""
    <button
      phx-click="filter_subscribers"
      phx-value-status={@status}
      class={[
        "admin-btn admin-btn-sm",
        @active && "admin-btn-primary",
        !@active && "admin-btn-ghost"
      ]}
    >
      {@label}
      <span :if={@count > 0} class="admin-badge admin-badge-sm admin-badge-count">
        {@count}
      </span>
    </button>
    """
  end

  attr :status, :string, required: true

  defp subscriber_status(%{status: "confirmed"} = assigns) do
    ~H"""
    <span class="admin-status-dot admin-status-dot-green">Confirmed</span>
    """
  end

  defp subscriber_status(%{status: "pending"} = assigns) do
    ~H"""
    <span class="admin-status-dot admin-status-dot-amber">Pending</span>
    """
  end

  defp subscriber_status(%{status: "unsubscribed"} = assigns) do
    ~H"""
    <span class="admin-status-dot admin-status-dot-muted">Unsubscribed</span>
    """
  end

  defp subscriber_status(assigns) do
    ~H"""
    <span class="admin-status-dot admin-status-dot-muted">{@status}</span>
    """
  end

  attr :status, :string, required: true

  defp campaign_status(%{status: "draft"} = assigns) do
    ~H"""
    <span class="admin-status-dot admin-status-dot-muted">Draft</span>
    """
  end

  defp campaign_status(%{status: "scheduled"} = assigns) do
    ~H"""
    <span class="admin-status-dot admin-status-dot-blue">Scheduled</span>
    """
  end

  defp campaign_status(%{status: "sending"} = assigns) do
    ~H"""
    <span class="admin-status-dot admin-status-dot-amber">Sending</span>
    """
  end

  defp campaign_status(%{status: "sent"} = assigns) do
    ~H"""
    <span class="admin-status-dot admin-status-dot-green">Sent</span>
    """
  end

  defp campaign_status(%{status: "cancelled"} = assigns) do
    ~H"""
    <span class="admin-status-dot admin-status-dot-red">Cancelled</span>
    """
  end

  defp campaign_status(assigns) do
    ~H"""
    <span class="admin-status-dot admin-status-dot-muted">{@status}</span>
    """
  end

  # ── Helpers ─────────────────────────────────────────────────────

  defp total_subs(counts) do
    Enum.reduce(counts, 0, fn {_status, count}, acc -> acc + count end)
  end

  defp format_date(nil), do: "—"

  defp format_date(datetime) do
    Calendar.strftime(datetime, "%-d %b %Y")
  end
end
