import { z } from 'zod';

// ── Provider interface ──────────────────────────────────────

/** Audio input passed to a transcription provider. */
export interface TranscriptionInput {
  /** Raw audio bytes. */
  audio: ArrayBuffer;
  /** Filename with extension (used for content-type inference). */
  filename: string;
  /** ISO 639-1 language hint. */
  language?: string;
  /** Prompt to guide transcription style. */
  prompt?: string;
  /** Model override (provider-specific, e.g. 'whisper-1' for OpenAI). */
  model?: string;
}

/** Result from a transcription provider. */
export interface TranscriptionResult {
  /** The transcribed text. */
  text: string;
  /** Detected or specified language code. */
  language: string | null;
  /** Duration of the audio in seconds (when available). */
  durationSeconds: number | null;
  /** Provider-specific model identifier. */
  model: string;
}

/** Cloud-agnostic speech-to-text provider. */
export interface TranscriptionProvider {
  /** Transcribe audio to text. */
  transcribe(input: TranscriptionInput): Promise<TranscriptionResult>;
  /** Check if the provider is configured with valid credentials. */
  isConfigured(): boolean;
}

export type STTProviderType = 'openai' | 'azure' | 'mock';

// ── Transcription request schema ────────────────────────────────

export const TranscribeRequestSchema = z.object({
  /** URL of the audio file (e.g. Azure Blob SAS URL). */
  audioUrl: z.string().url('audioUrl must be a valid URL'),
  /** Override the Whisper model (default: whisper-1). */
  model: z.string().optional(),
  /** ISO 639-1 language hint (e.g. 'en', 'es'). Improves accuracy. */
  language: z.string().max(5).optional(),
  /** Optional prompt to guide the transcription style. */
  prompt: z.string().max(1000).optional(),
  /** Response format: 'text' returns plain text, 'verbose_json' returns word-level timestamps. */
  responseFormat: z.enum(['text', 'json', 'verbose_json']).default('text'),
  /** Product ID for scoping / rate limiting. */
  productId: z.string().optional(),
});

export type TranscribeRequest = z.infer<typeof TranscribeRequestSchema>;

// ── Transcription response ──────────────────────────────────────

export interface TranscribeResponse {
  /** The transcribed text. */
  text: string;
  /** Detected or specified language code. */
  language: string | null;
  /** Duration of the audio in seconds (when available). */
  durationSeconds: number | null;
  /** Whisper model used. */
  model: string;
  /** Processing time in milliseconds. */
  durationMs: number;
  /** Request ID for tracing. */
  requestId?: string;
}

// ── Supported audio formats ─────────────────────────────────────

export const SUPPORTED_AUDIO_TYPES = new Set([
  'audio/mpeg', // .mp3
  'audio/mp4', // .m4a
  'audio/mp4a-latm',
  'audio/x-m4a',
  'audio/wav', // .wav
  'audio/x-wav',
  'audio/webm', // .webm
  'audio/ogg', // .ogg
  'audio/flac', // .flac
  'video/mp4', // .mp4 (video with audio track)
]);

/** Max audio file size: 25 MB (OpenAI Whisper limit). */
export const MAX_AUDIO_SIZE_BYTES = 25 * 1024 * 1024;

// ── Filename helper (shared by route + providers) ─────────────

export function deriveFilename(url: string, contentType: string | null): string {
  try {
    const pathname = new URL(url).pathname;
    const lastSegment = pathname.split('/').pop();
    if (lastSegment && /\.(mp3|m4a|wav|webm|ogg|flac|mp4|mpeg|mpga)$/i.test(lastSegment)) {
      return lastSegment;
    }
  } catch {
    // URL parsing failed — use fallback
  }

  const extMap: Record<string, string> = {
    'audio/mpeg': 'audio.mp3',
    'audio/mp4': 'audio.m4a',
    'audio/mp4a-latm': 'audio.m4a',
    'audio/x-m4a': 'audio.m4a',
    'audio/wav': 'audio.wav',
    'audio/x-wav': 'audio.wav',
    'audio/webm': 'audio.webm',
    'audio/ogg': 'audio.ogg',
    'audio/flac': 'audio.flac',
    'video/mp4': 'audio.mp4',
  };

  if (contentType) {
    const base = contentType.split(';')[0].trim().toLowerCase();
    if (extMap[base]) return extMap[base];
  }

  return 'audio.mp3';
}
