/**
 * API出勤记录与本地课评交叉核对脚本
 * 严格遵循《课评写入和查找规则V1.0》的两级查找逻辑
 *
 * 用法: node check-api-vs-local.js <开始日期> <结束日期>
 * 示例: node check-api-vs-local.js 2026-05-15 2026-05-17
 */

const axios = require('axios');
const fs = require('fs');
const path = require('path');
require('dotenv').config({ path: path.join(__dirname, '..', '.env') });

const API_BASE_URL = process.env.API_BASE_URL;
const AUTHORIZATION = process.env.AUTHORIZATION;
const MEMORY_DIR = path.join(__dirname, '..', '.claude', 'memory', 'class');

// ============ 课程编号别名映射 ============

// API课程编号 → 本地目录名可能的大小写变体
const DIR_CODE_ALIASES = {
  'KITTEN04': ['Kitten04', 'KITTEN04', 'kitten04'],
  'KITTEN': ['Kitten', 'KITTEN', 'kitten'],
  'AICODE03': ['AICODE03'],
  'AICODE01': ['AICODE01'],
  'CSP03': ['CSP03'],
  'CSP05': ['CSP05'],
};

// API课程编号 → 文件名中可能的别名
const FILE_CODE_ALIASES = {
  'KITTEN04': ['KITTEN04', 'Kitten04', 'kitten04', 'K4', 'k4'],
  'KITTEN': ['KITTEN', 'Kitten', 'kitten', 'K4', 'k4'],
  'AICODE03': ['AICODE03'],
  'AICODE01': ['AICODE01'],
  'CSP03': ['CSP03'],
  'CSP05': ['CSP05'],
};

// 非常规班目录关键词
const IRREGULAR_KEYWORDS = ['集训', '体验', '临时', '测试'];

// ============ 辅助函数 ============

function extractCourseCode(className) {
  const match = className.match(/^([A-Z]+\d+)/);
  return match ? match[1] : className;
}

function getWeekday(dateStr) {
  const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
  const d = new Date(dateStr + 'T00:00:00');
  return weekdays[d.getDay()];
}

function extractTimeCode(timePeriod) {
  if (!timePeriod) return '';
  const match = timePeriod.match(/(\d{2}):(\d{2})/);
  return match ? match[1] + match[2] : '';
}

function getFileAliases(courseCode) {
  return FILE_CODE_ALIASES[courseCode] || [courseCode];
}

function getDirAliases(courseCode) {
  return DIR_CODE_ALIASES[courseCode] || [courseCode];
}

// 列出所有本地班级目录
function listAllClassDirs() {
  if (!fs.existsSync(MEMORY_DIR)) return [];
  return fs.readdirSync(MEMORY_DIR, { withFileTypes: true })
    .filter(d => d.isDirectory())
    .map(d => d.name);
}

// 判断是否非常规班目录
function isIrregularDir(dirName) {
  return IRREGULAR_KEYWORDS.some(k => dirName.includes(k));
}

// ============ 两级查找逻辑 ============

/**
 * 第1级：精确匹配（课程编号 + 老师 + 星期 + 时间）
 */
function findLevel1Dir(courseCode, weekday, timeCode) {
  const dirs = listAllClassDirs();
  const aliases = getDirAliases(courseCode);

  for (const code of aliases) {
    const pattern = new RegExp(`${code}.*橙子.*${weekday}.*${timeCode}`, 'i');
    const match = dirs.find(d => pattern.test(d));
    if (match) return match;
  }

  // 模糊回退
  for (const code of aliases) {
    const match = dirs.find(d =>
      d.toLowerCase().includes(code.toLowerCase()) &&
      d.includes(weekday) &&
      (timeCode === '' || d.includes(timeCode))
    );
    if (match) return match;
  }

  return null;
}

/**
 * 第2级：放宽时间（课程编号 + 老师），排除非常规班和第1级已匹配的目录
 */
function findLevel2Dirs(courseCode, excludeDir) {
  const dirs = listAllClassDirs();
  const aliases = getDirAliases(courseCode);

  return dirs.filter(dir => {
    if (dir === excludeDir) return false;
    if (isIrregularDir(dir)) return false;
    if (!dir.includes('橙子')) return false;
    return aliases.some(code => dir.toLowerCase().includes(code.toLowerCase()));
  });
}

/**
 * 在指定目录下检查学生课评文件
 * 返回: { hasFeedback, files, fileTypes, note }
 */
