import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

const CDN_BASE = "https://yefranchisees.b-cdn.net/frontend"

/**
 * Widths Next's image optimizer will accept - `deviceSizes` plus `imageSizes`
 * from the defaults. Anything else answers 400, so a requested width is rounded
 * up to the next one of these.
 */
const OPTIMIZER_WIDTHS = [
  16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840,
] as const;

/**
 * Route a remote image through Next's optimizer.
 *
 * `next/image` does this by itself, but plenty of images here are CSS
 * `background-image` values or plain `<img>` tags, which the optimizer never
 * sees. Those were being served at full size - a 1.7 MB upload into a 300px
 * slot - because BunnyCDN's Optimizer is not enabled on the pull zone either,
 * so nothing between the origin and the browser was resizing anything.
 *
 * Pointing the same `src` at this keeps the markup untouched and still gets a
 * resized WebP back.
 *
 * Returns the URL unchanged when optimizing would be pointless or harmful:
 * SVG is in the optimizer's BYPASS_TYPES and comes back byte-for-byte, and
 * video/data URLs are not images at all.
 */
export function optimizedImage(
  url: string | null | undefined,
  width = 1920,
  quality = 75,
): string {
  if (!url) return url ?? "";
  if (url.startsWith("data:") || url.startsWith("blob:")) return url;
  if (/\.svg($|\?)/i.test(url)) return url;
  if (/\.(mp4|webm|ogg|mov|m4v)($|\?)/i.test(url)) return url;

  // Some callers hold an already-encoded URL ("bg%20(14).png"). Encoding that
  // again turns %20 into %2520 and the optimizer fetches a path that does not
  // exist, so decode first when the string looks escaped. A URL carrying a
  // literal % that is not an escape sequence is left alone.
  let raw = url;
  if (/%[0-9A-Fa-f]{2}/.test(url)) {
    try {
      raw = decodeURIComponent(url);
    } catch {
      raw = url;
    }
  }

  const w = OPTIMIZER_WIDTHS.find((candidate) => candidate >= width) ?? 3840;

  // `encodeURIComponent` leaves ( ) and ' alone, and several uploads here are
  // named "bg (7) (1).png". Dropped into an unquoted CSS `url(...)` those
  // parentheses close the token early and the whole declaration is discarded -
  // which is how the card ribbons vanished. Escaping them keeps the value safe
  // in `url(...)`, `url('...')` and an <img> src alike; the optimizer decodes
  // them back before fetching.
  const encoded = encodeURIComponent(raw)
    .replace(/\(/g, "%28")
    .replace(/\)/g, "%29")
    .replace(/'/g, "%27");

  return `/_next/image?url=${encoded}&w=${w}&q=${quality}`;
}

export function withCDN(imagePath: string): string {
  if (!imagePath) return imagePath
  // If it already starts with http/https, return as-is
  if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
    return imagePath
  }
  // Ensure the path starts with /
  const normalizedPath = imagePath.startsWith("/") ? imagePath : `/${imagePath}`
  return `${CDN_BASE}${normalizedPath}`
}
