import { counter, histogram, gauge } from "./metrics"
import { getLogger } from "./logger"

const log = getLogger("system")

// ── Search Telemetry ──

export const searchLatency = histogram("search_latency_ms", "search", "Latency of search operations in milliseconds")
export const searchCount = counter("search_total", "search", "Total number of search operations")
export const searchErrors = counter("search_errors", "search", "Total number of search failures")
export const searchFilesScanned = histogram("search_files_scanned", "search", "Number of files scanned per search")
export const searchResultsReturned = histogram("search_results_returned", "search", "Number of results returned per search")

export function recordSearch(durationMs: number, filesScanned: number, resultsCount: number, error?: string): void {
  searchCount.inc()
  searchLatency.observe(durationMs)
  searchFilesScanned.observe(filesScanned)
  searchResultsReturned.observe(resultsCount)
  if (error) {
    searchErrors.inc()
    log.warn("search failed", { error, durationMs, metadata: { filesScanned, resultsCount } })
  }
}

// ── Indexing Telemetry ──

export const indexingLatency = histogram("indexing_latency_ms", "indexing", "Time to index files in milliseconds")
export const indexingCount = counter("indexing_total", "indexing", "Total files indexed")
export const indexingErrors = counter("indexing_errors", "indexing", "Total indexing failures")
export const indexingFileSize = histogram("indexing_file_size_bytes", "indexing", "Size of indexed files in bytes")
export const indexingSymbolsFound = histogram("indexing_symbols_per_file", "indexing", "Symbols found per file")

export function recordIndexing(durationMs: number, fileCount: number, symbolCount: number, fileSizeBytes: number, error?: string): void {
  indexingCount.inc(fileCount)
  indexingLatency.observe(durationMs)
  indexingFileSize.observe(fileSizeBytes)
  indexingSymbolsFound.observe(symbolCount)
  if (error) {
    indexingErrors.inc()
    log.warn("indexing failed", { error, durationMs, metadata: { fileCount, symbolCount } })
  }
}

// ── Tool Telemetry ──

export const toolLatency = histogram("tool_latency_ms", "tool", "Latency of tool executions in milliseconds")
export const toolCount = counter("tool_total", "tool", "Total tool executions")
export const toolErrors = counter("tool_errors", "tool", "Total tool failures")
export const toolActive = gauge("tool_active", "tool", "Currently executing tools")

export function recordToolExecution(toolName: string, durationMs: number, error?: string): void {
  toolCount.inc()
  toolLatency.observe(durationMs)
  if (error) toolErrors.inc()
}

// ── Agent Telemetry ──

export const agentLatency = histogram("agent_latency_ms", "agent", "Agent execution latency in milliseconds")
export const agentCount = counter("agent_executions_total", "agent", "Total agent executions")
export const agentErrors = counter("agent_errors", "agent", "Total agent failures")
export const agentTokensGenerated = counter("agent_tokens_total", "agent", "Total tokens generated by agents")
export const agentSessions = gauge("agent_sessions_active", "agent", "Currently active agent sessions")
export const agentToolCallsPerSession = histogram("agent_tool_calls_per_session", "agent", "Tool calls per agent session")

export function recordAgentExecution(durationMs: number, tokensGenerated: number, toolCalls: number, error?: string): void {
  agentCount.inc()
  agentLatency.observe(durationMs)
  agentTokensGenerated.inc(tokensGenerated)
  agentToolCallsPerSession.observe(toolCalls)
  if (error) agentErrors.inc()
}

// ── Browser Telemetry ──

export const browserLatency = histogram("browser_latency_ms", "browser", "Browser operation latency in milliseconds")
export const browserCount = counter("browser_operations_total", "browser", "Total browser operations")
export const browserErrors = counter("browser_errors", "browser", "Total browser failures")
export const browserSessions = gauge("browser_sessions_active", "browser", "Currently active browser sessions")
export const browserTabs = gauge("browser_tabs_open", "browser", "Currently open browser tabs")
export const browserNavigationLatency = histogram("browser_navigation_latency_ms", "browser", "Page navigation latency")

export function recordBrowserOperation(operation: string, durationMs: number, error?: string): void {
  browserCount.inc()
  browserLatency.observe(durationMs)
  if (error) browserErrors.inc()
}

export function recordBrowserNavigation(durationMs: number): void {
  browserNavigationLatency.observe(durationMs)
}

// ── Memory Telemetry ──

export const memoryHeapUsed = gauge("memory_heap_used_mb", "system", "Heap memory used in MB")
export const memoryHeapTotal = gauge("memory_heap_total_mb", "system", "Total heap memory in MB")
export const memoryGrowthRate = gauge("memory_growth_rate_mb_per_hour", "system", "Memory growth rate")

export function sampleMemory(): void {
  const usage = process.memoryUsage?.()
  if (!usage) return
  memoryHeapUsed.set(Math.round(usage.heapUsed / (1024 * 1024)))
  memoryHeapTotal.set(Math.round(usage.heapTotal / (1024 * 1024)))
}

// ── CPU Telemetry ──

export const cpuUser = gauge("cpu_user_percent", "system", "CPU user time percentage")
export const cpuSystem = gauge("cpu_system_percent", "system", "CPU system time percentage")
let lastCpuUsage = process.cpuUsage?.()

export function sampleCpu(): void {
  const current = process.cpuUsage?.()
  if (!current || !lastCpuUsage) {
    lastCpuUsage = current
    return
  }
  const userDelta = current.user - lastCpuUsage.user
  const sysDelta = current.system - lastCpuUsage.system
  const totalDelta = userDelta + sysDelta
  if (totalDelta > 0) {
    cpuUser.set(Math.round((userDelta / totalDelta) * 100))
    cpuSystem.set(Math.round((sysDelta / totalDelta) * 100))
  }
  lastCpuUsage = current
}

// ── Periodic Sampling ──

let samplingInterval: ReturnType<typeof setInterval> | null = null

export function startPeriodicSampling(intervalMs = 5000): void {
  stopPeriodicSampling()
  samplingInterval = setInterval(() => {
    sampleMemory()
    sampleCpu()
  }, intervalMs)
}

export function stopPeriodicSampling(): void {
  if (samplingInterval) {
    clearInterval(samplingInterval)
    samplingInterval = null
  }
}

// ── Provider Telemetry ──

export const providerLatency = histogram("provider_latency_ms", "network", "Provider request latency")
export const providerErrors = counter("provider_errors", "network", "Provider request failures")
export const providerTokensPerSecond = histogram("provider_tokens_per_second", "network", "Token generation speed")

export function recordProviderRequest(durationMs: number, tokensPerSec: number, error?: string): void {
  providerLatency.observe(durationMs)
  providerTokensPerSecond.observe(tokensPerSec)
  if (error) providerErrors.inc()
}
