#!/usr/bin/env node
'use strict';

const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');

function emit(stage, message, status = 'running', extra = {}) {
  process.stderr.write(JSON.stringify({
    type: 'process_event',
    stage,
    message,
    status,
    timestamp: new Date().toISOString(),
    ...extra,
  }) + '\n');
}

function readInput() {
  const raw = String(process.argv[2] || process.env.SKILL_INPUT || process.env.AIFLOW_SKILL_INPUT || fs.readFileSync(0, 'utf8')).trim();
  return raw ? JSON.parse(raw) : {};
}

function workspaceRoot(env) {
  if (env.VEHICLE_SCRATCH_WORKSPACE_ROOT) return path.resolve(env.VEHICLE_SCRATCH_WORKSPACE_ROOT);
  if (env.RZYX_AI_WORKSPACE_ROOT) {
    const root = path.resolve(env.RZYX_AI_WORKSPACE_ROOT);
    return path.basename(root) === 'vehicle-scratch-inspection' ? root : path.join(root, 'vehicle-scratch-inspection');
  }
  if (env.RZYX_AI_DATA_DIR) return path.join(path.resolve(env.RZYX_AI_DATA_DIR), 'workspace', 'vehicle-scratch-inspection');
  return path.join(os.tmpdir(), 'vehicle-scratch-inspection');
}

function workspaceFor(taskId, env) {
  const safe = String(taskId || '').trim();
  if (!/^[a-zA-Z0-9_-]{1,80}$/.test(safe)) throw new Error('taskId非法或为空');
  const workspacePath = path.join(workspaceRoot(env), safe);
  if (!fs.existsSync(workspacePath)) throw new Error(`workspace不存在: ${workspacePath}`);
  return { taskId: safe, workspacePath };
}

function readJsonIfExists(filePath, fallback = {}) {
  try {
    return JSON.parse(fs.readFileSync(filePath, 'utf8'));
  } catch {
    return fallback;
  }
}

function writeText(filePath, text) {
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
  fs.writeFileSync(filePath, text, 'utf8');
}

function escapeHtml(value) {
  return String(value ?? '').replace(/[&<>"']/g, ch => ({
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;',
  }[ch]));
}

function valueOrDash(value) {
  if (value === null || value === undefined || value === '') return '-';
  return String(value);
}

function imageDataUri(filePath) {
  try {
    const ext = path.extname(filePath).toLowerCase();
    const mime = ext === '.png'
      ? 'image/png'
      : ext === '.svg'
        ? 'image/svg+xml'
        : 'image/jpeg';
    return `data:${mime};base64,${fs.readFileSync(filePath).toString('base64')}`;
  } catch {
    return '';
  }
}

function publicUrl(workspace, relativePath) {
  return `/workspace/vehicle-scratch-inspection/${workspace.taskId}/${relativePath.replace(/\\/g, '/')}`;
}

function severityWeight(severity) {
  const text = String(severity || '');
  if (text.includes('严重')) return 2.5;
  if (text.includes('中')) return 1.5;
  return 0.8;
}

function computeScore(damages) {
  const penalty = damages.reduce((sum, item) => sum + severityWeight(item.severity), 0);
  return Math.max(1, Math.min(10, Number((10 - penalty).toFixed(1))));
}

function scoreText(score) {
  if (score >= 8.5) return '车况较好';
  if (score >= 7) return '车况良好';
  if (score >= 5) return '车况一般';
  return '车况较差';
}

function plateMatch(vehicle) {
  const front = vehicle.frontPlate;
  const rear = vehicle.rearPlate;
  if (front && rear) return front === rear ? '一致' : '不一致';
  if (front || rear) return '仅识别到一处';
  return '均未识别';
}

function vinMatch(vehicle) {
  const w = vehicle.windshieldVin;
  const n = vehicle.nameplateVin;
  if (w && n) return w === n ? '一致' : '不一致';
  if (w || n) return '仅识别到一处';
  return '均未识别';
}

function tireOverview(vehicle) {
  const health = vehicle.tireTreadHealth || {};
  const values = Object.values(health).filter(Boolean);
  if (values.length === 0) return '未识别到明确轮胎纹理健康度';
  return `已识别轮胎纹理健康度：${values.join('、')}`;
}

function buildSummary(vehicle, damages, score) {
  const brand = vehicle.vehicleBrandModel ? `车辆疑似为${vehicle.vehicleBrandModel}` : '车辆品牌型号未明确识别';
  const damageText = damages.length ? `共检测到${damages.length}处去重后的旧伤` : '未检测到明确旧伤';
  return `${brand}，${damageText}，综合评分${score}/10，${scoreText(score)}。`;
}

function buildRecommendations(damages) {
  if (!damages.length) return ['建议保留本次环车检测报告作为交付/承保留档。'];
  const recs = ['建议对报告中红框标注的旧伤进行人工复核，确认是否需在承保或交付资料中备注。'];
  if (damages.some(item => String(item.severity).includes('严重'))) recs.push('存在严重旧伤，建议进一步线下定损并补充维修方案。');
  if (damages.some(item => /裂纹|破损|凹陷/.test(String(item.type)))) recs.push('对裂纹、破损或凹陷类损伤建议优先检查结构影响和维修成本。');
  return recs;
}

