// 安装 @tfdesign/b-end 后自动执行四件事：
//
//  1. IDE Skill 自动写入（仅 opt-in 通道，不写 always-on）
//     → .cursor/skills/产品设计-体服平台B端-界面生成/    （Cursor      → /产品设计-体服平台B端-界面生成 唤起）
//     → .claude/skills/产品设计-体服平台B端-界面生成/    （Claude Code → /产品设计-体服平台B端-界面生成 唤起）
//     → .codex/skills/产品设计-体服平台B端-界面生成/     （Codex       → 项目内参考）
//     → ~/.codex/skills/产品设计-体服平台B端-界面生成/   （Codex       → 用户级 /产品设计-体服平台B端-界面生成 Skill，需新开/重启 Codex 会话）
//     → .agents/skills/产品设计-体服平台B端-界面生成/    （通用 agent 兜底，与 .codex 并存）
//     → .trae-cn/skills/产品设计-体服平台B端-界面生成/   （Trae CN     → Use Skill: 产品设计-体服平台B端-界面生成）
//     ⚠️ 不再自动写 .trae/rules/tfds.md：Trae rules 是 always-on 全局规则，
//        与 TFDS"显式调用才生效"原则冲突。
//     跳过：SKIP_TFDS_CURSOR_SKILL=1；目标已存在且完整时不覆盖，旧版/缺文件时自动同步
//
//  2. 入口 CSS 自动补丁（最关键步骤，消除手动操作）
//     在 @import "tailwindcss" 之后自动插入：
//       @import "@tfdesign/b-end/theme.css";
//       @source "./**/*.{js,jsx,ts,tsx}";
//       @source "<relPath>/node_modules/@tfdesign/b-end/**/*.{js,jsx}";
//     候选文件：src/index.css、src/main.css、src/styles.css、
//              src/global.css、app/globals.css、styles/globals.css、index.css
//     已有 theme.css import → 跳过；未找到 @import "tailwindcss" → 不改写，终端提示
//     跳过：SKIP_TFDS_CSS_PATCH=1
//
//  3. npm 最新版本检测（只读提醒，不阻断安装）
//     跳过：SKIP_TFDS_UPDATE_CHECK=1
//
//  4. 终端安装报告（已做了什么、还差什么、如何唤起规范）

import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { printInstallSuccessMessage } from './install-success-message.mjs';
import { isTfdsMonorepoRoot } from './is-tfds-monorepo-root.mjs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const pkgRoot = path.resolve(__dirname, '..');
const SKILL_PUBLIC_NAME = '产品设计-体服平台B端-界面生成';
const LEGACY_SKILL_NAMES = ['tfds', 'TFDS', '体服B端组件调用SKILL'];

const projectRoot = process.env.INIT_CWD || process.cwd();

// ─────────────────────────────────────────────────────────────────
// 前置检查：确认运行在正确的业务项目根（有自己的 package.json，且不是 tfds-b-end 自身）
// ─────────────────────────────────────────────────────────────────

function readJson(p) {
  try {
    return JSON.parse(fs.readFileSync(p, 'utf8'));
  } catch {
    return null;
  }
}

const projectPkg = readJson(path.join(projectRoot, 'package.json'));
const isSelfPkg = projectPkg?.name === '@tfdesign/b-end';
const hasNoPkg = !projectPkg;
const updateCheckScript = path.join(pkgRoot, 'scripts', 'check-tfds-update.mjs');

