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

const distDir = path.resolve('dist');
const manifestPath = path.join(distDir, 'manifest.webmanifest');
const indexPath = path.join(distDir, 'index.html');
const serviceWorkerPath = path.join(distDir, 'sw.js');

const errors = [];

function fail(message) {
  errors.push(message);
}

function readJson(filePath) {
  try {
    return JSON.parse(fs.readFileSync(filePath, 'utf8'));
  } catch (error) {
    fail(`无法读取或解析 ${path.relative(process.cwd(), filePath)}: ${error.message}`);
    return null;
  }
}

function fileExistsFromManifest(src) {
  const normalized = src.replace(/^\.?\//, '').split('?')[0];
  return fs.existsSync(path.join(distDir, normalized));
}

if (!fs.existsSync(distDir)) {
  fail('dist 目录不存在，请先运行构建。');
}

const manifest = fs.existsSync(manifestPath) ? readJson(manifestPath) : null;
if (!manifest) {
  fail('dist/manifest.webmanifest 不存在。');
} else {
  for (const field of ['id', 'name', 'short_name', 'description', 'start_url', 'scope', 'display', 'theme_color', 'background_color']) {
    if (!manifest[field]) {
      fail(`manifest 缺少 ${field}。`);
    }
  }

  if (!['standalone', 'fullscreen', 'minimal-ui'].includes(manifest.display)) {
    fail('manifest.display 应为 standalone、fullscreen 或 minimal-ui。');
  }

  const icons = Array.isArray(manifest.icons) ? manifest.icons : [];
  const has192 = icons.some((icon) => icon.sizes?.includes('192x192') && fileExistsFromManifest(icon.src));
  const has512 = icons.some((icon) => icon.sizes?.includes('512x512') && fileExistsFromManifest(icon.src));
  const hasMaskable = icons.some((icon) => icon.sizes?.includes('512x512') && icon.purpose?.includes('maskable') && fileExistsFromManifest(icon.src));

  if (!has192) fail('manifest 缺少可访问的 192x192 图标。');
  if (!has512) fail('manifest 缺少可访问的 512x512 图标。');
  if (!hasMaskable) fail('manifest 缺少可访问的 512x512 maskable 图标。');

  if (!Array.isArray(manifest.categories) || manifest.categories.length === 0) {
    fail('manifest 缺少 categories，Microsoft Store/PWABuilder 会降低质量评分。');
  }
}

if (!fs.existsSync(indexPath)) {
  fail('dist/index.html 不存在。');
} else {
  const html = fs.readFileSync(indexPath, 'utf8');
  if (!html.includes('rel="manifest"')) {
    fail('index.html 缺少 manifest 链接。');
  }
  if (!html.includes('apple-touch-icon')) {
    fail('index.html 缺少 apple-touch-icon。');
  }
  if (!html.includes('msapplication-TileImage')) {
    fail('index.html 缺少 Windows tile 图标声明。');
  }
}

if (!fs.existsSync(serviceWorkerPath)) {
  fail('dist/sw.js 不存在，PWA 离线能力未生成。');
} else {
  const sw = fs.readFileSync(serviceWorkerPath, 'utf8');
  if (!sw.includes('sw-cache-manager.js')) {
    fail('sw.js 未导入 sw-cache-manager.js。');
  }
  if (!sw.includes('index.html')) {
    fail('sw.js 未包含导航回退，离线打开应用可能失败。');
  }
}

if (!fs.existsSync(path.join(distDir, 'sw-cache-manager.js'))) {
  fail('dist/sw-cache-manager.js 不存在。');
}

if (errors.length > 0) {
  console.error('PWA 构建校验失败:');
  for (const error of errors) {
    console.error(`- ${error}`);
  }
  process.exit(1);
}

console.log('PWA 构建校验通过。');
