import fs from "node:fs";
import path from "node:path";

const CACHE_PATH = path.join(process.cwd(), ".media-cache.json");

interface MediaSize {
  width: number | null;
  height: number | null;
}

let _cache: Record<string, MediaSize> | null = null;

function loadCache(): Record<string, MediaSize> {
  if (_cache) return _cache;
  try {
    _cache = JSON.parse(fs.readFileSync(CACHE_PATH, "utf-8"));
  } catch {
    _cache = {};
  }
  return _cache ?? {};
}

export function getCachedMediaSize(url: string): MediaSize | null {
  const cache = loadCache();
  if (!url) return null;
  const hit = cache[url];
  if (hit) return hit;
  const filename = url.split("/").pop()?.split("?")[0];
  if (filename && cache[filename]) return cache[filename];
  return null;
}

export function getCachedMediaSizes(): Record<string, MediaSize> {
  return loadCache();
}

export interface MediaSizesMap {
  [url: string]: { width: number | null; height: number | null };
}

export function fetchMediaSizesForContent(content: unknown): MediaSizesMap {
  const cache = loadCache();
  const result: MediaSizesMap = {};
  const urls = extractImageUrls(content);
  for (const url of urls) {
    result[url] = cache[url] || cache[url.split("/").pop()?.split("?")[0] || ""] || { width: null, height: null };
  }
  return result;
}

function extractImageUrls(obj: unknown, found = new Set<string>()): string[] {
  if (!obj || typeof obj !== "object") return [];
  if (Array.isArray(obj)) {
    for (const item of obj) extractImageUrls(item, found);
  } else {
    for (const val of Object.values(obj as Record<string, unknown>)) {
      if (typeof val === "string" && /^https?:\/\/.*\.(jpg|jpeg|png|gif|webp|avif|svg)/i.test(val)) {
        found.add(val);
      } else if (typeof val === "object" || Array.isArray(val)) {
        extractImageUrls(val, found);
      }
    }
  }
  return [...found];
}