if (hasNoPkg || isSelfPkg) {
  console.log('\n╔══════════════════════════════════════════════════════╗');
  console.log('║   @tfdesign/b-end  ⚠ 安装位置需要调整         ║');
  console.log('╚══════════════════════════════════════════════════════╝\n');

  if (hasNoPkg) {
    console.log('  当前目录没有业务项目的 package.json。');
  } else {
    console.log('  当前目录是 tfds-b-end 包自身，不是业务项目根。');
  }
  console.log('  请在业务项目根目录使用 npm 官网一键安装向导，不要在本包目录内直接 npm install。\n');

  console.log('  ── 推荐：在目标文件夹（业务项目根或空文件夹）执行 ──\n');
  console.log('       npx -y -p @tfdesign/b-end@latest tfds-b-end-setup\n');
  console.log('  向导会自动判断：');
  console.log('    • 已有项目：复用现有 package.json / vite.config / 入口 CSS，缺什么补什么');
  console.log('    • 全新空文件夹：自动创建最小 Vite + React 项目，然后从 npm 安装 TFDS\n');
  console.log('  若安装向导不在目标项目根，请显式指定：');
  console.log('       npx -y -p @tfdesign/b-end@latest tfds-b-end-setup -- --target "/绝对路径/.../业务项目根"\n');
  console.log('  详见：README.md → "全新项目？从这里开始"\n');
  process.exit(0);
}

// ─────────────────────────────────────────────────────────────────
// Step 1: Cursor / Agents Skill 复制
// ─────────────────────────────────────────────────────────────────

const skillSrcCandidates = [
  path.join(pkgRoot, 'skills', SKILL_PUBLIC_NAME),
  path.join(pkgRoot, 'skills', 'tfds'),
  path.join(pkgRoot, 'skills', 'TFDS'),
];
const skillSrc = skillSrcCandidates.find((dir) => fs.existsSync(dir)) ?? null;

const REQUIRED_TFDS_SKILL_FILES = [
  'SKILL.md',
  'DESIGN_PRINCIPLES.md',
  'PAGE_ARCHETYPES.md',
  'archetypes.json',
  'custom-blocks.json',
  'components.summary.json',
  'components.index.json',
  'LAYOUT_RULES.md',
  'GLOBAL_DESIGN_RULES.md',
  'CHECKLIST.md',
  'COMMON_FAILURES.md',
];

function readText(p) {
  try {
    return fs.readFileSync(p, 'utf8');
  } catch {
    return '';
  }
}

function runUpdateCheck() {
  if (process.env.SKIP_TFDS_UPDATE_CHECK === '1') {
    done.push('版本更新检测已跳过（SKIP_TFDS_UPDATE_CHECK=1）');
    return;
  }

  if (!fs.existsSync(updateCheckScript)) {
    todo.push('未找到版本更新检测脚本，已跳过 npm latest 检查。');
    return;
  }

  const result = spawnSync(process.execPath, [updateCheckScript], {
    cwd: projectRoot,
    stdio: 'inherit',
    env: process.env,
  });

  if (result.error) {
    todo.push(`版本更新检测未完成：${result.error.message}`);
    return;
  }

  if (result.status && result.status !== 0) {
    todo.push('版本更新检测脚本返回异常，但不影响本次安装。可稍后手动执行：node node_modules/@tfdesign/b-end/scripts/check-tfds-update.mjs');
  }
}

function hasSourceSkillDiff(dest) {
  return REQUIRED_TFDS_SKILL_FILES.some((file) => {
    const sourceFile = path.join(skillSrc, file);
    const destFile = path.join(dest, file);
    return readText(sourceFile) !== readText(destFile);
  });
}

function needsSkillRefresh(dest) {
  const missingRequiredFile = REQUIRED_TFDS_SKILL_FILES.some((file) => !fs.existsSync(path.join(dest, file)));
  if (missingRequiredFile) return true;

  return hasSourceSkillDiff(dest);
}

function copySkillDir(dest) {
  fs.mkdirSync(dest, { recursive: true });
  fs.cpSync(skillSrc, dest, { recursive: true, force: true });
}

/** @type {string[]} postinstall 步骤摘要，最后汇总打印 */
const done = [];
/** @type {string[]} 需用户手动处理的提示 */
const todo = [];

