import type { VideoGenerationRequest, VideoGenerationResponse } from './types';

export const SEEDANCE_MODEL = process.env.SEEDANCE_MODEL || 'doubao-seedance-2-0-260128';
const SEEDANCE_API_BASE = process.env.SEEDANCE_API_BASE || 'https://ark.cn-beijing.volces.com/api/v3';

function durationOrDefault(duration?: number): number {
  return Math.min(Math.max(duration ?? 6, 3), 15);
}

function normalizeStatus(status?: string): VideoGenerationResponse['status'] {
  if (status === 'succeeded') return 'succeeded';
  if (status === 'failed') return 'failed';
  if (status === 'processing' || status === 'running') return 'processing';
  return 'submitted';
}

function publicUrlOrUndefined(url?: string): string | undefined {
  if (!url) return undefined;
  if (url.startsWith('/')) {
    const base = process.env.PUBLIC_APP_URL || process.env.NEXT_PUBLIC_APP_URL;
    if (!base || /^https?:\/\/(localhost|127\.0\.0\.1|\[::1\])/i.test(base)) return undefined;
    return new URL(url, base).toString();
  }
  if (!/^https?:\/\//i.test(url)) return undefined;
  if (/^https?:\/\/(localhost|127\.0\.0\.1|\[::1\])/i.test(url)) return undefined;
  return url;
}

function buildContent(opts: VideoGenerationRequest): Array<Record<string, unknown>> {
  const content: Array<Record<string, unknown>> = [{ type: 'text', text: opts.prompt.trim() }];
  const refs = [...(opts.references ?? [])];
  if (opts.imageUrl) refs.unshift({ type: 'image_url', url: opts.imageUrl, role: 'reference_image' });

  for (const ref of refs) {
    const url = publicUrlOrUndefined(ref.url);
    if (!url) continue;
    if (ref.type === 'image_url') {
      content.push({ type: 'image_url', image_url: { url }, role: ref.role ?? 'reference_image' });
    }
    if (ref.type === 'video_url') {
      content.push({ type: 'video_url', video_url: { url }, role: ref.role ?? 'reference_video' });
    }
    if (ref.type === 'audio_url') {
      content.push({ type: 'audio_url', audio_url: { url }, role: ref.role ?? 'reference_audio' });
    }
  }
  return content;
}

export async function generateSeedanceVideo(opts: VideoGenerationRequest): Promise<VideoGenerationResponse> {
  const key = process.env.SEEDANCE_API_KEY;
  if (!key) throw new Error('SEEDANCE_API_KEY missing');
  if (!opts.prompt?.trim()) throw new Error('prompt required');

  const content = buildContent(opts);
  const body: Record<string, unknown> = {
    model: SEEDANCE_MODEL,
    content,
    generate_audio: opts.generateAudio ?? true,
    ratio: opts.ratio || '16:9',
    duration: durationOrDefault(opts.duration),
    watermark: opts.watermark ?? false,
  };
  if (opts.resolution) body.resolution = opts.resolution;

  const res = await fetch(`${SEEDANCE_API_BASE}/contents/generations/tasks`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${key}`,
    },
    body: JSON.stringify(body),
  });

  if (!res.ok) throw new Error(`Seedance ${res.status}: ${await res.text()}`);
  const raw = await res.json() as {
    id?: string;
    task_id?: string;
    status?: string;
    video_url?: string;
    output?: { video_url?: string; url?: string };
  };

  return {
    provider: 'seedance',
    model: SEEDANCE_MODEL,
    taskId: raw.task_id || raw.id,
    status: normalizeStatus(raw.status),
    videoUrl: raw.video_url || raw.output?.video_url || raw.output?.url,
    raw,
  };
}

export async function getSeedanceVideoTask(taskId: string): Promise<VideoGenerationResponse> {
  const key = process.env.SEEDANCE_API_KEY;
  if (!key) throw new Error('SEEDANCE_API_KEY missing');
  if (!taskId) throw new Error('taskId required');

  const res = await fetch(`${SEEDANCE_API_BASE}/contents/generations/tasks/${encodeURIComponent(taskId)}`, {
    headers: { Authorization: `Bearer ${key}` },
  });

  if (!res.ok) throw new Error(`Seedance ${res.status}: ${await res.text()}`);
  const raw = await res.json() as {
    id?: string;
    task_id?: string;
    status?: string;
    video_url?: string;
    output?: { video_url?: string; url?: string };
  };

  return {
    provider: 'seedance',
    model: SEEDANCE_MODEL,
    taskId: raw.task_id || raw.id || taskId,
    status: normalizeStatus(raw.status),
    videoUrl: raw.video_url || raw.output?.video_url || raw.output?.url,
    raw,
  };
}
