/**
 * Luma AI Video Generation Provider
 *
 * Integrates with the Luma AI API to generate videos from text prompts.
 * Supports multi-key failover and async polling for video completion.
 *
 * API Reference: https://docs.lumalabs.ai/docs/api
 */

import { getAIConfig, getConfiguredKeyStats, markKeyHealth, sleep } from '../../utils/aiProvider';

// ============================================
// TYPES
// ============================================

export interface VideoGenerationResult {
  videoUrl: string;
  thumbnailUrl?: string;
  duration?: string;
  revisedPrompt?: string;
  model: string;
  provider: string;
  generationId: string;
  latencyMs: number;
}

export interface VideoGenerationOptions {
  model?: string;
  aspectRatio?: string;  // e.g., '16:9', '9:16', '1:1'
  duration?: string;      // e.g., '5s', '10s'
  loop?: boolean;
  keyOverride?: any;
  userId?: string;
}

// ============================================
// LUMA AI API INTEGRATION
// ============================================

const LUMA_API_BASE = 'https://api.lumalabs.ai';

/**
 * Get the active Luma API key from configuration.
 */
async function getLumaApiKey(keyOverride?: any): Promise<{ key: string; url: string; model: string } | null> {
  if (keyOverride?.key) {
    return {
      key: keyOverride.key,
      url: keyOverride.url || process.env.LUMA_API_URL || `${LUMA_API_BASE}/v1`,
      model: keyOverride.model || 'ray-2',
    };
  }

  const config = await getAIConfig(keyOverride?._userId);
  const keyList = config.LUMA_KEY_LIST || [];

  // Try keys in order: active+healthy first, then any healthy key
  for (const keyEntry of keyList) {
    if (keyEntry.key && keyEntry.health !== 'inactive') {
      return {
        key: keyEntry.key,
        url: config.LUMA_API_URL || `${LUMA_API_BASE}/v1`,
        model: config.LUMA_MODEL || 'ray-2',
      };
    }
  }

  // Fall back to the single active key
  if (config.LUMA_API_KEY) {
    return {
      key: config.LUMA_API_KEY,
      url: config.LUMA_API_URL || `${LUMA_API_BASE}/v1`,
      model: config.LUMA_MODEL || 'ray-2',
    };
  }

  return null;
}

/**
 * Submit a video generation request to Luma AI.
 * Returns the generation ID for polling.
 */
async function submitLumaGeneration(
  prompt: string,
  apiKey: string,
  apiUrl: string,
  model: string,
  options: VideoGenerationOptions = {},
): Promise<string> {
  const url = `${apiUrl}/generations`;

  const body: Record<string, any> = {
    prompt,
    model: model || options.model || 'ray-2',
  };

  if (options.aspectRatio) {
    body.aspect_ratio = options.aspectRatio;
  }
  if (options.loop !== undefined) {
    body.loop = options.loop;
  }

  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });

  if (!response.ok) {
    const errorText = await response.text().catch(() => '');
    throw new Error(`Luma AI API error (${response.status}): ${errorText || response.statusText}`);
  }

  const data: any = await response.json();
  const generationId = data?.id || data?.generation_id;

  if (!generationId) {
    throw new Error(`Luma AI API did not return a generation ID. Response: ${JSON.stringify(data).slice(0, 500)}`);
  }

  return generationId;
}

/**
 * Poll Luma AI for video generation completion.
 * Returns the video URL when the generation is complete.
 */
