#!/usr/bin/env node

import fs from 'node:fs';
import path from 'node:path';

const root = process.cwd();
const envPath = path.join(root, '.env.local');
const outputDir = path.join(root, 'public', 'style-previews');

function loadEnvFile(filePath) {
  if (!fs.existsSync(filePath)) return;
  for (const line of fs.readFileSync(filePath, 'utf8').split(/\r?\n/)) {
    const match = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)=(.*)\s*$/);
    if (!match) continue;
    const [, key, rawValue] = match;
    if (process.env[key]) continue;
    process.env[key] = rawValue.replace(/^['"]|['"]$/g, '');
  }
}

const styles = [
  {
    id: 'none',
    label: 'neutral toy concept',
    prompt: 'neutral original toy mascot concept preview, small rounded collectible character, clean studio light, no text, no logo, no watermark, square UI thumbnail',
  },
  {
    id: 'plush',
    label: 'plush toy',
    prompt: 'plush toy style preview, soft fuzzy fabric original rounded mascot, stitched details, warm studio light, no text, no logo, no watermark, square UI thumbnail',
  },
  {
    id: 'mecha',
    label: 'mecha toy',
    prompt: 'mecha toy style preview, original rounded robot collectible, polished armor panels, tiny mechanical joints, clean dramatic light, no text, no logo, no watermark, square UI thumbnail',
  },
  {
    id: 'kawaii',
    label: 'kawaii toy',
    prompt: 'kawaii toy style preview, original cute rounded mascot, soft pastel colors, friendly expression, clean studio background, no text, no logo, no watermark, square UI thumbnail',
  },
  {
    id: 'blueprint',
    label: 'patent blueprint',
    prompt: 'patent blueprint style preview, original toy mascot shown as clean white technical line art on deep blue blueprint background, no readable text, no logo, no watermark, square UI thumbnail',
  },
  {
    id: 'cyber',
    label: 'cyberpunk toy',
    prompt: 'cyberpunk toy style preview, original rounded collectible mascot, neon rim light, glossy dark materials, futuristic display glow, no text, no logo, no watermark, square UI thumbnail',
  },
  {
    id: 'minimal',
    label: 'minimal toy',
    prompt: 'minimal toy style preview, original rounded mascot, simple geometric silhouette, restrained colors, premium clean product render, no text, no logo, no watermark, square UI thumbnail',
  },
];

async function imageToBuffer(payload, apiKey) {
  const first = payload?.data?.[0];
  if (!first) throw new Error('missing image data');
  if (first.b64_json) return Buffer.from(first.b64_json, 'base64');
  if (first.url) {
    const res = await fetch(first.url, { headers: { Authorization: `Bearer ${apiKey}` } });
    if (!res.ok) throw new Error(`image url fetch ${res.status}: ${await res.text()}`);
    return Buffer.from(await res.arrayBuffer());
  }
  throw new Error('image payload has no b64_json or url');
}

async function main() {
  loadEnvFile(envPath);
  const apiKey = process.env.OPENAI_API_KEY;
  if (!apiKey) throw new Error('OPENAI_API_KEY missing');

  const apiBase = process.env.GPT_API_BASE || 'https://api.openai.com/v1';
  const model = process.env.GPT_IMAGE_MODEL || 'gpt-image-2';
  fs.mkdirSync(outputDir, { recursive: true });

  for (const style of styles) {
    const out = path.join(outputDir, `${style.id}.png`);
    if (fs.existsSync(out) && !process.argv.includes('--force')) {
      console.log(`skip ${style.id}`);
      continue;
    }
    console.log(`generate ${style.id}`);
    const res = await fetch(`${apiBase}/images/generations`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${apiKey}`,
      },
      body: JSON.stringify({
        model,
        prompt: style.prompt,
        n: 1,
        size: '1024x1024',
      }),
    });
    if (!res.ok) throw new Error(`GPT image ${style.id} ${res.status}: ${await res.text()}`);
    fs.writeFileSync(out, await imageToBuffer(await res.json(), apiKey));
  }
}

main().catch(error => {
  console.error(error instanceof Error ? error.message : String(error));
  process.exit(1);
});