function checkStudentFeedback(baseDir, studentName, dateNum, aliases) {
  const feedbackDir = path.join(baseDir, studentName, 'feedback');
  if (!fs.existsSync(feedbackDir)) {
    return { hasFeedback: false, files: [], fileTypes: [], note: '无feedback目录' };
  }

  const files = fs.readdirSync(feedbackDir)
    .filter(f => f.endsWith('.md'))
    .filter(f => {
      const dateMatch = f.startsWith(dateNum);
      const codeMatch = aliases.some(a => f.includes(a));
      return dateMatch && codeMatch;
    });

  const fileTypes = files.map(f => {
    if (f.includes('(请假)')) return '请假';
    if (f.includes('(补课')) return '补课';
    if (f.includes('(未到')) return '未到';
    return '正常课评';
  });

  return {
    hasFeedback: files.length > 0,
    files,
    fileTypes,
    note: files.length > 0 ? fileTypes.join(', ') : '无匹配文件'
  };
}

/**
 * 检查学生目录是否存在（用于判断是"新增"还是"有目录但无文件"）
 */
function hasStudentDir(baseDir, studentName) {
  return fs.existsSync(path.join(baseDir, studentName));
}

// ============ API查询 ============

async function queryDailySchedule(date) {
  try {
    const response = await axios.get(`${API_BASE_URL}/reports/teaching-schedule`, {
      headers: { 'Authorization': AUTHORIZATION },
      params: {
        teacher_name: '橙子（程城）',
        teaching_date: date
      },
      timeout: 15000
    });

    if (response.data.code === 0 && response.data.data.items.length > 0) {
      return response.data.data.items;
    }
    return [];
  } catch (error) {
    console.error(`查询 ${date} 失败:`, error.response?.data?.message || error.message);
    return [];
  }
}

// ============ 主函数 ============

