defmodule Web.AdminPostLive do
  use Web, :live_view

  def mount(_params, _session, socket) do
    {:ok, socket}
  end

  def handle_params(%{"post_id" => post_id}, _uri, socket) do
    post = Core.Posts.get!(post_id)
    form = Core.Posts.change_post(post, %{}) |> to_form()

    socket =
      assign(socket,
        post: post,
        form: form,
        page_title: page_title(post, socket.assigns.live_action)
      )

    {:noreply, socket}
  end

  def handle_params(%{"kind" => kind}, _uri, %{assigns: %{live_action: :new}} = socket)
      when kind in ~w[blog status] do
    post = %Schema.Post{kind: String.to_existing_atom(kind)}
    form = Core.Posts.change_post(post, %{}) |> to_form()

    socket =
      assign(socket,
        post: post,
        form: form,
        page_title: page_title(post, socket.assigns.live_action)
      )

    {:noreply, socket}
  end

  def handle_event("validate", %{"post" => attrs}, %{assigns: %{post: post}} = socket) do
    attrs =
      if update_slug?(post) and attrs["_unused_slug"] == "" do
        Map.put(attrs, "slug", Slug.slugify(attrs["title"]))
      else
        attrs
      end

    form = Core.Posts.change_post(post, attrs) |> to_form()

    socket = assign(socket, form: form)

    {:noreply, socket}
  end

  def handle_event("save", %{"post" => attrs}, %{assigns: %{post: post}} = socket) do
    socket =
      case Core.Posts.create_or_update_post(post, attrs) do
        {:ok, post} ->
          socket
          |> put_flash(:info, "post saved")
          |> push_patch(to: ~p"/admin/posts/#{post}", replace: true)

        {:error, changest} ->
          assign(socket, form: to_form(changest))
      end

    {:noreply, socket}
  end

  def handle_event("publish", _, %{assigns: %{post: post}} = socket) do
    socket =
      case Core.Posts.publish_post(post) do
        {:ok, post} ->
          assign(socket, post: post)

        _ ->
          socket
      end

    {:noreply, socket}
  end

  def handle_event("unpublish", _, %{assigns: %{post: post}} = socket) do
    socket =
      case Core.Posts.unpublish_post(post) do
        {:ok, post} ->
          assign(socket, post: post)

        _ ->
          socket
      end

    {:noreply, socket}
  end

  def handle_event("delete", _, %{assigns: %{post: post}} = socket) do
    socket =
      case Core.Posts.delete_post(post) do
        {:ok, post} ->
          assign(socket, post: post)

        _ ->
          socket
      end

    {:noreply, socket}
  end

  def handle_event("undelete", _, %{assigns: %{post: post}} = socket) do
    socket =
      case Core.Posts.undelete_post(post) do
        {:ok, post} ->
          assign(socket, post: post)

        _ ->
          socket
      end

    {:noreply, socket}
  end

  def render(assigns) do
    ~H"""
    <main>
      <header>
        <h1>{page_title(@post, @live_action)}</h1>
      </header>

      <.form for={@form} phx-change="validate" phx-submit="save">
        <.input :if={@post.kind == :blog} type="text" field={@form[:title]} />
        <.input
          :if={@post.kind == :blog}
          type="text"
          field={@form[:slug]}
          disabled={not update_slug?(@post)}
        />
        <.input type="textarea" field={@form[:body]} />

        <.button type="submit">save</.button>
      </.form>

      <%= if @live_action == :edit do %>
        <div>
          <%= if @post.published_at do %>
            <.button phx-click="unpublish">unpublish</.button>
          <% else %>
            <.button phx-click="publish">publish</.button>
          <% end %>
          <%= if @post.deleted_at do %>
            <.button phx-click="undelete">undelete</.button>
          <% else %>
            <.button phx-click="delete">delete</.button>
          <% end %>
        </div>
      <% end %>
    </main>
    """
  end

  defp page_title(%Schema.Post{kind: :blog}, :new), do: "new blog"
  defp page_title(%Schema.Post{kind: :status}, :new), do: "new status"
  defp page_title(%Schema.Post{kind: :blog}, :edit), do: "edit blog"
  defp page_title(%Schema.Post{kind: :status}, :edit), do: "edit status"

  defp update_slug?(%Schema.Post{kind: :blog, published_at: published_at}),
    do: is_nil(published_at)

  defp update_slug?(_), do: true
end