#!/usr/bin/env node
import pg from 'pg';

const { Client } = pg;

const adjectives = ['云朵', '星河', '松风', '月白', '晴川', '青柚', '琥珀', '小满', '竹影', '橘光', '海盐', '霁蓝'];
const nouns = ['画师', '旅人', '造梦家', '观察员', '收藏家', '调色师', '冒险家', '灵感师', '策展人', '星愿者', '小导演', '光影客'];
const kinds = ['person', 'cat', 'bear', 'bunny', 'fox'];
const palettes = [
  ['#7dd3fc', '#c084fc', '#fdf2f8', '#0f172a'],
  ['#fbbf24', '#fb7185', '#fff7ed', '#3b1d0f'],
  ['#86efac', '#38bdf8', '#f0fdf4', '#052e2b'],
  ['#f9a8d4', '#a78bfa', '#fdf4ff', '#312e81'],
  ['#fdba74', '#60a5fa', '#eff6ff', '#1e3a8a'],
];

function hashString(value) {
  let hash = 2166136261;
  for (let i = 0; i < value.length; i += 1) {
    hash ^= value.charCodeAt(i);
    hash = Math.imul(hash, 16777619);
  }
  return hash >>> 0;
}

function pick(items, seed, offset = 0) {
  return items[(seed + offset) % items.length];
}

function escapeXml(value) {
  return value.replace(/[&<>"']/g, char => ({
    '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&apos;',
  })[char] || char);
}

function generateChineseNickname(seedValue) {
  const seed = hashString(seedValue);
  return `${pick(adjectives, seed)}${pick(nouns, seed >>> 5)}${String(seed % 1000).padStart(3, '0')}`;
}

function generateDefaultAvatarDataUrl(seedValue, labelValue) {
  const seed = hashString(seedValue);
  const [primary, secondary, surface, ink] = pick(palettes, seed);
  const kind = pick(kinds, seed >>> 3);
  const label = escapeXml(String(labelValue || '').trim().slice(0, 1) || '妙');
  const blush = seed % 2 === 0 ? '#fb7185' : '#f472b6';
  const earLeft = kind === 'cat'
    ? '<path d="M76 92 L110 44 L126 108 Z" fill="url(#face)" stroke="rgba(255,255,255,.6)" stroke-width="5"/>'
    : kind === 'bunny'
      ? '<ellipse cx="105" cy="54" rx="19" ry="48" fill="url(#face)" transform="rotate(-16 105 54)"/>'
      : kind === 'bear' || kind === 'fox'
        ? '<circle cx="103" cy="86" r="26" fill="url(#face)" stroke="rgba(255,255,255,.58)" stroke-width="5"/>'
        : '';
  const earRight = kind === 'cat'
    ? '<path d="M180 108 L196 44 L232 92 Z" fill="url(#face)" stroke="rgba(255,255,255,.6)" stroke-width="5"/>'
    : kind === 'bunny'
      ? '<ellipse cx="205" cy="54" rx="19" ry="48" fill="url(#face)" transform="rotate(16 205 54)"/>'
      : kind === 'bear' || kind === 'fox'
        ? '<circle cx="213" cy="86" r="26" fill="url(#face)" stroke="rgba(255,255,255,.58)" stroke-width="5"/>'
        : '';
  const nose = kind === 'person'
    ? `<path d="M160 147 c-7 10 -1 18 10 16" fill="none" stroke="${ink}" stroke-width="5" stroke-linecap="round" opacity=".44"/>`
    : `<path d="M151 151 q9 -8 18 0 q-9 11 -18 0Z" fill="${ink}" opacity=".72"/>`;
  const hair = kind === 'person'
    ? `<path d="M90 133 c16 -58 58 -83 112 -57 c29 14 40 44 35 70 c-23 -20 -42 -17 -66 -36 c-26 26 -52 28 -81 23Z" fill="${secondary}" opacity=".92"/>`
    : '';
  const muzzle = kind === 'person' ? '' : '<ellipse cx="160" cy="165" rx="39" ry="26" fill="rgba(255,255,255,.54)"/>';
  const whiskers = kind === 'cat' || kind === 'fox'
    ? `<path d="M101 155 h36 M101 174 h36 M183 155 h36 M183 174 h36" stroke="${ink}" stroke-width="4" stroke-linecap="round" opacity=".38"/>`
    : '';
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 320"><defs><radialGradient id="bg" cx="34%" cy="25%" r="78%"><stop offset="0%" stop-color="${surface}"/><stop offset="48%" stop-color="${primary}"/><stop offset="100%" stop-color="${secondary}"/></radialGradient><linearGradient id="face" x1="72" y1="64" x2="236" y2="246" gradientUnits="userSpaceOnUse"><stop stop-color="#fff8f0"/><stop offset=".58" stop-color="#ffd7b5"/><stop offset="1" stop-color="#f8a978"/></linearGradient><filter id="soft" x="-30%" y="-30%" width="160%" height="160%"><feDropShadow dx="0" dy="18" stdDeviation="16" flood-color="#111827" flood-opacity=".22"/></filter></defs><rect width="320" height="320" rx="80" fill="url(#bg)"/><circle cx="254" cy="58" r="34" fill="rgba(255,255,255,.34)"/><circle cx="68" cy="250" r="44" fill="rgba(255,255,255,.20)"/><g filter="url(#soft)">${earLeft}${earRight}<circle cx="160" cy="153" r="83" fill="url(#face)" stroke="rgba(255,255,255,.68)" stroke-width="6"/>${hair}<circle cx="128" cy="144" r="9" fill="${ink}"/><circle cx="192" cy="144" r="9" fill="${ink}"/><circle cx="125" cy="142" r="3" fill="#fff"/><circle cx="189" cy="142" r="3" fill="#fff"/>${muzzle}${nose}${whiskers}<path d="M137 184 q23 18 46 0" fill="none" stroke="${ink}" stroke-width="6" stroke-linecap="round" opacity=".62"/><circle cx="105" cy="169" r="13" fill="${blush}" opacity=".30"/><circle cx="215" cy="169" r="13" fill="${blush}" opacity=".30"/></g><g transform="translate(218 222)"><circle cx="34" cy="34" r="30" fill="rgba(255,255,255,.78)" stroke="rgba(255,255,255,.86)" stroke-width="3"/><text x="34" y="45" text-anchor="middle" font-size="30" font-weight="800" font-family="Arial, sans-serif" fill="${ink}">${label}</text></g></svg>`;
  return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
}

