/**
 * HTTP clients for the imajin classifier stack.
 *
 * Two services, both reached through the Model Boss coordinator:
 *   - imajin-moderator (POST /scan)   → blocklist / NSFW scoring
 *   - imajin-semantic  (POST /detect) → CLIP-like multi-tag scoring
 *
 * Both accept image_base64. We base64 the photo bytes on the @mac-sync side
 * (storage helpers already give us a Buffer) instead of presigning URLs,
 * matching the pattern in imajin-media-gallery's classification.module.
 */

import { loadConfig } from '@/app/config';

export interface ModeratorResult {
  readonly safe: boolean;
  readonly score: number;
  readonly categories: Readonly<Record<string, number>>;
  readonly message?: string | null;
}

export interface SiglipResult {
  /** Map of requested tag -> score in [0, 1]. */
  readonly scores: Readonly<Record<string, number>>;
  /** The top label, if the service computes one. */
  readonly top_label?: string | null;
  readonly message?: string | null;
}

const DEFAULT_TIMEOUT_MS = 30_000;

async function postJson<TReq, TRes>(
  baseUrl: string,
  serviceName: string,
  path: string,
  body: TReq,
  timeoutMs = DEFAULT_TIMEOUT_MS,
): Promise<TRes> {
  const url = `${baseUrl.replace(/\/$/, '')}${path}`;
  try {
    const res = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'X-Client-Id': 'mac-sync-server' },
      body: JSON.stringify(body),
      signal: AbortSignal.timeout(timeoutMs),
    });
    if (!res.ok) {
      const text = await res.text().catch(() => '');
      throw new Error(`${serviceName} ${path} -> ${res.status}: ${text.slice(0, 200)}`);
    }
    return (await res.json()) as TRes;
  } catch (err) {
    if (err instanceof Error) throw err;
    throw new Error(`${serviceName} ${path} failed: ${String(err)}`);
  }
}

export async function classifyWithModerator(imageBase64: string): Promise<ModeratorResult> {
  const { IMAJIN_MODERATOR_URL } = loadConfig();
  return postJson<{ image_base64: string; skip_hash_check: boolean }, ModeratorResult>(
    IMAJIN_MODERATOR_URL,
    'imajin-moderator',
    '/scan',
    { image_base64: imageBase64, skip_hash_check: true },
  );
}

export async function classifyWithSiglip(
  imageBase64: string,
  requestedFilters: readonly string[],
): Promise<SiglipResult> {
  const { IMAJIN_SEMANTIC_URL } = loadConfig();
  return postJson<{ image_base64: string; requested_filters: readonly string[] }, SiglipResult>(
    IMAJIN_SEMANTIC_URL,
    'imajin-semantic',
    '/detect',
    { image_base64: imageBase64, requested_filters: requestedFilters },
  );
}
