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

export const TFDS_LOCK_REL_PATH = '.tfds/lock.json';
export const TFDS_LOCK_SCHEMA_VERSION = 1;

/**
 * @param {string} projectRoot
 */
export function readTfdsLock(projectRoot) {
  const lockPath = path.join(projectRoot, TFDS_LOCK_REL_PATH);
  if (!fs.existsSync(lockPath)) return null;
  try {
    return JSON.parse(fs.readFileSync(lockPath, 'utf8'));
  } catch {
    return null;
  }
}

/**
 * @param {object} options
 * @param {string} options.projectRoot
 * @param {string} options.packageName
 * @param {string} options.skillName
 * @param {string} options.version
 */
export function writeTfdsLockEntry({ projectRoot, packageName, skillName, version }) {
  const lockPath = path.join(projectRoot, TFDS_LOCK_REL_PATH);
  /** @type {{ schemaVersion: number, updatedAt: string, packages: Record<string, unknown> }} */
  let lock = {
    schemaVersion: TFDS_LOCK_SCHEMA_VERSION,
    updatedAt: new Date().toISOString(),
    packages: {},
  };

  const existing = readTfdsLock(projectRoot);
  if (existing?.packages && typeof existing.packages === 'object') {
    lock.packages = { ...existing.packages };
  }

  const now = new Date().toISOString();
  lock.updatedAt = now;
  lock.packages[packageName] = {
    version,
    skillName,
    skillSyncedAt: now,
    skillSyncedVersion: version,
    ideSkillDirs: [
      `.cursor/skills/${skillName}`,
      `.claude/skills/${skillName}`,
      `.codex/skills/${skillName}`,
      `.agents/skills/${skillName}`,
      `.trae-cn/skills/${skillName}`,
    ],
  };

  fs.mkdirSync(path.dirname(lockPath), { recursive: true });
  fs.writeFileSync(lockPath, `${JSON.stringify(lock, null, 2)}\n`, 'utf8');
  return lockPath;
}

/**
 * @param {object} options
 * @param {string} options.projectRoot
 * @param {string} options.packageName
 * @param {string} options.localVersion
 * @param {string} options.skillName
 */
export function getSkillSyncStatus({ projectRoot, packageName, localVersion, skillName }) {
  const lockEntry = readTfdsLock(projectRoot)?.packages?.[packageName];
  const cursorSkillPath = path.join(projectRoot, '.cursor', 'skills', skillName, 'SKILL.md');
  const skillDirExists = fs.existsSync(cursorSkillPath);

  const syncedVersion = lockEntry?.skillSyncedVersion || null;
  const inSyncWithNpm =
    syncedVersion != null && compareLooseVersion(syncedVersion, localVersion) === 0 && skillDirExists;

  return {
    skillName,
    skillDirExists,
    lockSyncedVersion: syncedVersion,
    npmVersion: localVersion,
    inSync: inSyncWithNpm,
    staleReason: !skillDirExists
      ? 'IDE Skill 目录缺失，请重新 npm i 触发 postinstall'
      : syncedVersion == null
        ? '尚未写入 .tfds/lock.json，请重新 npm i'
        : compareLooseVersion(syncedVersion, localVersion) !== 0
          ? `Skill 快照版本 ${syncedVersion} 落后于 node_modules ${localVersion}`
          : null,
  };
}

function compareLooseVersion(a, b) {
  const pa = String(a || '')
    .replace(/^v/i, '')
    .split('-')[0];
  const pb = String(b || '')
    .replace(/^v/i, '')
    .split('-')[0];
  if (pa === pb) return 0;
  return pa < pb ? -1 : 1;
}