function vehicleRows(vehicle) {
  return [
    ['车辆品牌型号', vehicle.vehicleBrandModel],
    ['前车牌号', vehicle.frontPlate],
    ['后车牌号', vehicle.rearPlate],
    ['挡风玻璃VIN', vehicle.windshieldVin],
    ['铭牌VIN', vehicle.nameplateVin],
    ['VIN一致性', vinMatch(vehicle)],
    ['前后车牌一致性', plateMatch(vehicle)],
    ['仪表盘总里程', vehicle.odometerKm ? `${vehicle.odometerKm} km` : null],
    ['胎压', JSON.stringify(vehicle.tirePressure || {})],
    ['轮胎纹理健康度', JSON.stringify(vehicle.tireTreadHealth || {})],
    ['轮胎品牌型号规格', JSON.stringify(vehicle.tireSpecs || {})],
  ];
}

function buildHtml({ workspace, videoInfo, vehicle, damages, bestFrameImages, score, summary, recommendations }) {
  const damageRows = damages.map((item, index) => `
    <tr>
      <td>${index + 1}</td>
      <td>${escapeHtml(item.location)}</td>
      <td>${escapeHtml(item.type)}</td>
      <td>${escapeHtml(item.severity)}</td>
      <td>${escapeHtml((item.timestamps || []).map(ts => `${Number(ts).toFixed(2)}s`).join(', '))}</td>
      <td>${escapeHtml(item.description)}</td>
    </tr>`).join('');

  const detailCards = damages.map((item, index) => {
    const images = (item.bestFrames || []).map(frame => {
      const src = imageDataUri(frame.path);
      if (!src) return '';
      return `<figure><img src="${src}" alt="旧伤${index + 1}最佳帧"><figcaption>${escapeHtml(Number(frame.timestamp || 0).toFixed(2))}s</figcaption></figure>`;
    }).join('');
    return `<section class="damage-detail">
      <h3>${index + 1}. ${escapeHtml(item.location)} ${escapeHtml(item.type)}</h3>
      <p><strong>严重程度：</strong>${escapeHtml(item.severity)}</p>
      <p>${escapeHtml(item.description)}</p>
      <div class="image-grid">${images || '<p class="muted">未生成最佳展示帧</p>'}</div>
    </section>`;
  }).join('');

  const vehicleTable = vehicleRows(vehicle).map(([k, v]) => `<tr><th>${escapeHtml(k)}</th><td>${escapeHtml(valueOrDash(v))}</td></tr>`).join('');
  const recItems = recommendations.map(item => `<li>${escapeHtml(item)}</li>`).join('');

  return `<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>环车旧伤检测报告 - ${escapeHtml(workspace.taskId)}</title>
  <style>
    body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif; color: #18202b; background: #f4f6f8; }
    header { background: #18202b; color: white; padding: 28px 36px; }
    main { max-width: 1120px; margin: 0 auto; padding: 24px; }
    h1, h2, h3 { margin: 0 0 12px; }
    section { background: white; border: 1px solid #dfe5ec; border-radius: 8px; padding: 20px; margin-bottom: 16px; }
    .cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
    .card { background: #eef3f8; border-radius: 8px; padding: 14px; }
    .card strong { display: block; font-size: 24px; margin-top: 4px; }
    table { width: 100%; border-collapse: collapse; }
    th, td { border-bottom: 1px solid #e6ebf0; padding: 10px; text-align: left; vertical-align: top; }
    th { width: 180px; color: #455465; background: #f7f9fb; }
    .image-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; }
    figure { margin: 0; border: 1px solid #e0e5ea; border-radius: 8px; overflow: hidden; background: #fbfcfd; }
    img { display: block; width: 100%; height: auto; }
    figcaption { padding: 8px 10px; color: #5b6673; font-size: 13px; }
    .muted { color: #697586; }
    @media (max-width: 760px) { .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } main { padding: 12px; } header { padding: 20px; } }
  </style>
</head>
<body>
  <header>
    <h1>环车旧伤检测报告</h1>
    <p>任务ID：${escapeHtml(workspace.taskId)} ｜ 生成时间：${escapeHtml(new Date().toLocaleString('zh-CN', { hour12: false }))}</p>
  </header>
  <main>
    <section>
      <h2>检测概况</h2>
      <p>${escapeHtml(summary)}</p>
      <div class="cards">
        <div class="card">旧伤总数<strong>${damages.length}</strong></div>
        <div class="card">车况评分<strong>${score}/10</strong></div>
        <div class="card">抽帧数量<strong>${escapeHtml(videoInfo.extractedFrames || 0)}</strong></div>
        <div class="card">视频时长<strong>${escapeHtml(videoInfo.duration || 0)}s</strong></div>
      </div>
    </section>
    <section>
      <h2>车辆信息</h2>
      <table>${vehicleTable}</table>
    </section>
    <section>
      <h2>视频信息</h2>
      <table>
        <tr><th>分辨率</th><td>${escapeHtml(valueOrDash(videoInfo.resolution))}</td></tr>
        <tr><th>原始帧率</th><td>${escapeHtml(valueOrDash(videoInfo.videoFps))}</td></tr>
        <tr><th>抽帧FPS</th><td>${escapeHtml(valueOrDash(videoInfo.extractFps))}</td></tr>
        <tr><th>总帧数估算</th><td>${escapeHtml(valueOrDash(videoInfo.totalFrames))}</td></tr>
      </table>
    </section>
    <section>
      <h2>损伤汇总</h2>
      <table>
        <thead><tr><th>序号</th><th>位置</th><th>类型</th><th>严重程度</th><th>时间</th><th>描述</th></tr></thead>
        <tbody>${damageRows || '<tr><td colspan="6">未检测到明确旧伤</td></tr>'}</tbody>
      </table>
    </section>
    ${detailCards}
    <section>
      <h2>处理建议</h2>
      <ul>${recItems}</ul>
    </section>
  </main>
</body>
</html>`;
}

