defmodule CentralcloudStaff.ChatLive do
  use CentralcloudStaffWeb, :live_view
  alias CentralcloudStaff.RouterAgent

  def mount(_params, _session, socket) do
    default = "router"

    {:ok,
     assign(socket,
       page_title: "AI Chat",
       agents: RouterAgent.agents(),
       agent_keys: RouterAgent.agent_keys(),
       current_agent: default,
       conversations: empty_conversations(),
       streaming: false,
       streaming_content: "",
       error: nil
     )}
  end

  defp empty_conversations,
    do: Map.new(RouterAgent.agent_keys(), fn k -> {k, []} end)

  defp messages(socket), do: Map.fetch!(socket.assigns.conversations, socket.assigns.current_agent)

  defp put_messages(socket, msgs),
    do:
      assign(socket,
        conversations: Map.put(socket.assigns.conversations, socket.assigns.current_agent, msgs)
      )

  def handle_event("select_agent", %{"agent" => key}, socket) do
    if socket.assigns.streaming do
      {:noreply, socket}
    else
      key = if key in socket.assigns.agent_keys, do: key, else: "router"

      {:noreply,
       assign(socket,
         current_agent: key,
         streaming_content: "",
         error: nil
       )}
    end
  end

  def handle_event("send", %{"message" => text}, socket), do: do_send(text, socket)
  def handle_event("send", %{"value" => text}, socket), do: do_send(text, socket)

  def handle_event("clear", _params, socket) do
    {:noreply,
     socket
     |> put_messages([])
     |> assign(streaming: false, streaming_content: "", error: nil)}
  end

  defp do_send(text, socket) do
    text = String.trim(text)

    cond do
      text == "" ->
        {:noreply, socket}

      socket.assigns.streaming ->
        {:noreply, socket}

      true ->
        user_msg = %{role: "user", content: text}
        msgs = messages(socket) ++ [user_msg]
        agent_key = socket.assigns.current_agent

        caller = self()
        Task.start(fn -> RouterAgent.stream_chat(msgs, caller, agent_key) end)

        {:noreply,
         socket
         |> put_messages(msgs)
         |> assign(streaming: true, streaming_content: "", error: nil)}
    end
  end

  def handle_info({:chunk, text}, socket) do
    {:noreply, assign(socket, streaming_content: socket.assigns.streaming_content <> text)}
  end

  def handle_info(:stream_done, socket) do
    content = socket.assigns.streaming_content

    if content != "" do
      assistant_msg = %{role: "assistant", content: content, agent: socket.assigns.current_agent}

      {:noreply,
       socket
       |> put_messages(messages(socket) ++ [assistant_msg])
       |> assign(streaming: false, streaming_content: "")}
    else
      {:noreply, assign(socket, streaming: false)}
    end
  end

  def handle_info({:stream_error, reason}, socket) do
    {:noreply,
     assign(socket,
       streaming: false,
       streaming_content: "",
       error: "Agent error: #{reason}"
     )}
  end

  defp current(assigns), do: Map.fetch!(assigns.agents, assigns.current_agent)

  defp bubble_name(assigns, msg) do
    case msg do
      %{agent: a} when is_binary(a) -> Map.get(assigns.agents, a, current(assigns))[:name]
      _ -> current(assigns).name
    end
  end

  def render(assigns) do
    ~H"""
    <div class="flex items-center justify-between mb-4">
      <h1 class="text-lg font-bold text-slate-100 flex items-center gap-2">
        🤖 AI Operations Chat
      </h1>
      <div class="flex items-center gap-2 text-xs text-slate-500">
        <span>Agent:</span>
        <form phx-change="select_agent">
          <select
            name="agent"
            disabled={@streaming}
            class="bg-[#0f1629] border border-[#1e3a5f] rounded px-2 py-1 text-slate-200 text-xs outline-none focus:border-blue-600 disabled:opacity-50"
          >
            <option :for={k <- @agent_keys} value={k} selected={k == @current_agent}>
              {@agents[k][:name]}
            </option>
          </select>
        </form>
      </div>
    </div>

    <div class="bg-[#0f1629] border border-[#1e3a5f] rounded-lg overflow-hidden flex flex-col h-[calc(100vh-180px)] min-h-[400px]">
      <div class="px-4 py-2 border-b border-[#1e3a5f] flex items-center gap-2 text-xs">
        <span class="text-orange-400 font-semibold">{current(@assigns).name}</span>
        <span class="text-slate-500">— {current(@assigns).description}</span>
      </div>

      <div
        id={"chat-messages-#{@current_agent}"}
        phx-hook="ScrollBottom"
        class="flex-1 overflow-y-auto p-4 flex flex-col gap-3"
      >
        <% msgs = Map.fetch!(@conversations, @current_agent) %>
        <div
          :if={msgs == [] and not @streaming}
          class="flex-1 flex flex-col items-center justify-center text-slate-500 gap-3 py-12 px-4 text-center"
        >
          <div class="text-4xl">🔥</div>
          <div class="text-base font-semibold text-slate-400">
            Talking to <span class="text-orange-400">{current(@assigns).name}</span>
          </div>
          <div class="text-sm text-slate-500">{current(@assigns).description}</div>
        </div>

        <div :for={msg <- msgs}>
          <div :if={msg.role == "user"} class="flex justify-end">
            <div class="max-w-[75%] px-3.5 py-2.5 rounded-2xl rounded-br-sm bg-blue-600 text-white text-sm leading-relaxed whitespace-pre-wrap break-words">
              {msg.content}
            </div>
          </div>
          <div :if={msg.role == "assistant"} class="flex justify-start items-start gap-2">
            <div class="w-7 h-7 rounded-full bg-[#1e3a5f] flex items-center justify-center text-sm flex-shrink-0 mt-0.5">
              🤖
            </div>
            <div class="max-w-[80%]">
              <div class="text-[10px] text-slate-500 mb-1 ml-1">{bubble_name(@assigns, msg)}</div>
              <div class="px-3.5 py-2.5 rounded-2xl rounded-bl-sm bg-[#0f1629] border border-[#1e3a5f] text-slate-200 text-sm leading-relaxed whitespace-pre-wrap break-words">
                {msg.content}
              </div>
            </div>
          </div>
        </div>

        <div :if={@streaming} class="flex justify-start items-start gap-2">
          <div class="w-7 h-7 rounded-full bg-[#1e3a5f] flex items-center justify-center text-sm flex-shrink-0 mt-0.5">
            🤖
          </div>
          <div class="max-w-[80%]">
            <div class="text-[10px] text-slate-500 mb-1 ml-1">{current(@assigns).name}</div>
            <div class="px-3.5 py-2.5 rounded-2xl rounded-bl-sm bg-[#0f1629] border border-[#1e3a5f] text-slate-200 text-sm leading-relaxed">
              <span :if={@streaming_content == ""} class="flex gap-1 items-center py-0.5">
                <span class="bounce-dot"></span>
                <span class="bounce-dot"></span>
                <span class="bounce-dot"></span>
              </span>
              <span :if={@streaming_content != ""} class="whitespace-pre-wrap break-words">
                {@streaming_content}<span class="chat-cursor">▋</span>
              </span>
            </div>
          </div>
        </div>
      </div>

      <div
        :if={@error}
        class="px-4 py-2 bg-red-950/80 border-t border-red-800 text-red-300 text-sm"
      >
        ⚠️ {@error}
      </div>

      <div class="border-t border-[#1e3a5f] px-4 py-3">
        <form phx-submit="send" class="flex gap-2 items-center">
          <input
            id="chat-input"
            type="text"
            name="message"
            autocomplete="off"
            disabled={@streaming}
            placeholder={if @streaming, do: "Waiting for response…", else: "Ask #{current(@assigns).name}…"}
            class="flex-1 bg-[#0a0f1e] border border-[#1e3a5f] rounded-lg px-3 py-2 text-slate-200 text-sm outline-none focus:border-blue-600 disabled:opacity-50 disabled:cursor-not-allowed placeholder:text-slate-600"
          />
          <.button type="submit" size="sm" color="primary" disabled={@streaming}>Send</.button>
          <.button
            :if={Map.fetch!(@conversations, @current_agent) != [] and not @streaming}
            type="button"
            size="sm"
            color="gray"
            variant="outline"
            phx-click="clear"
          >
            Clear
          </.button>
        </form>
      </div>
    </div>
    """
  end
end
