/**
 * Transcript Debug Handler
 * Watches all agent project dirs (.claude-ejecutor/projects/, .claude-nucleo000/projects/)
 * for JSONL file changes and broadcasts notifications via the sync server.
 *
 * Uses a polling approach on Windows (fs.watch is unreliable for appends)
 * combined with fs.watch for immediate detection.
 */

import { watch, existsSync, readdirSync, statSync, type FSWatcher } from 'fs'
import { join } from 'path'
import { homedir } from 'os'

const AGENT_NAMES = ['ejecutor', 'nucleo000', 'claude']
const DEBOUNCE_MS = 25
const POLL_INTERVAL_MS = 1500

// Per-agent state
interface AgentWatcherState {
  projectDir: string
  watcher: FSWatcher | null
  fileSizeCache: Map<string, number>
  debounceTimer: ReturnType<typeof setTimeout> | null
}

const agentStates = new Map<string, AgentWatcherState>()
let pollTimer: ReturnType<typeof setInterval> | null = null

// Project hash matching the working dir
const PROJECT_HASH = 'C--Users-jodar-agent-ui'

function findProjectDir(workingDir: string, agent: string): string | null {
  const agentDir = agent === 'claude'
    ? join(homedir(), '.claude', 'projects')
    : join(workingDir, `.claude-${agent}`, 'projects')
  if (!existsSync(agentDir)) return null

  // For claude global dir, go straight to the project hash
  if (agent === 'claude') {
    const exact = join(agentDir, PROJECT_HASH)
    return existsSync(exact) ? exact : null
  }

  const dirs = readdirSync(agentDir)
  return dirs.length > 0 ? join(agentDir, dirs[0]) : null
}

function emitChange(agent: string, sessionId: string, filename: string, projectDir: string, broadcast: (message: string) => void) {
  const state = agentStates.get(agent)
  if (!state) return

  if (state.debounceTimer) clearTimeout(state.debounceTimer)
  state.debounceTimer = setTimeout(() => {
    const filePath = join(projectDir, filename)
    let size = 0
    try {
      size = statSync(filePath).size
    } catch {}

    console.log(`[TranscriptDebug:${agent}] Change: ${filename} (${size} bytes)`)
    broadcast(JSON.stringify({
      type: 'transcript-debug-change',
      sessionId,
      agent,
      filename,
      size,
      timestamp: Date.now()
    }))
  }, DEBOUNCE_MS)
}

export function setupTranscriptDebugWatcher(workingDir: string, broadcast: (message: string) => void) {
  let anyWatched = false

  for (const agent of AGENT_NAMES) {
    const projectDir = findProjectDir(workingDir, agent)
    if (!projectDir) continue

    const state: AgentWatcherState = {
      projectDir,
      watcher: null,
      fileSizeCache: new Map(),
      debounceTimer: null
    }

    // Initialize file size cache
    try {
      const files = readdirSync(projectDir).filter(f => f.endsWith('.jsonl'))
      for (const f of files) {
        try {
          state.fileSizeCache.set(f, statSync(join(projectDir, f)).size)
        } catch {}
      }
    } catch {}

    // fs.watch for immediate detection
    try {
      state.watcher = watch(projectDir, { recursive: false }, (_, filename) => {
        if (!filename) return
        if (!filename.endsWith('.jsonl')) return
        const sessionId = filename.replace('.jsonl', '')
        emitChange(agent, sessionId, filename, projectDir, broadcast)
      })
      console.log(`[TranscriptDebug] Watching ${agent}: ${projectDir}`)
    } catch (e: any) {
      console.error(`[TranscriptDebug] Watch failed for ${agent}: ${e.message}`)
    }

    agentStates.set(agent, state)
    anyWatched = true
  }

  if (!anyWatched) {
    console.log('[TranscriptDebug] No agent project directories found, skipping watcher')
    return
  }

  // Shared polling fallback for all agents
  pollTimer = setInterval(() => {
    for (const [agent, state] of agentStates) {
      try {
        const files = readdirSync(state.projectDir).filter(f => f.endsWith('.jsonl'))
        for (const f of files) {
          try {
            const size = statSync(join(state.projectDir, f)).size
            const prevSize = state.fileSizeCache.get(f) || 0
            if (size !== prevSize) {
              state.fileSizeCache.set(f, size)
              const sessionId = f.replace('.jsonl', '')
              emitChange(agent, sessionId, f, state.projectDir, broadcast)
            }
          } catch {}
        }
        // Detect new files
        for (const f of files) {
          if (!state.fileSizeCache.has(f)) {
            state.fileSizeCache.set(f, 0)
          }
        }
      } catch {}
    }
  }, POLL_INTERVAL_MS)
}

export function cleanupTranscriptDebugWatcher() {
  for (const [, state] of agentStates) {
    if (state.watcher) {
      state.watcher.close()
    }
    if (state.debounceTimer) {
      clearTimeout(state.debounceTimer)
    }
  }
  agentStates.clear()

  if (pollTimer) {
    clearInterval(pollTimer)
    pollTimer = null
  }
}