async function pollLumaGeneration(
  generationId: string,
  apiKey: string,
  apiUrl: string,
  maxAttempts: number = 120,
  intervalMs: number = 5000,
): Promise<{ videoUrl: string; thumbnailUrl?: string; state: string }> {
  const url = `${apiUrl}/generations/${generationId}`;

  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${apiKey}`,
      },
    });

    if (!response.ok) {
      if (response.status === 404) {
        throw new Error(`Luma AI generation ${generationId} not found.`);
      }
      // Retry on transient errors
      if (response.status >= 500) {
        await sleep(intervalMs);
        continue;
      }
      const errorText = await response.text().catch(() => '');
      throw new Error(`Luma AI polling error (${response.status}): ${errorText || response.statusText}`);
    }

    const data: any = await response.json();
    const state = data?.state || data?.status || '';

    if (state === 'completed' || state === 'complete') {
      const videoUrl = data?.assets?.video || data?.video_url || data?.url || '';
      const thumbnailUrl = data?.assets?.thumbnail || data?.thumbnail_url || '';
      if (!videoUrl) {
        throw new Error(`Luma AI generation completed but no video URL found. Response: ${JSON.stringify(data).slice(0, 500)}`);
      }
      return { videoUrl, thumbnailUrl, state };
    }

    if (state === 'failed' || state === 'error') {
      const errorMsg = data?.failure_reason || data?.error || 'Unknown error';
      throw new Error(`Luma AI generation failed: ${errorMsg}`);
    }

    // Still processing — wait and retry
    await sleep(intervalMs);
  }

  throw new Error(`Luma AI generation timed out after ${maxAttempts} polling attempts (${Math.round(maxAttempts * intervalMs / 1000)}s). Generation ID: ${generationId}`);
}

// ============================================
// MAIN EXPORT: Generate Video with Luma AI
// ============================================

/**
 * Generate a video using Luma AI with multi-key failover.
 *
 * @param prompt - The text prompt describing the video to generate
 * @param options - Video generation options (model, aspect ratio, duration, etc.)
 * @returns VideoGenerationResult with the video URL and metadata
 * @throws Error if no API key is configured or generation fails
 */
export async function generateVideoWithLuma(
  prompt: string,
  options: VideoGenerationOptions = {},
): Promise<VideoGenerationResult> {
  const startTime = Date.now();

  // Get the API key configuration
  const keyConfig = await getLumaApiKey(options.keyOverride);
  if (!keyConfig) {
    const stats = await getConfiguredKeyStats(null, 'luma');
    if (stats.total > 0 && stats.inactive === stats.total) {
      throw new Error('All Luma AI API keys are currently inactive. Please check your Super Admin settings and activate at least one key.');
    }
    throw new Error('No Luma AI API key configured. Add one in Super Admin > AI Configuration > Luma AI.');
  }

  const { key: apiKey, url: apiUrl, model: defaultModel } = keyConfig;
  const model = options.model || defaultModel || 'ray-2';

  // Try key failover: start with the active key, then try others if it fails
  const config = await getAIConfig(options.userId);
  const keyList = config.LUMA_KEY_LIST || [];
  const keysToTry = [
    ...(keyList.filter(k => k.key && k.health !== 'inactive' && k.isActive)),
    ...(keyList.filter(k => k.key && k.health !== 'inactive' && !k.isActive)),
  ];

  // If no key list, try the single key
  if (keysToTry.length === 0) {
    keysToTry.push({ key: apiKey, isActive: true, health: 'active' });
  }

  let lastError: Error | null = null;

  for (const keyEntry of keysToTry) {
    const tryKey = keyEntry.key;
    try {
      // Submit the generation request
      const generationId = await submitLumaGeneration(prompt, tryKey, apiUrl, model, options);

      // Mark key as active (healthy)
      try {
        await markKeyHealth('luma', tryKey, 'active', undefined, undefined);
      } catch { /* non-fatal */ }

      // Poll for completion
      const result = await pollLumaGeneration(generationId, tryKey, apiUrl);

      return {
        videoUrl: result.videoUrl,
        thumbnailUrl: result.thumbnailUrl,
        model,
        provider: 'luma',
        generationId,
        latencyMs: Date.now() - startTime,
      };
    } catch (err: any) {
      lastError = err;
      const errMsg = err.message || '';
      console.warn(`[LumaVideo] Key ${tryKey.slice(-4)} failed: ${errMsg}`);

      // Mark key as inactive if it's an auth/key-specific error
      if (errMsg.includes('401') || errMsg.includes('403') || errMsg.includes('unauthorized') || errMsg.includes('invalid api key') || errMsg.includes('invalid key')) {
        try {
          await markKeyHealth('luma', tryKey, 'inactive', errMsg, undefined);
        } catch { /* non-fatal */ }
      }

      // Try next key
      continue;
    }
  }

  throw lastError || new Error('All Luma AI API keys failed. Please check your configuration.');
}

/**
 * Get the video provider for a given model name.
 */
export function getVideoProviderForModel(model: string): 'luma' {
  // Currently only Luma is supported; add more providers here as they're added
  return 'luma';
}