lib/pgflow_dashboard/live/flows_live/show.ex

defmodule PgFlowDashboard.Live.FlowsLive.Show do
  @moduledoc """
  Flow detail page with dependency graph and run history grid.
  """

  use Phoenix.LiveView

  alias PgFlowDashboard.Components.{DependencyGraph, Layouts, RunHistoryGrid}
  alias PgFlowDashboard.Live.LiveHelpers
  alias PgFlowDashboard.Queries.Flows

  @impl true
  def mount(%{"slug" => flow_slug}, session, socket) do
    {:cont, socket} = LiveHelpers.on_mount(session, socket)

    socket =
      socket
      |> assign(:page_title, flow_slug)
      |> assign(:base_path, session["base_path"] || "/pgflow")
      |> assign(:flow_slug, flow_slug)
      |> load_flow()
      |> load_run_history()

    if socket.assigns.flow do
      socket =
        socket
        |> LiveHelpers.subscribe_to_updates()
        |> LiveHelpers.schedule_refresh()

      {:ok, socket}
    else
      {:ok, push_navigate(socket, to: "#{socket.assigns.base_path}/flows")}
    end
  end

  @impl true
  def handle_info(:refresh, socket) do
    socket =
      socket
      |> load_flow()
      |> load_run_history()
      |> LiveHelpers.schedule_refresh()

    {:noreply, socket}
  end

  @impl true
  def handle_info({:pgflow, _run_id, {:run_completed, _}}, socket) do
    {:noreply, load_run_history(socket)}
  end

  @impl true
  def handle_info({:pgflow, _run_id, {:run_failed, _}}, socket) do
    {:noreply, load_run_history(socket)}
  end

  @impl true
  def handle_info(_, socket), do: {:noreply, socket}

  defp load_flow(socket) do
    case Flows.get_flow_with_graph(socket.assigns.repo, socket.assigns.flow_slug) do
      {:ok, flow} -> assign(socket, :flow, flow)
      {:error, _} -> assign(socket, :flow, nil)
    end
  end

  defp load_run_history(socket) do
    grid_data =
      Flows.get_run_history_grid(
        socket.assigns.repo,
        socket.assigns.flow_slug,
        limit: socket.assigns.config[:max_grid_runs] || 50
      )

    step_slugs =
      if socket.assigns.flow do
        Enum.map(socket.assigns.flow.steps, & &1.step_slug)
      else
        Map.keys(grid_data)
      end

    socket
    |> assign(:grid_data, grid_data)
    |> assign(:step_slugs, step_slugs)
  end

  @impl true
  def render(assigns) do
    ~H"""
    <Layouts.dashboard_layout current_page={:flows} base_path={@base_path}>
      <div :if={@flow}>
        <!-- Header -->
        <div class="mb-6">
          <.link navigate={"#{@base_path}/flows"} class="text-sm text-slate-500 hover:text-slate-700 dark:text-slate-400 mb-2 inline-block">
            ← Back to flows
          </.link>
          <h1 class="text-2xl font-bold text-slate-900 dark:text-white">{@flow.flow_slug}</h1>
          <p class="mt-1 text-sm text-slate-500 dark:text-slate-400">
            {@flow.step_count} steps · Max {@ flow.opt_max_attempts} attempts · {@ flow.opt_timeout}s timeout
          </p>
        </div>

        <!-- Stats -->
        <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
          <div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-4">
            <p class="text-sm text-slate-500 dark:text-slate-400">Total Runs (24h)</p>
            <p class="text-2xl font-semibold text-slate-900 dark:text-white">{@flow.total_runs_24h}</p>
          </div>
          <div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-4">
            <p class="text-sm text-slate-500 dark:text-slate-400">Success Rate</p>
            <p class="text-2xl font-semibold text-emerald-600 dark:text-emerald-400">{@flow.success_rate_24h}%</p>
          </div>
          <div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-4">
            <p class="text-sm text-slate-500 dark:text-slate-400">Avg Duration</p>
            <p class="text-2xl font-semibold text-slate-900 dark:text-white">{LiveHelpers.format_duration(@flow.avg_duration_ms)}</p>
          </div>
          <div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-4">
            <p class="text-sm text-slate-500 dark:text-slate-400">P95 Duration</p>
            <p class="text-2xl font-semibold text-slate-900 dark:text-white">{LiveHelpers.format_duration(@flow.p95_duration_ms)}</p>
          </div>
        </div>

        <!-- Workflow -->
        <div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-4 mb-6">
          <h2 class="text-sm font-semibold text-slate-900 dark:text-white mb-4">Workflow</h2>
          <DependencyGraph.dependency_graph steps={@flow.steps} />
        </div>

        <!-- Run History Grid -->
        <div class="bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-4">
          <h2 class="text-sm font-semibold text-slate-900 dark:text-white mb-4">Run History</h2>
          <p class="text-xs text-slate-500 dark:text-slate-400 mb-3">Click a cell to view run details with step selected</p>
          <RunHistoryGrid.run_history_grid
            grid_data={@grid_data}
            steps={@step_slugs}
            max_runs={@config[:max_grid_runs] || 50}
            base_path={@base_path}
          />
        </div>
      </div>
    </Layouts.dashboard_layout>
    """
  end
end