<script lang="ts">
  import cx from "classnames"
  import {Track} from "livekit-client"
  import {displayProfileByPubkey, loadProfile} from "@welshman/app"
  import ProfileCircle from "@app/components/ProfileCircle.svelte"
  import VideoCallVideo from "@app/components/VideoCallVideo.svelte"
  import {
    currentVoiceSession,
    currentVoiceRoom,
    videoCallContentActive,
    videoCallLayoutRevision,
    pubkeyFromLiveKitIdentity,
  } from "@app/voice"

  type Variant = "mobile" | "desktop-split" | "desktop-full"

  type Props = {
    variant: Variant
    url: string
    h: string
    visible?: boolean
    class?: string
  }

  type Tile = {
    identity: string
    isLocal: boolean
    trackSid: string
    attachable: Track | undefined
  }

  const {variant, url, h, visible = true, class: className = ""}: Props = $props()

  const roomMatches = $derived($currentVoiceRoom?.url === url && $currentVoiceRoom?.h === h)

  const allowEmptyPanel = $derived(variant === "desktop-split" || variant === "desktop-full")

  const showPanel = $derived(
    visible &&
      roomMatches &&
      (variant === "mobile" ? $videoCallContentActive : $videoCallContentActive || allowEmptyPanel),
  )

  const tiles = $derived.by(() => {
    // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- re-run when remote video subscribes
    $videoCallLayoutRevision
    const session = $currentVoiceSession
    if (!session || $currentVoiceRoom?.url !== url || $currentVoiceRoom?.h !== h) {
      return []
    }

    const room = session.room
    const out: Tile[] = []
    const lp = room.localParticipant

    if (session.cameraOn) {
      const localPub = lp.getTrackPublication(Track.Source.Camera)
      out.push({
        identity: lp.identity,
        isLocal: true,
        trackSid: localPub?.trackSid ?? "local-camera",
        attachable: localPub?.track,
      })
    }

    for (const rp of room.remoteParticipants.values()) {
      const pub = rp.getTrackPublication(Track.Source.Camera)
      if (pub?.isSubscribed && pub.track) {
        out.push({
          identity: rp.identity,
          isLocal: false,
          trackSid: pub.trackSid,
          attachable: pub.track,
        })
      }
    }

    return out
  })

  $effect(() => {
    for (const t of tiles) {
      const pk = pubkeyFromLiveKitIdentity(t.identity)
      if (pk) loadProfile(pk)
    }
  })

  const labelFor = (identity: string) => {
    const pk = pubkeyFromLiveKitIdentity(identity)
    return pk ? displayProfileByPubkey(pk) : "Unknown"
  }

  const showTileGrid = $derived(tiles.length > 0)
</script>

{#if showPanel && (showTileGrid || allowEmptyPanel)}
  <div
    class={cx(
      variant === "mobile" &&
        "cb ct cw z-compose bg-base-300/95 fixed inset-x-0 flex flex-col gap-2 overflow-y-auto p-2 md:hidden",
      variant === "desktop-split" &&
        "cb ct cw-split-video z-compose bg-base-300/95 fixed hidden flex-col gap-2 overflow-y-auto p-2 md:flex",
      variant === "desktop-full" &&
        "cb ct cw z-compose bg-base-300/95 fixed hidden flex-col gap-2 overflow-y-auto p-2 md:flex",
      className,
    )}>
    {#if showTileGrid}
      {#each tiles as tile (tile.trackSid + tile.identity)}
        <div class="relative aspect-video overflow-hidden rounded-box bg-base-100 shadow-sm">
          {#if tile.attachable}
            <VideoCallVideo track={tile.attachable} muted={tile.isLocal} class="absolute inset-0" />
          {:else}
            <div class="absolute inset-0 flex items-center justify-center">
              <ProfileCircle pubkey={pubkeyFromLiveKitIdentity(tile.identity)} {url} size={14} />
            </div>
          {/if}
          <span
            class="absolute bottom-1 left-1 max-w-[calc(100%-0.5rem)] truncate rounded bg-base-100/80 px-1.5 py-0.5 text-xs">
            {labelFor(tile.identity)}{tile.isLocal ? " (you)" : ""}
          </span>
        </div>
      {/each}
    {:else}
      <div
        class="flex min-h-[12rem] flex-1 flex-col items-center justify-center gap-2 rounded-box bg-base-100/50 p-4 text-center text-sm opacity-80">
        <p>No camera video yet.</p>
        <p class="text-xs">Use the camera control in the voice widget to share video.</p>
      </div>
    {/if}
  </div>
{/if}
