import { useState, type CSSProperties, type ReactNode } from "react";
import type { Attachment } from "../../../types/post";
import {
  SINGLE_IMAGE_FALLBACK_HEIGHT_CLASS,
  SINGLE_IMAGE_MAX_HEIGHT,
} from "../../../constants/media";
import { BubbleImage } from "../BubbleImage";

/**
 * Shared frame that sizes an image to its real aspect ratio. The image always
 * fills the full width (never any left/right black bars). Behaviour by
 * orientation:
 *  - Landscape/square: height capped at SINGLE_IMAGE_MAX_HEIGHT; images taller
 *    than the cap are cropped top/bottom (object-cover).
 *  - Portrait (height > width): no height cap — the frame grows to the real
 *    ratio so the whole image shows, uncropped and without side bars (the
 *    bubble is correspondingly tall).
 * Used by single-image bubbles and 2-image albums.
 *
 * The ratio is taken from backend width/height when present (no layout shift),
 * then refined from the loaded image's intrinsic size so it works even when the
 * backend omits those fields. See `constants/media.ts`.
 */
export function AdaptiveImageFrame({
  attachment,
  src,
  fallbackSrc,
  onOpen,
  ariaLabel,
  children,
}: {
  attachment: Attachment;
  /** Display source; defaults to the attachment's full url. */
  src?: string;
  fallbackSrc?: (string | undefined)[];
  onOpen: () => void;
  ariaLabel: string;
  /** Overlays rendered on top of the image (download pill, "+N", etc.). */
  children?: ReactNode;
}) {
  const [ratio, setRatio] = useState<number | undefined>(
    attachment.width && attachment.height
      ? attachment.width / attachment.height
      : undefined,
  );

  const isPortrait = ratio !== undefined && ratio < 1;

  let frameStyle: CSSProperties | undefined;
  if (ratio !== undefined) {
    frameStyle = isPortrait
      ? // Portrait: follow the real ratio with no cap → full image, full width,
        // no crop, no side bars (the frame is tall).
        { aspectRatio: String(ratio) }
      : // Landscape/square: real ratio, capped height, cropped top/bottom past it.
        { aspectRatio: String(ratio), maxHeight: SINGLE_IMAGE_MAX_HEIGHT };
  }

  return (
    <div
      className={`relative w-full overflow-hidden bg-black ${
        ratio ? "" : SINGLE_IMAGE_FALLBACK_HEIGHT_CLASS
      }`}
      style={frameStyle}
    >
      <button
        type="button"
        onClick={onOpen}
        className="block h-full w-full"
        aria-label={ariaLabel}
      >
        <BubbleImage
          src={src ?? attachment.url}
          fallbackSrc={fallbackSrc}
          loading="lazy"
          className="h-full w-full object-cover"
          onNaturalSize={(w, h) => {
            if (w && h) setRatio(w / h);
          }}
        />
      </button>
      {children}
    </div>
  );
}
