import { apiJson } from "../http.ts";

interface SegmentDescription {
  segment: { id: string; text: string; textVersion: number };
  voice: string;
  audio: { url: string } | null;
}

export async function describeSegmentAudio(segmentId: string, voice: string): Promise<SegmentDescription> {
  return apiJson<SegmentDescription>(
    `/api/segments/${encodeURIComponent(segmentId)}/audio?describe=1&voice=${encodeURIComponent(voice)}`,
  );
}

export async function uploadSegmentAudio(input: {
  segmentId: string;
  textVersion: number;
  voice: string;
  audio: Blob;
  durationMs?: number | null;
}): Promise<{ url: string }> {
  const result = await apiJson<{ audio: { url: string } }>(
    `/api/segments/${encodeURIComponent(input.segmentId)}/audio`,
    {
      method: "PUT",
      headers: {
        "content-type": "audio/mpeg",
        "x-text-version": String(input.textVersion),
        "x-voice": input.voice,
        ...(input.durationMs === undefined || input.durationMs === null
          ? {}
          : { "x-duration-ms": String(Math.round(input.durationMs)) }),
      },
      body: input.audio,
    },
  );
  return { url: result.audio.url };
}

export async function ensureSegmentAudio(dependencies: {
  segmentId: string;
  voice: string;
  rate: number;
  describe?: (segmentId: string, voice: string) => Promise<SegmentDescription>;
  synthesize(input: { text: string; voice: string; rate: number }): Promise<Blob>;
  upload?: typeof uploadSegmentAudio;
}): Promise<{ url: string; generated: boolean }> {
  const describe = dependencies.describe ?? describeSegmentAudio;
  const upload = dependencies.upload ?? uploadSegmentAudio;
  const description = await describe(dependencies.segmentId, dependencies.voice);
  if (description.audio) return { url: description.audio.url, generated: false };
  const audio = await dependencies.synthesize({
    text: description.segment.text,
    voice: description.voice,
    rate: dependencies.rate,
  });
  const stored = await upload({
    segmentId: dependencies.segmentId,
    textVersion: description.segment.textVersion,
    voice: description.voice,
    audio,
  });
  return { url: stored.url, generated: true };
}
