// scripts/skyeye/report-generator.js
// 天眼·全局健康报告生成器
//
// 汇总所有扫描结果 + 诊断 + 修复结果 → 生成统一报告
// 报告写入：/tmp/skyeye/full-report.json + memory.json skyeye 段

'use strict';

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

const ROOT      = path.resolve(__dirname, '../..');
const SKYEYE_DIR = '/tmp/skyeye';
const BRAIN_DIR = path.join(ROOT, '.github/persona-brain');
const MEMORY_PATH = path.join(BRAIN_DIR, 'memory.json');

const BEIJING_OFFSET_MS = 8 * 3600 * 1000;
const startTime = Date.now();

// ━━━ 安全读取 JSON ━━━
function readJSON(filePath) {
  try {
    if (!fs.existsSync(filePath)) return null;
    return JSON.parse(fs.readFileSync(filePath, 'utf8'));
  } catch (e) {
    return null;
  }
}

// ━━━ 生成报告 ━━━
function generateReport() {
  const now = new Date();
  const dateStr = now.toISOString().slice(0, 10);
  const bjTime = new Date(now.getTime() + BEIJING_OFFSET_MS).toISOString()
    .replace('T', ' ').slice(0, 19) + '+08:00';

  // 读取所有扫描结果
  const wfHealth       = readJSON(path.join(SKYEYE_DIR, 'workflow-health.json'));
  const structHealth   = readJSON(path.join(SKYEYE_DIR, 'structure-health.json'));
  const brainHealth    = readJSON(path.join(SKYEYE_DIR, 'brain-health.json'));
  const bridgeHealth   = readJSON(path.join(SKYEYE_DIR, 'bridge-health.json'));
  const securityHealth = readJSON(path.join(SKYEYE_DIR, 'security-health.json'));
  const sfpHealth      = readJSON(path.join(SKYEYE_DIR, 'sfp-health.json'));
  const soldierHealth  = readJSON(path.join(SKYEYE_DIR, 'soldier-health.json'));
  const diagnosis      = readJSON(path.join(SKYEYE_DIR, 'diagnosis.json'));
  const repairResult   = readJSON(path.join(SKYEYE_DIR, 'repair-result.json'));

  // 计算时长
  const durationSeconds = Math.round((Date.now() - startTime) / 1000);

  // 确定整体健康度
  let overallHealth = '🟢';
  if (diagnosis && diagnosis.needs_human > 0) {
    overallHealth = '🔴';
  } else if (diagnosis && diagnosis.total_issues > 0) {
    overallHealth = '🟡';
  }

  // 构建报告
  const report = {
    report_id: `SKYEYE-${dateStr.replace(/-/g, '')}`,
    timestamp: bjTime,
    duration_seconds: durationSeconds,
    overall_health: overallHealth,

    brain_status: {
      integrity: brainHealth ? brainHealth.integrity : 'unknown',
      memory_fresh: brainHealth ? brainHealth.memory_fresh : false,
      routing_map_aligned: brainHealth ? brainHealth.routing_map_aligned : false,
      dev_status_last_sync: brainHealth && brainHealth.dev_status
        ? brainHealth.dev_status.last_sync : null,
      knowledge_base_entries: brainHealth && brainHealth.knowledge_base
        ? brainHealth.knowledge_base.entries : 0
    },

    workflow_health: {
      total: wfHealth ? wfHealth.total_workflows : 0,
      healthy: wfHealth ? wfHealth.healthy : 0,
      failed: wfHealth ? (wfHealth.total_workflows - wfHealth.healthy) : 0,
      never_triggered: 0, // Determined from recent runs
      conflicts: wfHealth ? (wfHealth.cron_conflicts || []).length : 0,
      details: wfHealth ? (wfHealth.workflow_map || []).map(w => ({
        name: w.name,
        file: w.file,
        status: w.status,
        last_run: w.last_run || 'unknown'
      })) : []
    },

    structure_health: {
      core_dirs_ok: structHealth ? structHealth.core_dirs_ok : false,
      orphan_files: structHealth ? structHealth.orphan_files : 0,
      missing_dirs: structHealth ? structHealth.missing_dirs : [],
      readme_ok: structHealth ? structHealth.readme_ok : false
    },

    bridge_health: {
      notion_api: bridgeHealth ? bridgeHealth.notion_api.status : '❓',
      server_ssh: bridgeHealth ? bridgeHealth.server_ssh.status : '❓',
      github_api: bridgeHealth ? bridgeHealth.github_api.status : '❓',
      secrets_complete: bridgeHealth && bridgeHealth.secrets
        ? bridgeHealth.secrets.complete : false
    },

    security_health: securityHealth && securityHealth.security_health
      ? securityHealth.security_health
      : {
          protocol_exists: false,
          root_rules_intact: false,
          level: null,
          permanent: false,
          copyright_anchor: false,
          last_verified: bjTime
        },

    bulletin_sfp_health: sfpHealth ? {
      dimension: 'D14',
      status: sfpHealth.status || '❓',
      total_messages: sfpHealth.total_messages || 0,
      valid_fingerprints: sfpHealth.valid_fingerprints || 0,
      invalid_fingerprints: sfpHealth.invalid_fingerprints || 0,
      without_fingerprint: sfpHealth.without_fingerprint || 0,
      sfp_config_exists: sfpHealth.sfp_config_exists || false,
      agent_activity: sfpHealth.agent_activity || {}
    } : { dimension: 'D14', status: '❓' },

    soldier_health: soldierHealth ? {
      dimension: 'D15',
      status: soldierHealth.status || '❓',
      total_soldiers: soldierHealth.total_soldiers || 0,
      healthy: soldierHealth.healthy || 0,
      failed: soldierHealth.failed || 0,
      failure_rate: soldierHealth.failure_rate || 0,
      recurring_errors: soldierHealth.recurring_errors || [],
      recommendations: soldierHealth.recommendations || []
    } : { dimension: 'D15', status: '❓' },

    hibernation_status: (() => {
      const hibDir = path.join(ROOT, 'skyeye/hibernation');
      const cpDir = path.join(hibDir, 'checkpoints');
      const snapDir = path.join(hibDir, 'weekly-snapshots');
      const upDir = path.join(hibDir, 'upgrade-packs');
      const distDir = path.join(hibDir, 'distribution-reports');
      const deployed = fs.existsSync(hibDir);
      let dailyCPs = 0, weeklySnaps = 0, upgradePacks = 0, distReports = 0;
      let lastDaily = null, lastWeekly = null;
      try {
        if (fs.existsSync(cpDir)) {
          const cpFiles = fs.readdirSync(cpDir).filter(f => f.startsWith('daily-cp-') && f.endsWith('.json')).sort();
          dailyCPs = cpFiles.length;
          if (cpFiles.length > 0) lastDaily = cpFiles[cpFiles.length - 1];
        }
        if (fs.existsSync(snapDir)) {
          const snapFiles = fs.readdirSync(snapDir).filter(f => f.endsWith('.json')).sort();
          weeklySnaps = snapFiles.length;
          if (snapFiles.length > 0) lastWeekly = snapFiles[snapFiles.length - 1];
        }
        if (fs.existsSync(upDir)) {
          upgradePacks = fs.readdirSync(upDir).filter(f => f.endsWith('.json')).length;
        }
        if (fs.existsSync(distDir)) {
          distReports = fs.readdirSync(distDir).filter(f => f.endsWith('.json')).length;
        }
      } catch (e) { /* ignore */ }
      return {
        deployed,
        daily_checkpoints: dailyCPs,
        weekly_snapshots: weeklySnaps,
        upgrade_packs: upgradePacks,
        distribution_reports: distReports,
        last_daily_checkpoint: lastDaily,
        last_weekly_snapshot: lastWeekly
      };
    })(),

    diagnosis: {
      total_issues: diagnosis ? diagnosis.total_issues : 0,
      auto_fixed: repairResult ? repairResult.total_repaired : 0,
      needs_human: diagnosis ? diagnosis.needs_human : 0,
      watching: diagnosis ? diagnosis.watch_list : 0,
      issues: diagnosis ? (diagnosis.issues || []).map(i => {
        const repairEntry = repairResult
          ? (repairResult.repairs || []).find(r => r.issue_id === i.id)
          : null;
        return {
          id: i.id,
          symptom: i.symptom,
          root_cause: i.root_cause,
          impact: i.impact,
          fix_applied: i.fixable ? i.fix_plan : null,
          verified: repairEntry ? repairEntry.verified : false
        };
      }) : []
    },

    repairs_applied: repairResult
      ? (repairResult.repairs || []).filter(r => r.success).map(r => r.symptom)
      : [],
    tickets_created: repairResult
      ? (repairResult.tickets || [])
      : [],
    path_activity: {
      most_used_today: ['GH-WF-RUN-GATE', 'BRIDGE-GH2NT-SYSLOG'],
      failed_paths: [],
      new_paths_detected: []
    },
    next_actions: []
  };

  // 生成下一步建议
  if (diagnosis && diagnosis.watch_list > 0) {
    report.next_actions.push('持续观察 watch_list 中的问题');
  }
  if (report.brain_status.integrity !== 'ok') {
    report.next_actions.push('核心大脑需要修复');
  }
  if (!report.brain_status.memory_fresh) {
    report.next_actions.push('memory.json 数据需要刷新');
  }
  if (!report.security_health.protocol_exists) {
    report.next_actions.push('P0: 安全协议文件缺失，需立即恢复');
  } else if (!report.security_health.root_rules_intact) {
    report.next_actions.push('P0: 安全协议根规则被篡改，需立即修复');
  } else if (report.security_health.level !== 'L0' || !report.security_health.permanent) {
    report.next_actions.push('P0: 安全协议L0等级或永久标记被修改');
  } else if (!report.security_health.copyright_anchor) {
    report.next_actions.push('P1: 安全协议版权锚点缺失，需补充');
  }
  if (report.bulletin_sfp_health && report.bulletin_sfp_health.invalid_fingerprints > 0) {
    report.next_actions.push('P0: 公告板发现无效指纹内容，需立即清理');
  }
  if (report.soldier_health && report.soldier_health.failure_rate > 20) {
    report.next_actions.push('P0: 小兵故障率超过20%，需全局修复');
  }
  if (report.soldier_health && report.soldier_health.recurring_errors &&
      report.soldier_health.recurring_errors.length > 0) {
    report.next_actions.push('P1: 存在持续性故障小兵，建议铸渊介入');
  }
  if (!report.hibernation_status.deployed) {
    report.next_actions.push('P0: 休眠系统未部署，需立即部署 skyeye/hibernation/');
  }

  // 保存完整报告
  fs.mkdirSync(SKYEYE_DIR, { recursive: true });
  fs.writeFileSync(path.join(SKYEYE_DIR, 'full-report.json'), JSON.stringify(report, null, 2));

  // 更新 memory.json 的 skyeye 段
  updateMemory(report);

  console.log(JSON.stringify(report, null, 2));
  console.log(`\n🦅 天眼报告生成完毕 · ${report.report_id} · 整体健康: ${overallHealth}`);
}