async function main() {
  const connectionString = process.env.LOCAL_DB_URL || process.env.DATABASE_URL;
  if (!connectionString) throw new Error('LOCAL_DB_URL or DATABASE_URL is required');

  const client = new Client({ connectionString });
  await client.connect();
  try {
    await client.query('ALTER TABLE profiles ADD COLUMN IF NOT EXISTS display_nickname VARCHAR(128)');
    const result = await client.query(`
      SELECT id, email, nickname, display_nickname, avatar_url
      FROM profiles
      WHERE display_nickname IS NULL OR display_nickname = ''
         OR avatar_url IS NULL OR avatar_url = ''
      ORDER BY created_at ASC
    `);

    let nicknameCount = 0;
    let avatarCount = 0;
    for (const row of result.rows) {
      const displayNickname = row.display_nickname || row.nickname || generateChineseNickname(`${row.id}:${row.email}`);
      const avatarUrl = row.avatar_url || generateDefaultAvatarDataUrl(`${row.id}:${row.email}`, displayNickname);
      if (!row.display_nickname) nicknameCount += 1;
      if (!row.avatar_url) avatarCount += 1;
      await client.query(
        `UPDATE profiles
         SET display_nickname = COALESCE(NULLIF(display_nickname, ''), $2),
             avatar_url = COALESCE(NULLIF(avatar_url, ''), $3),
             updated_at = NOW()
         WHERE id = $1`,
        [row.id, displayNickname, avatarUrl],
      );
    }
    console.log(JSON.stringify({ scanned: result.rowCount, displayNicknamesBackfilled: nicknameCount, avatarsBackfilled: avatarCount }));
  } finally {
    await client.end();
  }
}

main().catch(error => {
  console.error(error);
  process.exit(1);
});
