<div id={@id} class="contents">
  <%!--                                                                          --%>
  <%!-- MediaCanvasViewer — rendered inside a parent's modal shell (a <dialog>   --%>
  <%!-- in MediaViewer, a <div class="modal"> in MediaBrowser). Owns the         --%>
  <%!-- per-file content: close button, prev/next chevrons, image canvas /      --%>
  <%!-- video / pdf / icon, composer popover, and sidebar (filename, Download,   --%>
  <%!-- metadata, comments thread).                                              --%>
  <%!--                                                                          --%>
  <%!-- All click events on the close + chevron buttons target the parent       --%>
  <%!-- LiveComponent (`phx-target={"#" <> @parent_id}`) — the parent owns      --%>
  <%!-- modal open/close state and file navigation, this component just         --%>
  <%!-- displays whichever file's been handed to it.                             --%>
  <%!--                                                                          --%>
  <% f = @file %>
  <%!-- Close button — top-right of modal-box. Suppressed in viewer_only --%>
  <%!-- mode (standalone-page hosts provide their own back navigation).  --%>
  <button
    :if={not @viewer_only}
    type="button"
    phx-click="close_viewer"
    phx-target={"##{@parent_id}"}
    class="btn btn-ghost btn-sm btn-circle absolute top-3 right-3 z-30 bg-base-100 hover:bg-base-200 shadow-lg ring-1 ring-base-300"
    title={gettext("Close")}
  >
    <.icon name="hero-x-mark" class="w-4 h-4" />
  </button>

  <div class="flex flex-col lg:flex-row h-full overflow-hidden">
    <%!-- Viewer column (image / video / pdf / icon) --%>
    <div class="flex-[7] relative flex items-center justify-center bg-base-200 overflow-hidden p-0 lg:p-2 min-h-[40vh] lg:min-h-0">
      <%!-- Chevron positioning sits on a wrapper div, not the button.       --%>
      <%!-- daisyUI's active-state CSS replaces `transform` with             --%>
      <%!-- `scale(0.97)` on click, which would clobber a -translate-y-1/2    --%>
      <%!-- on the button itself and make it jump down 50% of its height.    --%>
      <%= if @has_prev do %>
        <div class="absolute left-2 top-1/2 -translate-y-1/2 z-10">
          <button
            type="button"
            phx-click="step_viewer"
            phx-value-dir="prev"
            phx-target={"##{@parent_id}"}
            class="btn btn-circle btn-ghost bg-base-100/80 hover:bg-base-100 shadow-md"
            title={gettext("Previous (←)")}
          >
            <.icon name="hero-chevron-left" class="w-5 h-5" />
          </button>
        </div>
      <% end %>
      <%= if @has_next do %>
        <div class="absolute right-2 top-1/2 -translate-y-1/2 z-10">
          <button
            type="button"
            phx-click="step_viewer"
            phx-value-dir="next"
            phx-target={"##{@parent_id}"}
            class="btn btn-circle btn-ghost bg-base-100/80 hover:bg-base-100 shadow-md"
            title={gettext("Next (→)")}
          >
            <.icon name="hero-chevron-right" class="w-5 h-5" />
          </button>
        </div>
      <% end %>

      <%= cond do %>
        <% is_binary(f.mime_type) and String.starts_with?(f.mime_type, "image/") -> %>
          <%!-- Fresco canvas + Etcher annotation layer + Tessera zoom layer.   --%>
          <%!--                                                                  --%>
          <%!-- - <Fresco.canvas> hosts the image at its base (medium)          --%>
          <%!--   resolution; the Canvas struct is built in                     --%>
          <%!--   build_viewer_canvas/2 with the file's annotations stuffed     --%>
          <%!--   into extensions.etcher — Etcher hydrates on mount via         --%>
          <%!--   handle.getExtension("etcher").                                 --%>
          <%!-- - <Etcher.layer> attaches via fresco_id; emits a single bulk    --%>
          <%!--   etcher:annotations-changed event the parent handles.          --%>
          <%!-- - <Tessera.layer> swaps medium → large → original as the user   --%>
          <%!--   zooms in, and (when urls["dzi"] is present) streams DZI tiles --%>
          <%!--   past the top raster for deep zoom on gigapixel images. Only   --%>
          <%!--   variants that exist on the file are included; tile + manifest --%>
          <%!--   fetches are lazy so unviewed regions never hit storage.       --%>
          <%= if @viewer_canvas do %>
            <Fresco.canvas
              id={"media-zoom-" <> f.file_uuid}
              canvas={@viewer_canvas}
              class="w-full h-full lg:rounded"
              theme={:inherit}
            />
            <Etcher.layer
              fresco_id={"media-zoom-" <> f.file_uuid}
              colors={@etcher_colors}
              line_params={@etcher_line_params}
              tools={[
                :grabber,
                :rectangle,
                :circle,
                :polygon,
                :freehand,
                :marker,
                :callout,
                :text,
                :dimension,
                :line,
                :eraser
              ]}
            />
            <%!-- Zoom ladder: medium → large, then for images over 4K we stream
                 DZI tiles of the original (only the visible area) instead of
                 ever loading the whole multi-MB original; for ≤4K images the
                 full original raster is the top of the ladder (no tiles). DZI
                 tiles also require the storage tile-generation setting (which
                 is what populates urls["dzi"]). --%>
            <% over_4k = max(Map.get(f, :width) || 0, Map.get(f, :height) || 0) > 4096
            has_dzi = is_binary(f.urls["dzi"]) and f.urls["dzi"] != ""
            use_tiles = over_4k and has_dzi

            tessera_sources =
              ([{f.urls["medium"], 800}, {f.urls["large"], 1920}] ++
                 if(use_tiles, do: [], else: [{f.urls["original"], Map.get(f, :width) || 4096}]))
              |> Enum.filter(fn {url, _w} -> is_binary(url) and url != "" end)
              |> Enum.map(fn {url, width} -> %{url: url, width: width} end)

            tessera_dzi = if use_tiles, do: f.urls["dzi"], else: nil %>
            <%= if tessera_sources != [] do %>
              <Tessera.layer
                fresco_id={"media-zoom-" <> f.file_uuid}
                sources={tessera_sources}
                dzi_url={tessera_dzi}
              />
            <% end %>
          <% end %>
        <% is_binary(f.mime_type) and String.starts_with?(f.mime_type, "video/") -> %>
          <video
            src={f.urls["original"]}
            controls
            class="max-w-full max-h-full rounded"
            preload="metadata"
          >
            {gettext("Your browser does not support the video tag.")}
          </video>
        <% f.mime_type == "application/pdf" -> %>
          <iframe
            src={f.urls["original"]}
            sandbox="allow-same-origin"
            class="w-full h-full rounded border-0"
            title={f.filename}
          ></iframe>
        <% true -> %>
          <div class="flex flex-col items-center justify-center text-base-content/50 py-12">
            <.icon name={file_icon(f.file_type)} class="w-32 h-32 mb-4" />
            <p class="text-2xl font-semibold">
              {String.upcase(f.file_type || gettext("FILE"))}
            </p>
            <p class="text-sm text-base-content/70 mt-2">{f.mime_type}</p>
          </div>
      <% end %>

      <%!-- Floating annotation composer — positioned above the just-drawn --%>
      <%!-- shape by the AnnotationComposerPosition JS hook (it looks up    --%>
      <%!-- the shape via [data-uuid="…"]). Sidebar comments stay visible   --%>
      <%!-- alongside; this popover is for the new shape only.               --%>
      <%= if @composing_annotation_uuid && @current_user do %>
        <div
          id={"annotation-composer-popover-" <> @composing_annotation_uuid}
          phx-hook="AnnotationComposerPosition"
          class="absolute z-30 w-80 max-w-[calc(100%-1rem)] bg-base-100 rounded-lg shadow-xl border border-base-300 p-3"
          style="left: 0px; top: 0px;"
        >
          <div class="flex items-center gap-2 text-sm font-medium mb-2">
            <.icon name="hero-pencil-square" class="w-4 h-4 text-warning" />
            <span>{gettext("Add a note to your annotation")}</span>
          </div>
          <p class="text-xs text-base-content/60 mb-3">
            {gettext(
              "Post to add the note. Cancel to skip — you can edit or delete the annotation later via the toolbar."
            )}
          </p>
          <.live_component
            module={PhoenixKitWeb.Components.AnnotationComposer}
            id={"annotation-composer-" <> @composing_annotation_uuid}
            annotation_uuid={@composing_annotation_uuid}
            file_uuid={f.file_uuid}
            current_user={@current_user}
            parent_id={@id}
            parent_module={PhoenixKitWeb.Components.MediaCanvasViewer}
          />
        </div>
      <% end %>
    </div>

    <%!-- Sidebar: filename + download + metadata + comments. Suppressed --%>
    <%!-- in viewer_only mode — standalone-page hosts render their own  --%>
    <%!-- sidebar with admin actions / metadata editor / file details.   --%>
    <div
      :if={not @viewer_only}
      class="flex-[3] flex flex-col gap-3 p-4 overflow-y-auto lg:min-w-[280px] bg-base-100"
    >
      <h2 class="text-base font-bold break-all leading-tight pr-10">
        {f.filename}
      </h2>

      <%= if f.urls["original"] do %>
        <a
          href={f.urls["original"]}
          download={f.filename}
          target="_blank"
          rel="noopener"
          class="btn btn-primary btn-sm gap-2 self-start"
        >
          <.icon name="hero-arrow-down-tray" class="w-4 h-4" /> {gettext("Download")}
        </a>
      <% end %>

      <div class="text-sm space-y-2 mt-1">
        <div>
          <span class="text-base-content/60">{gettext("Type:")}</span>
          <span class="ml-1 badge badge-ghost">
            {String.upcase(f.file_type || gettext("FILE"))}
          </span>
        </div>
        <div class="break-all">
          <span class="text-base-content/60">{gettext("MIME:")}</span>
          <span class="ml-1 font-mono text-xs">{f.mime_type}</span>
        </div>
        <div>
          <span class="text-base-content/60">{gettext("Size:")}</span>
          <span class="ml-1">{format_file_size(f.size)}</span>
        </div>
        <div>
          <span class="text-base-content/60">{gettext("Uploaded:")}</span>
          <span class="ml-1">
            {Calendar.strftime(f.inserted_at, "%b %d, %Y at %H:%M")}
          </span>
        </div>
      </div>

      <%!-- Comments section — gated on the Comments module being     --%>
      <%!-- installed AND enabled, plus a logged-in user. Keyed by    --%>
      <%!-- file_uuid so prev/next remounts the component cleanly.    --%>
      <%!--                                                            --%>
      <%!-- The wrapper applies a compact-mode override: shrinks the  --%>
      <%!-- comments component's typography, paddings, and avatars    --%>
      <%!-- via descendant selectors so it fits inside the sidebar    --%>
      <%!-- without truncation. The component itself isn't modified.  --%>
      <%= if comments_enabled?() and @current_user do %>
        <div class="border-t border-base-300 pt-3 mt-3 leaf-comments-compact">
          <.live_component
            module={PhoenixKitComments.Web.CommentsComponent}
            id={"media-comments-" <> f.file_uuid}
            resource_type="file"
            resource_uuid={f.file_uuid}
            current_user={@current_user}
            show_likes={true}
            title={gettext("Comments")}
            comment_decorations={build_comment_decorations(@viewer_annotations)}
            parent_module={PhoenixKitWeb.Components.MediaCanvasViewer}
            parent_id={@id}
          />
        </div>
      <% end %>
    </div>
  </div>
</div>