// ━━━ 更新 memory.json ━━━
function updateMemory(report) {
  try {
    const mem = readJSON(MEMORY_PATH);
    if (!mem) return;

    // 添加 skyeye 段
    mem.skyeye = {
      last_run: report.timestamp,
      report_id: report.report_id,
      overall_health: report.overall_health,
      issues_found: report.diagnosis.total_issues,
      auto_fixed: report.diagnosis.auto_fixed,
      needs_human: report.diagnosis.needs_human
    };

    mem.last_updated = new Date().toISOString();

    // 添加天眼事件到 recent_events（检查重复）
    const eventDate = new Date().toISOString().slice(0, 10);
    const existingEvent = (mem.recent_events || []).find(
      e => e.date === eventDate && e.type === 'skyeye_scan'
    );

    if (!existingEvent) {
      if (!mem.recent_events) mem.recent_events = [];
      mem.recent_events.unshift({
        date: eventDate,
        type: 'skyeye_scan',
        description: `天眼扫描 · ${report.overall_health} · 问题:${report.diagnosis.total_issues} 自动修复:${report.diagnosis.auto_fixed} 需人工:${report.diagnosis.needs_human}`,
        by: '天眼系统'
      });

      // 保持最近 20 条事件
      if (mem.recent_events.length > 20) {
        mem.recent_events = mem.recent_events.slice(0, 20);
      }
    }

    fs.writeFileSync(MEMORY_PATH, JSON.stringify(mem, null, 2));
    console.log('✅ memory.json 已更新天眼段');
  } catch (e) {
    console.error('⚠️ 更新 memory.json 失败:', e.message);
  }
}

generateReport();
