defmodule AlgoraWeb.ShowLive.Show do
  use AlgoraWeb, :live_view

  alias Algora.{Shows, Library, Events}
  alias Algora.Accounts
  alias AlgoraWeb.LayoutComponent

  @impl true
  def render(assigns) do
    ~H"""
    <img
      src={@show.image_url}
      class="w-screen min-w-screen max-h-[200px] sm:max-h-none sm:h-[200px] md:h-[250px] lg:h-[350px] object-cover"
    />
    <div class="text-white min-h-screen p-8">
      <div class="flex flex-col md:grid md:grid-cols-3 gap-6">
        <div class="md:col-span-1 bg-white/5 ring-1 ring-white/15 rounded-lg p-6 space-y-6">
          <div class="space-y-2">
            <div class="flex items-center space-x-2">
              <span class="relative ring-4 ring-[#15122c] flex h-10 w-10 shrink-0 overflow-hidden rounded-full">
                <img
                  class="aspect-square h-full w-full"
                  alt={@channel.name}
                  src={@channel.avatar_url}
                />
              </span>
              <span class="font-bold"><%= @channel.name %></span>
              <.link
                :if={@channel.twitter_url}
                target="_blank"
                rel="noopener noreferrer"
                href={@channel.twitter_url}
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  width="24"
                  height="24"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  class="text-white"
                >
                  <path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M4 4l11.733 16h4.267l-11.733 -16z" /><path d="M4 20l6.768 -6.768m2.46 -2.46l6.772 -6.772" />
                </svg>
              </.link>
            </div>
            <div :if={!@owns_show?} class="pt-2">
              <.button :if={@current_user} phx-click="toggle_subscription">
                <%= if @subscribed? do %>
                  Unsubscribe
                <% else %>
                  Subscribe
                <% end %>
              </.button>
              <.button :if={!@current_user && @authorize_url}>
                <.link navigate={@authorize_url}>
                  Subscribe
                </.link>
              </.button>
            </div>
            <div :if={@owns_show?} class="pt-2">
              <.button>
                <.link patch={~p"/shows/#{@show.slug}/edit"}>
                  Edit show
                </.link>
              </.button>
            </div>
          </div>
          <div :if={@attendees_count > 0} class="border-t border-white/15 pt-6 space-y-4">
            <div>
              <span class="font-medium"><%= @attendees_count %> Attending</span>
            </div>
            <div>
              <div class="flex -space-x-1">
                <span
                  :for={attendee <- @attendees |> Enum.take(@max_attendee_avatars_count)}
                  class="relative ring-4 ring-[#15122c] flex h-10 w-10 shrink-0 overflow-hidden rounded-full"
                >
                  <img
                    class="aspect-square h-full w-full"
                    alt={attendee.user_display_name}
                    src={attendee.user_avatar_url}
                  />
                </span>
              </div>
              <div class="mt-2">
                <span
                  :for={
                    {attendee, i} <-
                      Enum.with_index(@attendees) |> Enum.take(@max_attendee_names_count)
                  }
                  class="font-medium"
                >
                  <span :if={i != 0} class="-ml-1">, </span><span><%= attendee.user_display_name %></span>
                </span>
                <span :if={@attendees_count > @max_attendee_names_count} class="font-medium">
                  and
                  <span :if={@attendees_count == @max_attendee_names_count + 1}>
                    <%= @attendees
                    |> Enum.map(fn attendee -> attendee.user_display_name end)
                    |> Enum.at(@max_attendee_names_count) %>
                  </span>
                  <span :if={@attendees_count != @max_attendee_names_count + 1}>
                    <%= @attendees_count - @max_attendee_names_count %> others
                  </span>
                </span>
              </div>
            </div>
          </div>
        </div>
        <div class="md:col-span-2 space-y-6">
          <div class="bg-white/5 ring-1 ring-white/15 rounded-lg p-6 space-y-6">
            <div class="flex flex-col md:flex-row md:items-start md:justify-between gap-6">
              <div>
                <h1 class="text-4xl font-bold"><%= @show.title %></h1>
                <div :if={@show.description} class="mt-4 space-y-4">
                  <div>
                    <h2 class="text-2xl font-bold">About</h2>
                    <p class="typography whitespace-pre-wrap"><%= @show.description %></p>
                  </div>
                </div>
              </div>

              <div class="space-y-2 w-full max-w-xs md:max-w-sm">
                <div :if={@show.scheduled_for} class="bg-gray-950/75 p-4 rounded-lg">
                  <div class="flex flex-col md:flex-wrap md:flex-row gap-2 md:items-center md:justify-between">
                    <div class="flex items-center space-x-4">
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        width="24"
                        height="24"
                        viewBox="0 0 24 24"
                        fill="none"
                        stroke="currentColor"
                        stroke-width="2"
                        stroke-linecap="round"
                        stroke-linejoin="round"
                        class="h-6 w-6 text-green-300 shrink-0"
                      >
                        <path d="M8 2v4"></path>
                        <path d="M16 2v4"></path>
                        <rect width="18" height="18" x="3" y="4" rx="2"></rect>
                        <path d="M3 10h18"></path>
                      </svg>
                      <div class="shrink-0">
                        <div class="text-sm font-semibold">
                          <%= @show.scheduled_for
                          |> Timex.to_datetime("Etc/UTC")
                          |> Timex.Timezone.convert("America/New_York")
                          |> Timex.format!("{WDfull}, {Mshort} {D}") %>
                        </div>
                        <div class="text-sm">
                          <%= @show.scheduled_for
                          |> Timex.to_datetime("Etc/UTC")
                          |> Timex.Timezone.convert("America/New_York")
                          |> Timex.format!("{h12}:{m} {am}, Eastern Time") %>
                        </div>
                        <.link
                          phx-hook="TimezoneDetector"
                          class="text-sm underline"
                          href={~p"/shows/#{@show.slug}/event.ics?tz=#{@current_user_tz}"}
                        >
                          Add to calendar
                        </.link>
                      </div>
                    </div>
                    <.button :if={@current_user && !@rsvpd?} phx-click="toggle_rsvp">
                      Attend
                    </.button>
                    <.button
                      :if={@rsvpd?}
                      disabled
                      class="bg-green-400 hover:bg-green-400 disabled:opacity-100 text-green-950 flex items-center active:text-green-950"
                    >
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        width="24"
                        height="24"
                        viewBox="0 0 24 24"
                        fill="none"
                        stroke="currentColor"
                        stroke-width="2"
                        stroke-linecap="round"
                        stroke-linejoin="round"
                        class="h-5 w-5 -ml-0.5"
                      >
                        <path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M5 12l5 5l10 -10" />
                      </svg>
                      <span class="ml-1">Attending</span>
                    </.button>
                    <.button :if={!@current_user && @authorize_url}>
                      <.link navigate={@authorize_url}>
                        Attend
                      </.link>
                    </.button>
                  </div>
                </div>
                <.link
                  href={@show.url || ~p"/#{@channel.handle}/latest"}
                  target="_blank"
                  rel="noopener"
                  class="block bg-gray-950/75 p-4 rounded-lg"
                >
                  <div class="flex items-center justify-between">
                    <div class="flex items-center space-x-4 shrink-0">
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        width="24"
                        height="24"
                        viewBox="0 0 24 24"
                        fill="none"
                        stroke="currentColor"
                        stroke-width="2"
                        stroke-linecap="round"
                        stroke-linejoin="round"
                        class="h-6 w-6 text-red-400"
                      >
                        <path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M18.364 19.364a9 9 0 1 0 -12.728 0" /><path d="M15.536 16.536a5 5 0 1 0 -7.072 0" /><path d="M12 13m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
                      </svg>
                      <div>
                        <div class="text-sm font-semibold">Watch live</div>
                        <div class="text-sm">
                          <%= @show.url || "tv.algora.io/#{@channel.handle}/latest" %>
                        </div>
                      </div>
                    </div>
                  </div>
                </.link>
              </div>
            </div>
          </div>
          <div class="bg-white/5 ring-1 ring-white/15 rounded-lg p-6 pb-2 space-y-6">
            <h2 class="pt-4 text-2xl font-bold">Past sessions</h2>
            <div
              id="past-sessions"
              class="flex gap-8 overflow-x-scroll pb-4 scrollbar-thin"
              phx-update="stream"
            >
              <div :for={{_id, video} <- @streams.videos} class="max-w-xs shrink-0 w-full">
                <.link class="cursor-pointer truncate" href={~p"/#{video.channel_handle}/#{video.id}"}>
                  <.video_thumbnail video={video} class="rounded-2xl" />
                  <div class="pt-2 text-base font-semibold truncate"><%= video.title %></div>
                  <div class="text-gray-300 text-sm"><%= Timex.from_now(video.inserted_at) %></div>
                </.link>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <.modal
      :if={@live_action in [:new, :edit]}
      id="show-modal"
      show
      on_cancel={JS.patch(~p"/shows/#{@show.slug}")}
    >
      <.live_component
        module={AlgoraWeb.ShowLive.FormComponent}
        id={@show.id || :new}
        title={@page_title}
        action={@live_action}
        show={@show}
      />
    </.modal>
    """
  end

  @impl true
  def mount(%{"slug" => slug}, _session, socket) do
    %{current_user: current_user} = socket.assigns

    show = Shows.get_show_by_fields!(slug: slug)

    channel = Accounts.get_user(show.user_id) |> Library.get_channel!()

    videos = Library.list_videos_by_show_ids([show.id])

    {:ok,
     socket
     |> assign_attendees(show)
     |> assign(:current_user_tz, "Etc/UTC")
     |> assign(:show, show)
     |> assign(:owns_show?, current_user && show.user_id == current_user.id)
     |> assign(:channel, channel)
     |> assign(:max_attendee_avatars_count, 5)
     |> assign(:max_attendee_names_count, 2)
     |> assign(:subscribed?, Events.subscribed?(current_user, channel))
     |> assign(:rsvpd?, Events.rsvpd?(current_user, channel))
     |> stream(:videos, videos)}
  end

  @impl true
  def handle_params(params, url, socket) do
    %{path: path} = URI.parse(url)
    LayoutComponent.hide_modal()

    {:noreply,
     socket
     |> assign(:authorize_url, Algora.Github.authorize_url(path))
     |> apply_action(socket.assigns.live_action, params)}
  end

  @impl true
  def handle_event("toggle_subscription", _params, socket) do
    Events.toggle_subscription_event(socket.assigns.current_user, socket.assigns.show)

    {:noreply,
     socket
     |> assign(:subscribed?, !socket.assigns.subscribed?)}
  end

  def handle_event("toggle_rsvp", _params, socket) do
    Events.toggle_rsvp_event(socket.assigns.current_user, socket.assigns.show)

    {:noreply,
     socket
     |> assign_attendees(socket.assigns.show)
     |> assign(:rsvpd?, !socket.assigns.rsvpd?)}
  end

  def handle_event("get_timezone", %{"tz" => tz}, socket) do
    {:noreply, socket |> assign(:current_user_tz, tz)}
  end

  @impl true
  def handle_info({AlgoraWeb.ShowLive.FormComponent, {:saved, show}}, socket) do
    {:noreply, socket |> assign(:show, show)}
  end

  defp apply_action(socket, :show, %{"slug" => slug}) do
    show = Shows.get_show_by_fields!(slug: slug)

    socket
    |> assign(:page_title, show.title)
    |> assign(:page_description, show.description)
    |> assign(:page_image, show.og_image_url)
  end

  defp apply_action(socket, :edit, %{"slug" => slug}) do
    %{current_user: current_user} = socket.assigns

    show = Shows.get_show_by_fields!(slug: slug)

    cond do
      current_user == nil ->
        socket
        |> redirect(to: ~p"/auth/login")

      current_user.id != show.user_id && !Accounts.admin?(current_user) ->
        socket
        |> put_flash(:error, "You don't have permission to edit this show")
        |> redirect(to: ~p"/shows/#{show.slug}")

      true ->
        socket
        |> assign(:page_title, show.title)
        |> assign(:page_description, show.description)
        |> assign(:page_image, show.og_image_url)
    end
  end

  defp assign_attendees(socket, show) do
    attendees = Events.fetch_attendees(show)

    socket
    |> assign(:attendees, attendees)
    |> assign(:attendees_count, length(attendees))
  end
end
