import { ref, watch } from 'vue'

import {
  fetchAgentAssetReleaseReviewQueue,
  fetchAgentAssetReleaseState,
  labelAgentAssetReleaseObservation
} from '../../services/agentAssets.js'

function requestId(assetId, observationId, label) {
  const suffix = typeof globalThis.crypto?.randomUUID === 'function'
    ? globalThis.crypto.randomUUID()
    : `${Date.now()}-${Math.random().toString(16).slice(2)}`
  return `release-review:${assetId}:${observationId}:${label}:${suffix}`.slice(0, 160)
}

export function buildReleaseMonitorMetricCards(reviewQueue = {}) {
  const metrics = reviewQueue?.metrics || {}
  const recall = metricNumber(metrics.recall)
  const recallLowerBound = metricNumber(metrics.recall_lower_bound)
  const groundTruthStatus = String(metrics.negative_ground_truth_status || '').trim()
  const recallReady = groundTruthStatus.startsWith('available_')
    && recall !== null
    && recallLowerBound !== null
  const confidence = metricNumber(metrics.recall_confidence_level)
  const falseNegativeCount = metricNumber(metrics.false_negative_count)
  const estimatedFalseNegativeCount = metricNumber(metrics.estimated_false_negative_count)
  const falseNegativeUpperBound = metricNumber(metrics.false_negative_upper_bound)

  return [
    { label: '运行样本', value: countLabel(metrics.observed_count), hint: '真实执行次数' },
    { label: '待盲审', value: countLabel(reviewQueue.pending_total), hint: '正负样本随机混排' },
    {
      label: '负样本池',
      value: countLabel(metrics.negative_sample_count),
      hint: `已标注 ${countLabel(metrics.negative_labeled_count)}`
    },
    {
      label: '负样本标注进度',
      value: progress(metrics.negative_labeled_count, metrics.negative_sample_count),
      hint: progressHint(metrics.negative_labeled_count, metrics.negative_sample_count)
    },
    {
      label: '负样本积压',
      value: countLabel(metrics.negative_pending_label_count),
      hint: '盲审完成前不自动晋级'
    },
    {
      label: '随机负样本抽检',
      value: progress(metrics.random_negative_labeled_count, metrics.random_negative_sample_count),
      hint: randomSampleHint(metrics)
    },
    {
      label: '运行失败',
      value: countLabel(metrics.runtime_failure_count),
      hint: `失败率 ${percent(metrics.runtime_failure_rate)}`
    },
    {
      label: '实际漏检',
      value: nullableNumber(falseNegativeCount),
      hint: falseNegativeCount === null
        ? '负样本真值未就绪，不按 0 展示'
        : '独立盲审确认的真实漏检'
    },
    {
      label: '估计漏检',
      value: nullableNumber(estimatedFalseNegativeCount),
      hint: falseNegativeUpperBound === null
        ? '保守上界不可用'
        : `保守上界 ${decimal(falseNegativeUpperBound)}`
    },
    {
      label: '召回率',
      value: recallReady ? percent(recall) : '不可用',
      hint: recallReady
        ? `保守下界 ${percent(recallLowerBound)}${confidence === null ? '' : ` · ${(confidence * 100).toFixed(0)}% 置信度`} · ${recallMethodLabel(metrics.recall_method)}`
        : negativeGroundTruthHint(groundTruthStatus)
    }
  ]
}

export function buildReleaseReviewDocumentRoute(item = {}) {
  const documentId = String(item?.source_document_id || '').trim()
  if (!documentId || documentId.length > 160) return null
  return { name: 'app-document-detail', params: { requestId: documentId } }
}

