const path = require('node:path');
const { parseJsonLoose, normalizePartName, runWithConcurrency } = require('./json_utils.cjs');
const { callVisionApi, imageContent } = require('./vision_client.cjs');
const { cropZoom } = require('./image_marker.cjs');
const { emitEvent, writeJson, toRelative, publicUrl } = require('./workspace.cjs');

function bestMarkedFrame(annotation) {
  const frames = annotation.markedFrames || [];
  return frames.find(frame => frame.bbox) || frames[0] || null;
}

async function reviewOne({ workspace, annotation, modelConfig, prompt, index }) {
  const frame = bestMarkedFrame(annotation);
  if (!frame) {
    return { annotation, confirmed: false, reason: '没有可复核帧', reviewImage: null };
  }
  const reviewName = `review_zoom_${annotation.damageId}_${frame.timestamp.toFixed(2).replace('.', '_')}s.jpg`;
  const reviewPath = path.join(workspace.workspacePath, 'source', reviewName);
  await cropZoom({
    sourcePath: frame.sourcePath || frame.path,
    targetPath: reviewPath,
    bbox: frame.bbox?.normalized || null,
  });

  const content = [
    { type: 'text', text: '原始帧：' },
    imageContent(frame.sourcePath || frame.path),
    { type: 'text', text: '候选区域放大图：' },
    imageContent(reviewPath),
    {
      type: 'text',
      text: `${prompt}\n候选：${annotation.part} ${annotation.type}。描述：${annotation.description}\n注意：放大图只用于复核，不用于重新标注位置。`,
    },
  ];
  const result = await callVisionApi({
    config: modelConfig,
    model: modelConfig.reviewModel,
    messages: [{ role: 'user', content }],
    maxTokens: 1024,
    temperature: 0.1,
  });
  const parsed = result.ok ? parseJsonLoose(result.content) : null;
  const confirmed = Boolean(parsed?.confirmed);
  const uncertain = !confirmed && /不清楚|无法|不能明确|模糊|反光|疑似|建议人工|无法确认/.test(String(parsed?.reason || result.error || ''));
  const reason = parsed?.reason || result.error || '模型未能明确确认';
  const reviewImage = {
    url: publicUrl(workspace, toRelative(workspace, reviewPath)),
    path: reviewPath,
    relativePath: toRelative(workspace, reviewPath),
    mimeType: 'image/jpeg',
    label: `放大复核图 ${annotation.damageId}`,
    purpose: 'model_uncertain_zoom_review',
    reason: `模型不清楚，放大后判断：${reason}`,
    damageId: annotation.damageId,
    timestamp: frame.timestamp,
    source: {
      type: 'model_uncertain_zoom_review',
      note: '模型不清楚时生成的放大复核图，供 agent 和前端展示',
    },
  };
  return {
    annotation: {
      ...annotation,
      part: normalizePartName(parsed?.part || annotation.part),
      type: parsed?.type || annotation.type,
      severity: parsed?.severity || annotation.severity,
      review: {
        confirmed,
        uncertain,
        confidence: parsed?.confidence ?? null,
        reason,
      },
    },
    confirmed,
    uncertain,
    reason,
    reviewImage,
    index,
  };
}

async function reviewDamageAnnotations({ workspace, annotations, modelConfig, prompt, concurrency = 3 }) {
  emitEvent('review', 'reviewing damage annotations with zoomed crops', { annotationCount: annotations.length, concurrency, model: modelConfig.reviewModel });
  const reviewImages = [];
  const reviewed = await runWithConcurrency(annotations.map((annotation, index) => () => reviewOne({
    workspace,
    annotation,
    modelConfig,
    prompt,
    index,
  })), concurrency);
  for (const result of reviewed) {
    if (result.reviewImage) reviewImages.push(result.reviewImage);
  }
  const accepted = reviewed.filter(item => item.confirmed).map(item => item.annotation);
  const uncertain = reviewed.filter(item => !item.confirmed && item.uncertain).map(item => item.annotation);
  const rejected = reviewed.filter(item => !item.confirmed && !item.uncertain);
  writeJson(workspace, 'damage_review.json', { accepted, uncertain, rejected, reviewImages });
  emitEvent('review', 'damage review complete', {
    annotationCount: accepted.length,
    uncertainCount: uncertain.length,
    rejectedCount: rejected.length,
    reviewImageCount: reviewImages.length,
  });
  return { accepted, uncertain, rejected, reviewImages };
}

module.exports = {
  bestMarkedFrame,
  reviewDamageAnnotations,
};
