defmodule KetbinWeb.PageController do
  require Logger

  use KetbinWeb, :controller

  alias Ketbin.Pastes
  alias Ketbin.Pastes.Paste
  alias Ketbin.Pastes.Utils

  def index(conn, _params) do
    changeset = Pastes.change_paste(%Paste{})
    render(conn, "index.html", changeset: changeset)
  end

  def show(%{assigns: %{show_edit: show_edit}} = conn, %{"id" => id}) do
    [head | tail] = String.split(id, ".")

    # fetch paste from db
    paste =
      try do
        Pastes.get_paste!(head)
      rescue
        Ecto.NoResultsError ->
          Pastes.get_paste!(id)
      end

    # paste is a url, redirect
    # regular paste, show content
    if paste.is_url do
      redirect(conn,
        external: paste.content |> String.replace("\r", "") |> String.replace("\n", "")
      )
    else
      render(conn, "show.html",
        paste: paste,
        show_edit: show_edit,
        extension: List.first(tail) || "",
        page_title: paste.id
      )
    end
  end

  def showlink(%{assigns: %{show_edit: show_edit}} = conn, %{"id" => id}) do
    [head | tail] = String.split(id, ".")
    paste = Pastes.get_paste!(head)

    render(conn, "shorten.html",
      paste: paste,
      show_edit: show_edit,
      extension: if(tail == [], do: "", else: tail),
      page_title: paste.id
    )
  end

  def raw(conn, %{"id" => id}) do
    paste = Pastes.get_paste!(id)
    text(conn, paste.content)
  end

  def create(%{assigns: %{current_user: current_user}} = conn, %{"paste" => paste_params}) do
    # if custom url exists, use it as id, else generate phonetic id
    id =
      case Map.get(paste_params, "custom_url", "") do
        custom_url when custom_url != "" -> custom_url
        _ -> Utils.generate_key()
      end

    # check if content is a url
    is_url =
      Map.get(paste_params, "content")
      |> Utils.is_url?()

    # put id and is_url values into changeset
    paste_params =
      Map.put(paste_params, "id", id)
      |> Map.put("is_url", is_url)
      |> Map.put("belongs_to", current_user && current_user.id)

    # attempt to create a paste
    case Pastes.create_paste(paste_params) do
      # all good, redirect
      {:ok, paste} ->
        unless is_url do
          conn
          # is a regular paste, take to regular route
          |> redirect(to: Routes.page_path(conn, :show, paste))
        else
          conn
          # is a url, take to route with /v/ prefix
          |> redirect(to: Routes.page_path(conn, :showlink, paste))
        end

      # something went wrong, bail
      {:error, %Ecto.Changeset{} = changeset} ->
        case changeset.errors[:id] do
          {"has already been taken", _} ->
            render(conn, "index.html", changeset: changeset, already_taken: true)

          _ ->
            render(conn, "index.html", changeset: changeset)
        end
    end
  end

  def edit(conn, %{"id" => id}) do
    paste = Pastes.get_paste!(id)
    changeset = Pastes.change_paste(paste)
    render(conn, "edit.html", paste: paste, changeset: changeset)
  end

  def update(conn, %{"id" => id, "paste" => paste_params}) do
    paste = Pastes.get_paste!(id)

    # check if content is a url
    is_url =
      Map.get(paste_params, "content")
      |> Utils.is_url?()

    paste_params = Map.put(paste_params, "is_url", is_url)

    case Pastes.update_paste(paste, paste_params) do
      {:ok, paste} ->
        unless is_url do
          conn
          |> put_flash(:info, "Paste updated successfully.")
          |> redirect(to: Routes.page_path(conn, :show, paste))
        else
          conn
          |> put_flash(:info, "Paste updated successfully.")
          |> redirect(to: Routes.page_path(conn, :showlink, paste))
        end

      {:error, %Ecto.Changeset{} = changeset} ->
        render(conn, "edit.html", paste: paste, changeset: changeset)
    end
  end

  def pastes(%{assigns: %{current_user: current_user}} = conn, _params) do
    pastes = Pastes.list_pastes_by_user(current_user.id)
    render(conn, "pastes.html", pastes: pastes)
  end
end