async function main() {
  const args = process.argv.slice(2);
  if (args.length < 2) {
    console.log('用法: node check-api-vs-local.js <开始日期> <结束日期>');
    console.log('示例: node check-api-vs-local.js 2026-05-15 2026-05-17');
    process.exit(1);
  }

  const beginDate = args[0];
  const endDate = args[1];

  console.log('========================================');
  console.log('  API出勤记录 vs 本地课评 交叉核对');
  console.log(`  日期范围: ${beginDate} 至 ${endDate}`);
  console.log('  查找规则: V1.0 两级查找（精确 → 放宽时间）');
  console.log('========================================\n');

  // 生成日期列表（本地时区）
  const dates = [];
  let curr = new Date(beginDate + 'T00:00:00');
  const end = new Date(endDate + 'T00:00:00');
  while (curr <= end) {
    const y = curr.getFullYear();
    const m = String(curr.getMonth() + 1).padStart(2, '0');
    const d = String(curr.getDate()).padStart(2, '0');
    dates.push(`${y}-${m}-${d}`);
    curr.setDate(curr.getDate() + 1);
  }

  const allResults = [];

  for (const date of dates) {
    console.log(`\n[${date} ${getWeekday(date)}]`);
    const courses = await queryDailySchedule(date);

    if (courses.length === 0) {
      console.log('  无课程安排');
      continue;
    }

    for (const course of courses) {
      const courseCode = extractCourseCode(course.class_name);
      const weekday = getWeekday(date);
      const timeCode = extractTimeCode(course.teaching_time_period);
      const dateNum = date.replace(/-/g, '');
      const fileAliases = getFileAliases(courseCode);

      console.log(`\n  课程: ${course.class_name}`);
      console.log(`  时间: ${course.teaching_time_period}`);
      console.log(`  API应到: ${course.student_count}人 (${course.student_names?.join(', ') || '无名单'})`);

      // ====== 两级查找：确定搜索目录范围 ======
      const level1Dir = findLevel1Dir(courseCode, weekday, timeCode);
      const level2Dirs = findLevel2Dirs(courseCode, level1Dir);

      const searchDirs = [];
      if (level1Dir) searchDirs.push({ dir: level1Dir, level: 1 });
      for (const d of level2Dirs) searchDirs.push({ dir: d, level: 2 });

      if (searchDirs.length === 0) {
        console.log(`  本地目录: ❌ 未找到任何匹配目录 (第1/2级均失败)`);
        allResults.push({
          date, courseCode, time: course.teaching_time_period,
          className: course.class_name, level1Dir: null, level2Dirs: [], searchDirs: [],
          apiStudents: course.student_names || [], apiCount: course.student_count,
          studentResults: [], feedbackCount: 0, issues: ['本地无匹配班级目录']
        });
        continue;
      }

      console.log(`  第1级目录: ${level1Dir || '无'}`);
      if (level2Dirs.length > 0) console.log(`  第2级目录: ${level2Dirs.join(', ')}`);

      // ====== 以学生为中心查找课评 ======
      const apiNames = (course.student_names || []).map(n => n.replace(/\(.*?\)/g, '').trim());
      const studentResults = [];

      for (const apiName of apiNames) {
        let found = false;
        let foundAt = null;

        for (const { dir, level } of searchDirs) {
          // 1a/2a: 主目录 S/feedback/
          const mainResult = checkStudentFeedback(
            path.join(MEMORY_DIR, dir), apiName, dateNum, fileAliases
          );
          if (mainResult.hasFeedback) {
            found = true;
            foundAt = { dir, level, type: '主目录', ...mainResult };
            break;
          }

          // 1b/2b: 补课目录 补课/S/feedback/
          const makeupResult = checkStudentFeedback(
            path.join(MEMORY_DIR, dir, '补课'), apiName, dateNum, fileAliases
          );
          if (makeupResult.hasFeedback) {
            found = true;
            foundAt = { dir, level, type: '补课目录', ...makeupResult };
            break;
          }
        }

        studentResults.push({ name: apiName, found, foundAt });
      }

      // ====== 比对：收集问题 ======
      const issues = [];
      const foundStudents = studentResults.filter(s => s.found);
      const missingStudents = studentResults.filter(s => !s.found);
      const foundInLevel2 = foundStudents.filter(s => s.foundAt.level === 2);

      // 1. 未找到课评的学生
      for (const s of missingStudents) {
        // 检查在哪些目录中有学生目录（但无课评文件）
        const dirsWithStudent = searchDirs.filter(({ dir }) =>
          hasStudentDir(path.join(MEMORY_DIR, dir), s.name)
        );

        if (dirsWithStudent.length > 0) {
          const dirNames = dirsWithStudent.map(d => d.dir).join(', ');
          issues.push(`${s.name}: 有学生目录但无课评文件 (在: ${dirNames})`);
        } else {
          issues.push(`${s.name}: 本地无学生目录(可能新增/转班)`);
        }
      }

      // 2. 在第2级目录中找到的学生（提示，非错误）
      for (const s of foundInLevel2) {
        issues.push(`${s.name}: 课评在「${s.foundAt.dir}」找到(${s.foundAt.type})，建议确认是否为补课/调时间`);
      }

      // 3. 检查课评文件日期（对已找到的学生）
      for (const s of foundStudents) {
        for (const f of s.foundAt.files) {
          const fileDate = f.substring(0, 8);
          if (fileDate !== dateNum) {
            issues.push(`${s.name}: 文件日期不匹配 ${f} (文件${fileDate} vs API${dateNum})`);
          }
        }
      }

      // 4. 检查课程编号（对已找到的学生）
      for (const s of foundStudents) {
        for (const f of s.foundAt.files) {
          const codeMatch = fileAliases.some(a => f.includes(a));
          if (!codeMatch) {
            issues.push(`${s.name}: 课程编号不匹配 ${f} (期望含${courseCode}或其别名)`);
          }
        }
      }

      // ====== 输出结果 ======
      const feedbackCount = foundStudents.length;
      if (issues.length === 0) {
        console.log(`  ✅ 核对通过 (${feedbackCount}/${apiNames.length}人有课评)`);
      } else {
        const realIssues = issues.filter(i => !i.includes('建议确认')); // 第2级找到是提示不是错误
        const hints = issues.filter(i => i.includes('建议确认'));
        if (realIssues.length > 0) {
          console.log(`  ⚠️ 发现 ${realIssues.length} 个问题:`);
          realIssues.forEach(issue => console.log(`    - ${issue}`));
        }
        if (hints.length > 0) {
          console.log(`  💡 ${hints.length} 个提示:`);
          hints.forEach(h => console.log(`    - ${h}`));
        }
      }

      allResults.push({
        date, courseCode, time: course.teaching_time_period,
        className: course.class_name,
        level1Dir, level2Dirs, searchDirs,
        apiStudents: course.student_names || [], apiCount: course.student_count,
        studentResults, feedbackCount,
        issues
      });
    }
  }

  // ============ 汇总报告 ============
  console.log('\n\n========================================');
  console.log('  核对汇总报告');
  console.log('========================================');

  const totalCourses = allResults.length;
  const okCourses = allResults.filter(r =>
    r.issues.filter(i => !i.includes('建议确认')).length === 0
  ).length;
  const issueCourses = allResults.filter(r =>
    r.issues.filter(i => !i.includes('建议确认')).length > 0
  );
  const missingDirCourses = allResults.filter(r => r.searchDirs && r.searchDirs.length === 0);
  const level2Hints = allResults.filter(r =>
    r.issues.some(i => i.includes('建议确认'))
  ).length;

  console.log(`\n总课程数: ${totalCourses}`);
  console.log(`核对通过: ${okCourses}`);
  console.log(`存在问题: ${issueCourses.length}`);
  console.log(`无本地目录: ${missingDirCourses.length}`);
  console.log(`有第2级提示: ${level2Hints}`);

  if (issueCourses.length > 0) {
    console.log('\n--- 问题详情 ---');
    issueCourses.forEach(r => {
      const realIssues = r.issues.filter(i => !i.includes('建议确认'));
      console.log(`\n[${r.date} ${r.time}] ${r.className}`);
      console.log(`  第1级: ${r.level1Dir || '无'}, 第2级: ${r.level2Dirs.join(', ') || '无'}`);
      realIssues.forEach(issue => console.log(`  ⚠️ ${issue}`));
    });
  }

  // ============ 保存报告 ============
  const reportPath = path.join(__dirname, '..', 'output', `api核对报告_${beginDate}_${endDate}.md`);
  const reportDir = path.dirname(reportPath);
  if (!fs.existsSync(reportDir)) fs.mkdirSync(reportDir, { recursive: true });

  let md = `# API出勤记录 vs 本地课评核对报告\n\n`;
  md += `- **日期范围**: ${beginDate} 至 ${endDate}\n`;
  md += `- **核对时间**: ${new Date().toLocaleString()}\n`;
  md += `- **老师**: 橙子（程城）\n`;
  md += `- **查找规则**: V1.0 两级查找（精确→放宽时间）\n\n`;

  md += `## 汇总\n\n`;
  md += `- 总课程数: ${totalCourses}\n`;
  md += `- 核对通过: ${okCourses}\n`;
  md += `- 存在问题: ${issueCourses.length}\n`;
  md += `- 无本地目录: ${missingDirCourses.length}\n`;
  md += `- 有第2级查找提示: ${level2Hints}\n\n`;

  md += `## 详细核对结果\n\n`;
  md += `| 日期 | 时间 | 课程 | 第1级目录 | 第2级目录 | API人数 | 找到课评 | 状态 |\n`;
  md += `|------|------|------|-----------|-----------|---------|----------|------|\n`;

  for (const r of allResults) {
    const hasRealIssues = r.issues.filter(i => !i.includes('建议确认')).length > 0;
    const hasHints = r.issues.some(i => i.includes('建议确认'));
    let status = '✅';
    if (r.searchDirs.length === 0) status = '❌';
    else if (hasRealIssues) status = '⚠️';
    else if (hasHints) status = '💡';

    md += `| ${r.date} | ${r.time} | ${r.className} | ${r.level1Dir || '-'} | ${r.level2Dirs.join(', ') || '-'} | ${r.apiCount} | ${r.feedbackCount || 0} | ${status} |\n`;
  }

  if (issueCourses.length > 0) {
    md += `\n## 问题详情\n\n`;
    for (const r of issueCourses) {
      const realIssues = r.issues.filter(i => !i.includes('建议确认'));
      if (realIssues.length === 0) continue;

      md += `### ${r.date} ${r.time} - ${r.className}\n\n`;
      md += `- 第1级目录: ${r.level1Dir || '无'}\n`;
      md += `- 第2级目录: ${r.level2Dirs.join(', ') || '无'}\n`;
      md += `- API学生: ${r.apiStudents.join(', ')}\n\n`;

      const foundList = r.studentResults.filter(s => s.found).map(s => {
        const loc = s.foundAt.level === 1 ? '第1级' : '第2级';
        return `${s.name}(${loc},${s.foundAt.type})`;
      }).join(', ');

      const missingList = r.studentResults.filter(s => !s.found).map(s => s.name).join(', ');

      if (foundList) md += `- 已找到: ${foundList}\n`;
      if (missingList) md += `- 未找到: ${missingList}\n`;
      md += `\n`;

      for (const issue of realIssues) {
        md += `- ⚠️ ${issue}\n`;
      }
      md += `\n`;
    }
  }

  // 第2级查找提示详情
  const hintCourses = allResults.filter(r => r.issues.some(i => i.includes('建议确认')));
  if (hintCourses.length > 0) {
    md += `\n## 第2级查找提示（课评在非精确匹配目录中找到）\n\n`;
    for (const r of hintCourses) {
      const hints = r.issues.filter(i => i.includes('建议确认'));
      md += `### ${r.date} ${r.time} - ${r.className}\n\n`;
      md += `- 精确目录: ${r.level1Dir || '无'}\n`;
      md += `- 实际找到目录: ${r.level2Dirs.join(', ')}\n\n`;
      for (const h of hints) {
        md += `- 💡 ${h}\n`;
      }
      md += `\n`;
    }
  }

  fs.writeFileSync(reportPath, md);
  console.log(`\n\n详细报告已保存: ${reportPath}`);
}

main().catch(console.error);
