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

/**
 * @param {object} options
 * @param {string} options.pkgRoot 包根目录（含 package.json）
 * @param {string} [options.setupCommand] 一键安装命令提示
 */
export async function runTfdsUpdateCheck({ pkgRoot, setupCommand }) {
  const packageJsonPath = path.join(pkgRoot, 'package.json');
  let localPkg;
  try {
    localPkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
  } catch (error) {
    console.log('\n[tfds-update-check] 无法读取本地 package.json');
    console.log(`  路径：${packageJsonPath}`);
    console.log(`  错误：${error?.message || error}`);
    process.exit(1);
  }

  const packageName = localPkg.name;
  const localVersion = localPkg.version;
  const registryUrl = `https://registry.npmjs.org/${encodeURIComponent(packageName).replace('%2F', '%2f')}`;

  console.log('\n╔══════════════════════════════════════════════════════╗');
  console.log('║        TFDS NPM 版本更新检测                         ║');
  console.log('╚══════════════════════════════════════════════════════╝');

  if (!packageName?.startsWith('@tfdesign/') || !localVersion) {
    console.log('\n[tfds-update-check] 当前脚本不在有效的 @tfdesign/* 包内。');
    console.log(`  读取到的包名：${packageName || '未知'}`);
    console.log(`  读取到的版本：${localVersion || '未知'}\n`);
    process.exit(1);
  }

  let metadata;
  try {
    const response = await fetch(registryUrl, { headers: { accept: 'application/json' } });
    if (!response.ok) throw new Error(`npm registry 返回 ${response.status} ${response.statusText}`);
    metadata = await response.json();
  } catch (error) {
    console.log('\n⚠ 暂时无法连接 npm registry，已跳过线上版本检测。');
    console.log(`  当前本地版本：v ${localVersion}`);
    console.log(`  原因：${error?.message || error}`);
    console.log('\n  不影响继续使用 TFDS。网络恢复后可重新执行：');
    console.log(`    node node_modules/${packageName}/scripts/check-tfds-update.mjs\n`);
    process.exit(0);
  }

  const latestVersion = metadata?.['dist-tags']?.latest;
  const localPublishedAt = metadata?.time?.[localVersion];
  const latestPublishedAt = latestVersion ? metadata?.time?.[latestVersion] : metadata?.time?.modified;

  if (!latestVersion) {
    console.log('\n⚠ 已连接 npm registry，但没有读取到 latest 版本。');
    console.log(`  当前本地版本：v ${localVersion}`);
    console.log('  请稍后重试，或打开 npm 页面手动确认：');
    console.log(`    https://www.npmjs.com/package/${packageName.replace('/', '%2F')}\n`);
    process.exit(0);
  }

  const versionState = compareVersions(localVersion, latestVersion);

  console.log(`\n  包名：${packageName}`);
  console.log(`  当前版本：v ${localVersion}`);
  console.log(`  当前版本更新时间：${formatDateToMinute(localPublishedAt)}`);
  console.log(`  线上最新版本：v ${latestVersion}`);
  console.log(`  最新版本更新时间：${formatDateToMinute(latestPublishedAt)}`);

  if (versionState < 0) {
    console.log('\n⚠ 检测到 TFDS 有新版本，可以选择更新后再生成页面。');
    console.log('\n  升级保护：');
    console.log('    • 更新 npm 包只会更新依赖、主题和 Skill，不应自动修改你的已有页面。');
    console.log('    • 如果已有页面使用的 TFDS 组件在新版中有更新，AI 必须先列出受影响组件与变化范围。');
    console.log('    • 只有你明确确认后，才允许按新版组件样式迁移已有界面。');
    console.log('\n  建议更新命令：');
    console.log(`    npm install ${packageName}@latest --save`);
    if (setupCommand) {
      console.log('  或重新执行一键安装：');
      console.log(`    ${setupCommand}`);
    }
    console.log('');
    process.exit(0);
  }

  if (versionState > 0) {
    console.log('\n✓ 当前本地版本高于 npm latest，可能是本地预发布或内部测试包。');
    console.log('  如果你不是在调试 TFDS 包，请确认安装来源是否符合预期。\n');
    process.exit(0);
  }

  console.log('\n✓ 当前已是 npm latest，可以继续使用 TFDS 生成页面。\n');
}

function formatDateToMinute(value) {
  if (!value) return '未知';
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return '未知';
  const parts = new Intl.DateTimeFormat('zh-CN', {
    timeZone: 'Asia/Shanghai',
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    hour12: false,
  }).formatToParts(date);
  const byType = Object.fromEntries(parts.map((part) => [part.type, part.value]));
  return `${byType.year}-${byType.month}-${byType.day} ${byType.hour}:${byType.minute}`;
}

function parseVersion(version) {
  return String(version || '')
    .trim()
    .replace(/^v/i, '')
    .split('-')[0]
    .split('.')
    .map((part) => Number.parseInt(part, 10) || 0);
}

function compareVersions(a, b) {
  const av = parseVersion(a);
  const bv = parseVersion(b);
  const len = Math.max(av.length, bv.length, 3);
  for (let i = 0; i < len; i += 1) {
    const left = av[i] || 0;
    const right = bv[i] || 0;
    if (left > right) return 1;
    if (left < right) return -1;
  }
  return 0;
}
