const fs = require('fs');
const path = require('path');

const projectRoot = path.resolve(__dirname, '..');
const webDir = path.join(projectRoot, 'web');
const versionsPath = path.join(webDir, 'asset-versions.json');
const statePath = path.join(webDir, '.asset-version-state.json');

const usage = `
用法:
  node scripts/bump-web-asset-version.js --sync
  node scripts/bump-web-asset-version.js --auto
  node scripts/bump-web-asset-version.js --bump ai-assistant.js public-status.js
  node scripts/bump-web-asset-version.js --bump-all

说明:
  --sync      仅按 asset-versions.json 同步所有 HTML 中的 ?v= 引用
  --auto      自动检查受管静态资源是否发生变更；有变更则递增对应版本并同步 HTML
  --bump      仅递增指定静态资源版本号，并同步 HTML 引用
  --bump-all  递增 asset-versions.json 中所有资源版本号，并同步 HTML 引用
`;

const args = process.argv.slice(2);
const hasFlag = (flag) => args.includes(flag);

const localPathPattern = /^\/?[^?#]+\.(?:js|css)(?:\?[^"]*)?$/i;

const readJson = (filePath) => JSON.parse(fs.readFileSync(filePath, 'utf8'));
const writeJson = (filePath, value) => {
  fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
};
const readJsonIfExists = (filePath, fallback) => {
  if (!fs.existsSync(filePath)) return fallback;
  return readJson(filePath);
};

const collectHtmlFiles = (dir) => {
  const files = [];
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
    const fullPath = path.join(dir, entry.name);
    if (entry.isDirectory()) {
      files.push(...collectHtmlFiles(fullPath));
      continue;
    }
    if (entry.isFile() && entry.name.toLowerCase().endsWith('.html')) {
      files.push(fullPath);
    }
  }
  return files;
};

const normalizeAssetName = (value) => path.basename(String(value || '').trim());

const withVersion = (originalPath, version) => {
  const [pathname] = originalPath.split('?');
  return `${pathname}?v=${version}`;
};

const getManagedAssetStats = (versions) => {
  const stats = {};
  Object.keys(versions).forEach((assetName) => {
    const assetPath = path.join(webDir, assetName);
    if (!fs.existsSync(assetPath)) return;
    const fileStat = fs.statSync(assetPath);
    stats[assetName] = {
      size: fileStat.size,
      mtimeMs: fileStat.mtimeMs
    };
  });
  return stats;
};

const syncHtmlReferences = (versions) => {
  const htmlFiles = collectHtmlFiles(webDir);
  const refPattern = /((?:src|href)\s*=\s*")([^"]+\.(?:js|css)(?:\?[^"]*)?)(")/gi;
  let changedFiles = 0;

  htmlFiles.forEach((filePath) => {
    const source = fs.readFileSync(filePath, 'utf8');
    const updated = source.replace(refPattern, (match, prefix, assetPath, suffix) => {
      if (/^https?:\/\//i.test(assetPath) || !localPathPattern.test(assetPath)) return match;
      const assetName = normalizeAssetName(assetPath.split('?')[0]);
      const version = versions[assetName];
      if (!version) return match;
      return `${prefix}${withVersion(assetPath, version)}${suffix}`;
    });

    if (updated !== source) {
      fs.writeFileSync(filePath, updated, 'utf8');
      changedFiles += 1;
    }
  });

  return changedFiles;
};

const versions = readJson(versionsPath);

if (hasFlag('--help') || hasFlag('-h') || !args.length) {
  console.log(usage.trim());
  process.exit(0);
}

if (hasFlag('--bump-all')) {
  Object.keys(versions).forEach((key) => {
    versions[key] += 1;
  });
  writeJson(versionsPath, versions);
  const changed = syncHtmlReferences(versions);
  console.log(`已递增全部资源版本，共 ${Object.keys(versions).length} 项；同步 HTML ${changed} 个文件。`);
  process.exit(0);
}

if (hasFlag('--sync')) {
  const changed = syncHtmlReferences(versions);
  console.log(`已按 asset-versions.json 同步 HTML 引用，共更新 ${changed} 个文件。`);
  process.exit(0);
}

if (hasFlag('--auto')) {
  const previousState = readJsonIfExists(statePath, {});
  const currentState = getManagedAssetStats(versions);
  const changedAssets = Object.keys(currentState).filter((assetName) => {
    const prev = previousState[assetName];
    const curr = currentState[assetName];
    if (!prev) return true;
    return prev.size !== curr.size || prev.mtimeMs !== curr.mtimeMs;
  });

  if (!changedAssets.length) {
    const synced = syncHtmlReferences(versions);
    writeJson(statePath, currentState);
    console.log(`未发现静态资源变更；已校准 HTML 引用 ${synced} 个文件。`);
    process.exit(0);
  }

  changedAssets.forEach((assetName) => {
    versions[assetName] += 1;
  });
  writeJson(versionsPath, versions);
  writeJson(statePath, currentState);
  const synced = syncHtmlReferences(versions);
  console.log(`检测到资源变更: ${changedAssets.join(', ')}；已自动递增版本并同步 HTML ${synced} 个文件。`);
  process.exit(0);
}

const bumpIndex = args.indexOf('--bump');
if (bumpIndex !== -1) {
  const requested = args.slice(bumpIndex + 1).map(normalizeAssetName).filter(Boolean);
  if (!requested.length) {
    console.error('请在 --bump 后提供至少一个静态资源文件名，例如 ai-assistant.js');
    process.exit(1);
  }

  const unknown = requested.filter((name) => !(name in versions));
  if (unknown.length) {
    console.error(`以下资源尚未纳入版本管理: ${unknown.join(', ')}`);
    console.error('请先在 web/asset-versions.json 中补充后再执行。');
    process.exit(1);
  }

  requested.forEach((name) => {
    versions[name] += 1;
  });
  writeJson(versionsPath, versions);
  const changed = syncHtmlReferences(versions);
  console.log(`已递增资源版本: ${requested.join(', ')}；同步 HTML ${changed} 个文件。`);
  process.exit(0);
}

console.error('未识别的参数。');
console.error(usage.trim());
process.exit(1);
