import type { Router } from 'vue-router'
import { onCLS, onFCP, onINP, onLCP, onTTFB, type Metric } from 'web-vitals'
import { apiFetch } from './api'

type BrowserMetricName =
  | 'CLS'
  | 'FCP'
  | 'INP'
  | 'LCP'
  | 'TTFB'
  | 'board_content_visible'
  | 'board_delta_painted'
  | 'mutation_confirmed'
  | 'agent_proposal_readback'

export interface BrowserMetricEnvelope {
  name: BrowserMetricName
  value: number
  rating: 'good' | 'needs-improvement' | 'poor' | 'custom'
  routeName: string
  buildVersion: string
  navigationType: string
  liveMode: 'live' | 'polling' | 'unknown'
  correlationId: string | null
}

const STANDARD_METRICS = new Set<BrowserMetricName>(['CLS', 'FCP', 'INP', 'LCP', 'TTFB'])
let activeRouter: Router | null = null
let started = false

export function isBrowserTelemetryEnabled(): boolean {
  return String(import.meta.env.VITE_BROWSER_TELEMETRY_ENABLED ?? 'true').toLowerCase() !== 'false'
}

function safeRouteName(): string {
  const name = activeRouter?.currentRoute.value.name
  return typeof name === 'string' && /^[A-Za-z0-9 _-]{1,80}$/.test(name) ? name : 'unknown'
}

async function report(envelope: BrowserMetricEnvelope): Promise<void> {
  if (!isBrowserTelemetryEnabled() || safeRouteName() === 'Login') return
  try {
    await apiFetch('/api/v1/telemetry/browser', {
      method: 'POST',
      keepalive: true,
      body: JSON.stringify(envelope),
    })
  } catch {
    // Telemetry must never alter user-visible behavior.
  }
}

function fromWebVital(metric: Metric): BrowserMetricEnvelope | null {
  if (!STANDARD_METRICS.has(metric.name as BrowserMetricName)) return null
  return {
    name: metric.name as BrowserMetricName,
    value: metric.value,
    rating: metric.rating,
    routeName: safeRouteName(),
    buildVersion: String(import.meta.env.VITE_BUILD_VERSION || import.meta.env.VITE_BUILD_SHA || 'development').slice(0, 80),
    navigationType: String(metric.navigationType || 'navigate').slice(0, 40),
    liveMode: 'unknown',
    correlationId: null,
  }
}

export function startBrowserTelemetry(router: Router): void {
  activeRouter = router
  if (!isBrowserTelemetryEnabled() || started || typeof window === 'undefined') return
  started = true

  const callback = (metric: Metric) => {
    const envelope = fromWebVital(metric)
    if (envelope) void report(envelope)
  }

  onCLS(callback)
  onFCP(callback)
  onINP(callback)
  onLCP(callback)
  onTTFB(callback)
}

export async function reportCustomMetric(
  name: Exclude<BrowserMetricName, 'CLS' | 'FCP' | 'INP' | 'LCP' | 'TTFB'>,
  value: number,
  options: {
    liveMode?: BrowserMetricEnvelope['liveMode']
    correlationId?: string | null
  } = {},
): Promise<void> {
  if (!Number.isFinite(value) || value < 0) return
  await report({
    name,
    value,
    rating: 'custom',
    routeName: safeRouteName(),
    buildVersion: String(import.meta.env.VITE_BUILD_VERSION || import.meta.env.VITE_BUILD_SHA || 'development').slice(0, 80),
    navigationType: 'spa',
    liveMode: options.liveMode ?? 'unknown',
    correlationId: options.correlationId?.slice(0, 128) ?? null,
  })
}

export function markPerformance(name: string): void {
  if (typeof performance === 'undefined') return
  performance.mark(`nexus:${name}`)
}

export async function measurePerformance(
  metricName: Parameters<typeof reportCustomMetric>[0],
  startMark: string,
  endMark: string,
  options?: Parameters<typeof reportCustomMetric>[2],
): Promise<number | null> {
  if (typeof performance === 'undefined') return null
  const start = `nexus:${startMark}`
  const end = `nexus:${endMark}`
  try {
    const measurement = performance.measure(`nexus:${metricName}`, start, end)
    await reportCustomMetric(metricName, measurement.duration, options)
    return measurement.duration
  } catch {
    return null
  } finally {
    performance.clearMarks(start)
    performance.clearMarks(end)
  }
}
