import { useI18n } from "../../../i18n";
import type { Post } from "../../../types/post";
import { ALBUM_GAP, ALBUM_MAX_HEIGHT } from "../../../constants/media";
import { AttachmentDownloadPill } from "../AttachmentDownloadPill";
import { BubbleImage } from "../BubbleImage";
import { useImageRatios } from "../hooks/useImageRatios";
import { useLightbox } from "../overlays/ImageLightbox";
import { autolink } from "../utils/autolink";
import { computeAlbumLayout } from "../utils/albumLayout";
import { postDisplayText } from "../utils/postText";
import { CollapsibleText } from "../CollapsibleText";

const MAX_VISIBLE = 4;

export function AlbumBubble({ post }: { post: Post }) {
  const { openLightbox } = useLightbox();
  const { lang } = useI18n();
  const images = post.attachments;
  const text = postDisplayText(post, lang);
  const visible = images.slice(0, MAX_VISIBLE);
  const extra = images.length - MAX_VISIBLE;

  const sources = visible.map(
    (att) => att.thumbnailUrl ?? att.thumbUrl ?? att.url,
  );
  const ratios = useImageRatios(visible, sources);
  const layout = computeAlbumLayout(ratios);

  // Two-image albums scale each image to fit its cell (object-contain) so a
  // tall poster is never cropped — the cell already matches the image ratio, so
  // there are no bars except on very wide screens where the height is capped.
  // 3+ images keep object-cover to stay a tidy mosaic.
  const imgFit = visible.length === 2 ? "object-contain" : "object-cover";

  return (
    <div className="flex flex-col">
      {/* aspect-ratio sets a definite box height; tiles are absolutely
          positioned by percentage so the mosaic fills it exactly (no CSS-grid
          `fr` quirks, no leftover black band). */}
      <div
        className="relative w-full overflow-hidden bg-black"
        style={{
          aspectRatio: layout?.aspectRatio,
          maxHeight: ALBUM_MAX_HEIGHT,
        }}
      >
        {visible.map((att, i) => {
          const isLastSlot = i === MAX_VISIBLE - 1 && extra > 0;
          const tile = layout?.tiles[i];
          if (!tile) return null;
          return (
            <div
              key={att.id}
              className="absolute overflow-hidden"
              style={{
                left: `${tile.left * 100}%`,
                top: `${tile.top * 100}%`,
                width: `calc(${tile.width * 100}% - ${ALBUM_GAP}px)`,
                height: `calc(${tile.height * 100}% - ${ALBUM_GAP}px)`,
                // Query container so the download pill scales with this tile.
                containerType: "inline-size",
              }}
            >
              <button
                type="button"
                onClick={() => openLightbox(images, i, text, post.id)}
                className="group block h-full w-full"
                aria-label={
                  isLastSlot ? `View all ${images.length} images` : "View image"
                }
              >
                <BubbleImage
                  src={sources[i]}
                  fallbackSrc={[att.thumbUrl, att.url]}
                  loading="lazy"
                  className={`h-full w-full ${imgFit} transition duration-300 group-hover:scale-[1.03]`}
                />
                {isLastSlot ? (
                  <div className="absolute inset-0 flex flex-col items-center justify-center gap-0.5 bg-black/60 text-white backdrop-blur-[1px] transition group-hover:bg-black/50">
                    <span className="text-3xl font-bold leading-none md:text-4xl">
                      +{extra}
                    </span>
                  </div>
                ) : null}
              </button>
              {!isLastSlot ? (
                <AttachmentDownloadPill
                  postId={post.id}
                  attachment={att}
                  adaptive
                />
              ) : null}
            </div>
          );
        })}
      </div>
      {text ? (
        <CollapsibleText
          wrapperClassName="px-4 pt-3"
          className="message-stream-copyable-text select-text whitespace-pre-wrap break-words text-[14px] leading-6 text-neutral-100"
        >
          {autolink(text)}
        </CollapsibleText>
      ) : null}
    </div>
  );
}
