import type { GenImage } from './types';

export type Provider = 'mock' | 'gpt';

export const GPT_TEXT_MODEL = process.env.GPT_TEXT_MODEL || 'gpt-5.5';
export const GPT_IMAGE_MODEL = process.env.GPT_IMAGE_MODEL || 'gpt-image-1';
const GPT_API_BASE = process.env.GPT_API_BASE || 'https://api.openai.com/v1';

export function detectProvider(): Provider {
  return process.env.OPENAI_API_KEY ? 'gpt' : 'mock';
}

// Mock：返回 SVG 占位图（data URL），不真的生图
export async function generateMock(opts: {
  sessionId: string;
  prompt: string;
  count: number;
}): Promise<GenImage[]> {
  const palette = ['#ff6b35', '#3b82f6', '#10b981', '#a855f7', '#f59e0b', '#ec4899', '#06b6d4', '#84cc16', '#ef4444'];
  return Array.from({ length: opts.count }).map((_, i) => {
    const c = palette[i % palette.length];
    const c2 = palette[(i + 3) % palette.length];
    const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
      <defs><linearGradient id="g${i}" x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" stop-color="${c}"/><stop offset="100%" stop-color="${c2}"/>
      </linearGradient></defs>
      <rect width="512" height="512" fill="url(#g${i})"/>
      <circle cx="256" cy="220" r="120" fill="white" opacity="0.85"/>
      <ellipse cx="220" cy="200" rx="10" ry="14" fill="#111"/>
      <ellipse cx="292" cy="200" rx="10" ry="14" fill="#111"/>
      <path d="M210 250 Q256 285 302 250" stroke="#111" stroke-width="6" fill="none" stroke-linecap="round"/>
      <rect x="160" y="340" width="192" height="130" rx="20" fill="white" opacity="0.85"/>
      <text x="256" y="500" text-anchor="middle" font-family="monospace" font-size="20" font-weight="bold" fill="white">MOCK #${i + 1}</text>
    </svg>`;
    const dataUrl = `data:image/svg+xml;base64,${Buffer.from(svg).toString('base64')}`;
    return {
      id: `img_${opts.sessionId}_${i}`,
      url: dataUrl,
      prompt: opts.prompt,
      status: 'pending' as const,
      meta: { provider: 'mock', index: i },
    };
  });
}

function readImageBase64(payload: unknown): string {
  const data = payload as { data?: Array<{ b64_json?: string; url?: string }> };
  const first = data.data?.[0];
  if (!first) throw new Error('GPT image response missing data');
  if (first.b64_json) return first.b64_json;
  throw new Error('GPT image response missing b64_json');
}

export async function generateGptImages(opts: {
  sessionId: string;
  prompt: string;
  count: number;
  refImages?: string[];
}): Promise<GenImage[]> {
  const key = process.env.OPENAI_API_KEY;
  if (!key) throw new Error('OPENAI_API_KEY missing');

  const refHint = opts.refImages?.length
    ? `\n参考图 URL，用于保持角色一致：\n${opts.refImages.join('\n')}`
    : '';

  const calls = Array.from({ length: opts.count }).map(async (_, i) => {
    const res = await fetch(`${GPT_API_BASE}/images/generations`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${key}`,
      },
      body: JSON.stringify({
        model: GPT_IMAGE_MODEL,
        prompt: `${opts.prompt}${refHint}`,
        n: 1,
        size: '1024x1024',
        response_format: 'b64_json',
      }),
    });
    if (!res.ok) throw new Error(`GPT image ${res.status}: ${await res.text()}`);
    const data = await res.json();
    return {
      id: `img_${opts.sessionId}_${i}`,
      url: `data:image/png;base64,${readImageBase64(data)}`,
      prompt: opts.prompt,
      status: 'pending' as const,
      meta: { provider: 'gpt', model: GPT_IMAGE_MODEL, index: i },
    };
  });

  return Promise.all(calls);
}

export async function generateGptJson<T>(opts: {
  prompt: string;
  fallback: T;
}): Promise<T> {
  const key = process.env.OPENAI_API_KEY;
  if (!key) return opts.fallback;

  const res = await fetch(`${GPT_API_BASE}/responses`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${key}`,
    },
    body: JSON.stringify({
      model: GPT_TEXT_MODEL,
      input: opts.prompt,
      text: { format: { type: 'json_object' } },
    }),
  });
  if (!res.ok) throw new Error(`GPT text ${res.status}: ${await res.text()}`);
  const data = await res.json() as {
    output_text?: string;
    output?: Array<{ content?: Array<{ text?: string }> }>;
  };
  const text = data.output_text || data.output?.flatMap(item => item.content ?? []).map(item => item.text ?? '').join('') || '';
  return text.trim() ? JSON.parse(text) as T : opts.fallback;
}