// ⚠️ SKILL_DIR_TARGETS 必须在 installSkillDir() 定义与调用之前声明，避免 const TDZ 错误
const SKILL_DIR_TARGETS = {
  cursor: { base: path.join(projectRoot, '.cursor', 'skills'), label: `Cursor      Skill → .cursor/skills/${SKILL_PUBLIC_NAME}/  （唤起：/${SKILL_PUBLIC_NAME}）` },
  claude: { base: path.join(projectRoot, '.claude', 'skills'), label: `Claude Code Skill → .claude/skills/${SKILL_PUBLIC_NAME}/  （唤起：/${SKILL_PUBLIC_NAME}）` },
  codex:  { base: path.join(projectRoot, '.codex',  'skills'), label: `Codex       参考文件 → .codex/skills/${SKILL_PUBLIC_NAME}/   （若 /${SKILL_PUBLIC_NAME} 不出现，请用下方手动提示词）` },
  agents: { base: path.join(projectRoot, '.agents', 'skills'), label: `Agents      Skill → .agents/skills/${SKILL_PUBLIC_NAME}/  （通用 agent 兜底）` },
  traeCn: { base: path.join(projectRoot, '.trae-cn', 'skills'), label: `Trae CN     Skill → .trae-cn/skills/${SKILL_PUBLIC_NAME}/  （Use Skill: ${SKILL_PUBLIC_NAME}）` },
};

function removeLegacySkillDirs(base) {
  for (const name of LEGACY_SKILL_NAMES) {
    const legacy = path.join(base, name);
    if (legacy === path.join(base, SKILL_PUBLIC_NAME) || !fs.existsSync(legacy)) continue;
    try {
      fs.rmSync(legacy, { recursive: true, force: true });
      done.push(`旧 Skill 目录已清理：${path.relative(projectRoot, legacy)}`);
    } catch (e) {
      todo.push(`旧 Skill 目录清理失败：${path.relative(projectRoot, legacy)}（${e?.message || e}）`);
    }
  }
}

/**
 * 复制整个 skill 目录到指定 IDE 的 skills 路径。
 * @param {'cursor'|'claude'|'codex'|'agents'|'traeCn'} which
 */
function installSkillDir(which) {
  const target = SKILL_DIR_TARGETS[which];
  const dest = path.join(target.base, SKILL_PUBLIC_NAME);
  removeLegacySkillDirs(target.base);

  if (fs.existsSync(dest)) {
    if (needsSkillRefresh(dest)) {
      try {
        copySkillDir(dest);
        done.push(`Skill 已存在且已同步新版（${which}）：${path.relative(projectRoot, dest)}`);
      } catch (e) {
        todo.push(`Skill 同步失败（${which}）：${e?.message || e}。请删除 ${path.relative(projectRoot, dest)} 后重新执行 npm i。`);
      }
    } else {
      done.push(`Skill 已存在且完整，跳过（${which}）：${path.relative(projectRoot, dest)}`);
    }
    return;
  }

  try {
    copySkillDir(dest);
    done.push(target.label);
  } catch (e) {
    todo.push(`Skill 复制失败（${which}）：${e?.message || e}`);
  }
}

function resolveCodexHome() {
  if (process.env.CODEX_HOME) return path.resolve(process.env.CODEX_HOME);
  const home = os.homedir();
  return home ? path.join(home, '.codex') : null;
}

