/**
 * Maps manifest `file` paths (relative to `frontend/assets/`) to Vite-resolved URLs.
 * Keep in sync with [public/assets/game/manifest.json](../../../../public/assets/game/manifest.json).
 */

const raw = import.meta.glob<string>('../../../assets/**/*.png', {
  eager: true,
  query: '?url',
  import: 'default',
});

function toManifestRelativePath(globModulePath: string): string {
  const n = globModulePath.replace(/\\/g, '/');
  const marker = '/assets/';
  const i = n.indexOf(marker);
  if (i === -1) {
    const parts = n.split('/');
    const ai = parts.lastIndexOf('assets');
    if (ai === -1) return n;
    return parts.slice(ai + 1).join('/');
  }
  return n.slice(i + marker.length);
}

const urlByManifestFile: Record<string, string> = {};
for (const [modPath, url] of Object.entries(raw)) {
  urlByManifestFile[toManifestRelativePath(modPath)] = url;
}

export function resolveGameAssetFile(manifestFile: string): string {
  const url = urlByManifestFile[manifestFile];
  if (!url) {
    throw new Error(`Game asset not found in bundle: ${manifestFile}`);
  }
  return url;
}

export function tryResolveGameAssetFile(manifestFile: string): string | undefined {
  return urlByManifestFile[manifestFile];
}

export interface GameTextureManifestEntry {
  file: string;
  kind: string;
  pixellabTileId?: string;
  pixellabObjectId?: string;
  pixellabCharacterId?: string;
  /** When only one rotation is exported to PNG (e.g. south). */
  rotation?: string;
}

export interface GameTextureManifest {
  version: number;
  note?: string;
  assetsRoot?: string;
  textures: Record<string, GameTextureManifestEntry>;
}

async function fetchManifestJson(resolvedUrl: string): Promise<GameTextureManifest> {
  const res = await fetch(resolvedUrl);
  if (!res.ok) throw new Error(`Game manifest fetch failed: ${res.status}`);
  const manifest = (await res.json()) as GameTextureManifest;
  const textures = manifest?.textures;
  if (
    !manifest ||
    textures === null ||
    typeof textures !== 'object' ||
    Array.isArray(textures) ||
    Object.keys(textures).length === 0
  ) {
    throw new Error('Game manifest missing or empty textures');
  }
  return manifest;
}

export async function fetchGameTextureManifest(url?: string): Promise<GameTextureManifest> {
  const base = import.meta.env.BASE_URL ?? '/';
  const normalizedBase = base.endsWith('/') ? base : `${base}/`;
  const resolvedUrl = url ?? `${normalizedBase}assets/game/manifest.json?version=82`;
  return fetchManifestJson(resolvedUrl);
}