function buildMarkdown({ workspace, videoInfo, vehicle, damages, score, summary, recommendations, reportUrl }) {
  const lines = [
    '# 环车旧伤检测报告',
    '',
    `- 任务ID：${workspace.taskId}`,
    `- 报告URL：${reportUrl}`,
    `- 检测摘要：${summary}`,
    `- 车况评分：${score}/10`,
    `- 视频信息：${valueOrDash(videoInfo.duration)}秒，${valueOrDash(videoInfo.resolution)}，抽帧${valueOrDash(videoInfo.extractedFrames)}张`,
    '',
    '## 车辆信息',
    '',
    `- 品牌型号：${valueOrDash(vehicle.vehicleBrandModel)}`,
    `- 前车牌：${valueOrDash(vehicle.frontPlate)}`,
    `- 后车牌：${valueOrDash(vehicle.rearPlate)}`,
    `- 挡风玻璃VIN：${valueOrDash(vehicle.windshieldVin)}`,
    `- 铭牌VIN：${valueOrDash(vehicle.nameplateVin)}`,
    `- VIN一致性：${vinMatch(vehicle)}`,
    `- 前后车牌一致性：${plateMatch(vehicle)}`,
    `- 仪表盘里程：${vehicle.odometerKm ? `${vehicle.odometerKm} km` : '-'}`,
    `- 轮胎概况：${tireOverview(vehicle)}`,
    '',
    '## 损伤汇总',
    '',
  ];
  if (!damages.length) {
    lines.push('未检测到明确旧伤。');
  } else {
    damages.forEach((item, index) => {
      lines.push(`${index + 1}. ${item.location}｜${item.type}｜${item.severity}｜${item.description}`);
    });
  }
  lines.push('', '## 处理建议', '');
  recommendations.forEach(item => lines.push(`- ${item}`));
  return lines.join('\n');
}

async function run(input, env = process.env) {
  if (!input?.taskId) throw new Error('taskId不能为空');
  const workspace = workspaceFor(input.taskId, env);
  const videoDoc = readJsonIfExists(path.join(workspace.workspacePath, 'video_info.json'));
  const damageDoc = readJsonIfExists(path.join(workspace.workspacePath, 'damages.json'));
  const bestDoc = readJsonIfExists(path.join(workspace.workspacePath, 'best_frames.json'));
  const videoInfo = videoDoc.videoInfo || {};
  const vehicle = damageDoc.vehicleInfo || {};
  const damages = bestDoc.damages || damageDoc.damages || [];
  const bestFrameImages = bestDoc.bestFrameImages || [];
  const score = computeScore(damages);
  const summary = buildSummary(vehicle, damages, score);
  const recommendations = buildRecommendations(damages);
  const html = buildHtml({ workspace, videoInfo, vehicle, damages, bestFrameImages, score, summary, recommendations });
  const reportRelativePath = 'report/index.html';
  const reportPath = path.join(workspace.workspacePath, reportRelativePath);
  writeText(reportPath, html);
  const reportUrl = publicUrl(workspace, reportRelativePath);
  const reportMarkdown = buildMarkdown({ workspace, videoInfo, vehicle, damages, score, summary, recommendations, reportUrl });
  writeText(path.join(workspace.workspacePath, 'report/report.md'), reportMarkdown);
  emit('generate_report', 'HTML检测报告已生成', 'completed', { reportUrl, totalDamages: damages.length });
  return {
    success: true,
    reportUrl,
    reportPath,
    totalDamages: damages.length,
    conditionScore: score,
    summary,
    reportMarkdown,
  };
}

(async () => {
  try {
    process.stdout.write(JSON.stringify(await run(readInput())));
  } catch (err) {
    process.stdout.write(JSON.stringify({
      success: false,
      error: err && err.message ? err.message : String(err),
    }));
  }
})();