function installCodexUserSkill() {
  const codexHome = resolveCodexHome();
  if (!codexHome) {
    todo.push('Codex 用户级 Skill 未写入：无法解析 home 目录。');
    return;
  }

  const dest = path.join(codexHome, 'skills', SKILL_PUBLIC_NAME);
  removeLegacySkillDirs(path.join(codexHome, 'skills'));
  if (fs.existsSync(dest)) {
    if (needsSkillRefresh(dest)) {
      try {
        copySkillDir(dest);
        done.push(`Codex 用户级 Skill 已存在且已同步新版：${dest}`);
      } catch (e) {
        todo.push(`Codex 用户级 Skill 同步失败：${e?.message || e}。请删除 ${dest} 后重新执行 npm i。`);
      }
    } else {
      done.push(`Codex 用户级 Skill 已存在且完整，跳过：${dest}`);
    }
    return;
  }

  try {
    copySkillDir(dest);
    done.push(`Codex 用户级 Skill → ${dest}  （新开/重启 Codex 后 /${SKILL_PUBLIC_NAME}）`);
  } catch (e) {
    todo.push(`Codex 用户级 Skill 写入失败：${e?.message || e}。可手动复制 node_modules/@tfdesign/b-end/skills/${SKILL_PUBLIC_NAME}（或旧版 skills/tfds）到 ${dest}`);
  }
}

if (process.env.SKIP_TFDS_CURSOR_SKILL === '1') {
  done.push('Skill 复制已跳过（SKIP_TFDS_CURSOR_SKILL=1）');
} else if (isTfdsMonorepoRoot(projectRoot)) {
  done.push('TFDS 主仓：不在仓库内复制 IDE Skill（请使用 packages/tfds-b-end/skills/…）');
} else if (!skillSrc) {
  todo.push(`包内未找到 skills/${SKILL_PUBLIC_NAME}（或旧版 skills/tfds）目录，Skill 未复制（可能是 files 裁剪的极简包）`);
} else {
  installSkillDir('cursor');   // Cursor      → .cursor/skills/产品设计-体服平台B端-界面生成/
  installSkillDir('claude');   // Claude Code → .claude/skills/产品设计-体服平台B端-界面生成/
  installSkillDir('codex');    // Codex       → .codex/skills/产品设计-体服平台B端-界面生成/
  installSkillDir('agents');   // 通用兜底     → .agents/skills/产品设计-体服平台B端-界面生成/
  installSkillDir('traeCn');   // Trae CN     → .trae-cn/skills/产品设计-体服平台B端-界面生成/
  if (process.env.SKIP_TFDS_CODEX_GLOBAL === '1') {
    done.push('Codex 用户级 Skill 复制已跳过（SKIP_TFDS_CODEX_GLOBAL=1）');
  } else {
    installCodexUserSkill();
  }
  // Trae：只写 opt-in Skill 目录，故意不自动写 .trae/rules/（避免 always-on 污染所有对话）
}

// ─────────────────────────────────────────────────────────────────
// Step 2: 入口 CSS 自动补丁
// ─────────────────────────────────────────────────────────────────

if (process.env.SKIP_TFDS_CSS_PATCH === '1') {
  todo.push(
    'CSS 补丁已跳过（SKIP_TFDS_CSS_PATCH=1），请手动在入口 CSS 添加 theme.css import 与 @source 扫描',
  );
} else {
  patchEntryCss();
}

function candidateCssFiles() {
  const rels = [
    'src/index.css',
    'src/main.css',
    'src/styles.css',
    'src/global.css',
    'app/globals.css',
    'styles/globals.css',
    'index.css',
  ];
  return rels.map((r) => path.join(projectRoot, r)).filter((p) => fs.existsSync(p));
}