export function useAuditReleaseMonitor({ selectedSkill, canManageSelected, toast }) {
  const releaseState = ref(null)
  const releaseQueue = ref(null)
  const releaseLoading = ref(false)
  const releaseError = ref('')
  const releaseAction = ref('')
  let loadSequence = 0

  function reset() {
    releaseState.value = null
    releaseQueue.value = null
    releaseError.value = ''
    releaseAction.value = ''
  }

  async function loadReleaseMonitor() {
    const assetId = String(selectedSkill.value?.id || '').trim()
    const stage = String(selectedSkill.value?.configJson?.release_guard?.stage || '').trim()
    if (!assetId || !selectedSkill.value?.usesJsonRiskRule || !stage || stage === 'rolled_back') {
      reset()
      return
    }
    const sequence = ++loadSequence
    releaseLoading.value = true
    releaseError.value = ''
    try {
      const [state, queue] = await Promise.all([
        fetchAgentAssetReleaseState(assetId),
        fetchAgentAssetReleaseReviewQueue(assetId)
      ])
      if (sequence !== loadSequence || selectedSkill.value?.id !== assetId) return
      releaseState.value = state
      releaseQueue.value = queue
    } catch (error) {
      if (sequence !== loadSequence) return
      releaseError.value = error?.message || '发布遥测加载失败，请稍后重试。'
    } finally {
      if (sequence === loadSequence) releaseLoading.value = false
    }
  }

  async function submitReleaseLabel(observationId, label) {
    const assetId = String(selectedSkill.value?.id || '').trim()
    if (!assetId || !canManageSelected.value || releaseAction.value) return
    releaseAction.value = `${observationId}:${label}`
    try {
      const result = await labelAgentAssetReleaseObservation(assetId, observationId, label, {
        requestId: requestId(assetId, observationId, label)
      })
      toast(
        label === 'risk_present'
          ? '已提交“存在真实风险”，发布指标已重新聚合。'
          : '已提交“确认无该风险”，发布指标已重新聚合。'
      )
      await loadReleaseMonitor()
      return result
    } catch (error) {
      toast(error?.message || '发布复核提交失败，请稍后重试。')
      return null
    } finally {
      releaseAction.value = ''
    }
  }

  watch(
    () => [
      selectedSkill.value?.id || '',
      selectedSkill.value?.configJson?.release_guard?.release_id || '',
      selectedSkill.value?.configJson?.release_guard?.stage || '',
      selectedSkill.value?.loading ? '1' : '0'
    ],
    () => {
      if (selectedSkill.value?.loading) return
      void loadReleaseMonitor()
    },
    { immediate: true }
  )

  return {
    releaseState,
    releaseQueue,
    releaseLoading,
    releaseError,
    releaseAction,
    loadReleaseMonitor,
    submitReleaseLabel
  }
}

function metricNumber(value) {
  if (value === null || typeof value === 'undefined' || value === '') return null
  const parsed = Number(value)
  return Number.isFinite(parsed) ? parsed : null
}

function countLabel(value) {
  const parsed = metricNumber(value)
  return parsed === null ? '不可用' : Math.max(0, parsed).toLocaleString('zh-CN')
}

function nullableNumber(value) {
  return value === null ? '不可用' : decimal(value)
}

function decimal(value) {
  const parsed = metricNumber(value)
  if (parsed === null) return '不可用'
  return parsed.toLocaleString('zh-CN', { maximumFractionDigits: 2 })
}

function percent(value) {
  const parsed = metricNumber(value)
  return parsed === null ? '不可用' : `${(parsed * 100).toFixed(1)}%`
}

function progress(completed, total) {
  const completedCount = metricNumber(completed)
  const totalCount = metricNumber(total)
  if (completedCount === null || totalCount === null || totalCount <= 0) return '不可用'
  return percent(Math.min(Math.max(completedCount / totalCount, 0), 1))
}

function progressHint(completed, total) {
  const completedCount = metricNumber(completed)
  const totalCount = metricNumber(total)
  if (completedCount === null || totalCount === null || totalCount <= 0) {
    return '负样本证据未就绪'
  }
  const completedLabel = countLabel(completed)
  const totalLabel = countLabel(total)
  return `${completedLabel}/${totalLabel} 已完成`
}

function randomSampleHint(metrics = {}) {
  const sampleCount = metricNumber(metrics.random_negative_sample_count)
  if (sampleCount === null || sampleCount <= 0) return '随机负样本证据未就绪'
  const sample = countLabel(metrics.random_negative_sample_count)
  const labeled = countLabel(metrics.random_negative_labeled_count)
  const population = countLabel(metrics.random_negative_population_count)
  if ([sample, labeled, population].includes('不可用')) return '随机负样本证据未就绪'
  return `抽检 ${labeled}/${sample} · 总体 ${population}`
}

function negativeGroundTruthHint(status) {
  return {
    available_stratified_random_audit: '负样本证据已就绪，但当前没有可计算分母',
    collecting_candidate_labels: '正负样本标签采集中',
    insufficient_random_negative_reviews: '随机负样本复核不足',
    unavailable: '负样本证据未就绪'
  }[status] || '负样本证据未就绪'
}

function recallMethodLabel(method) {
  return method === 'stratified_random_audit_wilson_upper_bound'
    ? '分层随机盲审 Wilson 保守上界'
    : '独立负样本盲审'
}