function patchEntryCss() {
  const cssFiles = candidateCssFiles();

  if (cssFiles.length === 0) {
    todo.push(
      '未在常见路径找到入口 CSS，请手动在入口 CSS 添加（src/index.css 为例）：\n' +
        '      @import "tailwindcss";\n' +
        '      @import "@tfdesign/b-end/theme.css";\n' +
        '      @source "./**/*.{js,jsx,ts,tsx}";\n' +
        '      @source "../node_modules/@tfdesign/b-end/**/*.{js,jsx}";',
    );
    return;
  }

  for (const cssPath of cssFiles) {
    let content;
    try {
      content = fs.readFileSync(cssPath, 'utf8');
    } catch {
      continue;
    }

    const rel = path.relative(projectRoot, cssPath);

    // 已有 theme.css → 无需操作
    if (/@tfdesign\/b-end\/theme\.css/.test(content)) {
      done.push(`CSS 已配置，无需更改：${rel}`);
      return;
    }

    // 没有 @import "tailwindcss" → 不改写，提示手动
    if (!/@import\s+["']tailwindcss["']/.test(content)) {
      continue; // 尝试下一个候选
    }

    // 计算 CSS 文件到 node_modules 的相对路径
    const cssDir = path.dirname(cssPath);
    const nmRel = path.relative(cssDir, path.join(projectRoot, 'node_modules')).replace(/\\/g, '/') || '.';

    const hasSource = /@source[^;]*@tfdesign\/b-end/i.test(content);

    // 在 @import "tailwindcss"; 行后插入
    const insertion =
      `\n@import "@tfdesign/b-end/theme.css";` +
      (hasSource ? '' : `\n@source "./**/*.{js,jsx,ts,tsx}";\n@source "${nmRel}/@tfdesign/b-end/**/*.{js,jsx}";`);

    const patched = content.replace(
      /(@import\s+["']tailwindcss["'];[^\n]*)/,
      `$1${insertion}`,
    );

    try {
      fs.writeFileSync(cssPath, patched, 'utf8');
      done.push(`CSS 已自动配置：${rel}`);
      done.push(`  + @import "@tfdesign/b-end/theme.css"`);
      if (!hasSource) {
        done.push(`  + @source "./**/*.{js,jsx,ts,tsx}"`);
        done.push(`  + @source "${nmRel}/@tfdesign/b-end/**/*.{js,jsx}"`);
      }
    } catch (e) {
      todo.push(
        `CSS 自动补丁写入失败（${rel}）：${e?.message}，请手动在 @import "tailwindcss" 后追加：\n` +
          `      @import "@tfdesign/b-end/theme.css";\n` +
          `      @source "${nmRel}/@tfdesign/b-end/**/*.{js,jsx}";`,
      );
    }
    return; // 只补丁第一个匹配的 CSS 文件
  }

  // 所有候选 CSS 都没有 @import "tailwindcss"
  const firstCss = path.relative(projectRoot, cssFiles[0]);
  todo.push(
    `在 ${firstCss} 中未找到 @import "tailwindcss"，CSS 未自动修改。\n` +
      '      请在入口 CSS 的 @import "tailwindcss" 之后手动追加：\n' +
      '      @import "@tfdesign/b-end/theme.css";\n' +
      '      @source "../node_modules/@tfdesign/b-end/**/*.{js,jsx}";',
  );
}

// ─────────────────────────────────────────────────────────────────
// Step 3: 版本更新检测（只读，不阻断安装）
// ─────────────────────────────────────────────────────────────────

runUpdateCheck();

// ─────────────────────────────────────────────────────────────────
// Step 4: 终端安装报告
// ─────────────────────────────────────────────────────────────────

console.log('\n╔══════════════════════════════════════════════════════╗');
console.log('║      @tfdesign/b-end  安装完成                ║');
console.log('╚══════════════════════════════════════════════════════╝\n');

if (done.length) {
  console.log('✓ 已完成：');
  done.forEach((l) => console.log(`  ${l}`));
}

if (todo.length) {
  console.log('\n⚠ 还需手动处理：');
  todo.forEach((l) => console.log(`  ! ${l}`));
}

printInstallSuccessMessage({ projectRoot, pkgRoot });
console.log(
  '  跳过 CSS 补丁：SKIP_TFDS_CSS_PATCH=1 npm i   |   跳过 Skill：SKIP_TFDS_CURSOR_SKILL=1 npm i   |   跳过版本检测：SKIP_TFDS_UPDATE_CHECK=1 npm i',
);
console.log('');

process.exit(0);
