import { appendFileSync, mkdirSync } from 'node:fs'
import path from 'node:path'
import { readPrefixedEnv, readPrefixedEnvFlag } from './env.js'

type RuntimeGlobals = typeof globalThis & {
  process?: Pick<NodeJS.Process, 'versions'>
}

function runtimeGlobals(): RuntimeGlobals {
  return globalThis as RuntimeGlobals
}

function isNodeLike(): boolean {
  const p = runtimeGlobals().process
  return Boolean(p && typeof p?.versions?.node === 'string')
}

function isDebugEnabled(): boolean {
  if (!isNodeLike())
    return false
  const v = readPrefixedEnvFlag(undefined, 'DEBUG')
  return v === '1' || v === 'true' || v === 'yes' || v === 'on'
}

// ---------------------------------------------------------------------------
// Directory helpers
// ---------------------------------------------------------------------------

const ensuredDirs = new Set<string>()

function ensureDir(dir: string): void {
  if (ensuredDirs.has(dir))
    return
  try {
    mkdirSync(dir, { recursive: true })
  }
  catch {
    // ignore
  }
  ensuredDirs.add(dir)
}

/**
 * All debug logs live under a single `logs/` directory.
 * When `DIMCODE_DEBUG_LOG` is set the parent of that path is used instead.
 */
function logsDir(): string {
  const raw = readPrefixedEnv(undefined, 'DEBUG_LOG')
  if (raw)
    return path.dirname(raw)
  return './logs'
}

// ---------------------------------------------------------------------------
// Formatting / writing
// ---------------------------------------------------------------------------

function formatLine(eventName: string, payload?: unknown): string {
  const name = String(eventName ?? '').trim() || 'event'
  const timestamp = new Date().toISOString()
  let line = `[${timestamp}] ${name}`
  if (payload !== undefined) {
    try {
      line += ` ${JSON.stringify(payload)}`
    }
    catch {
      // ignore
    }
  }
  return `${line}\n`
}

function writeLine(filePath: string, line: string): void {
  try {
    appendFileSync(filePath, line)
  }
  catch {
    // ignore
  }
}

// ---------------------------------------------------------------------------
// Global debug log
// ---------------------------------------------------------------------------

function debugLogPath(): string {
  const raw = readPrefixedEnv(undefined, 'DEBUG_LOG')
  if (raw)
    return raw
  const dir = logsDir()
  ensureDir(dir)
  return path.join(dir, 'dimcode-debug.log')
}

export function debugLog(eventName: string, payload?: unknown): void {
  if (!isDebugEnabled())
    return
  writeLine(debugLogPath(), formatLine(eventName, payload))
}

// ---------------------------------------------------------------------------
// Per-session debug log  (logs/<sessionId>.log)
// ---------------------------------------------------------------------------

/**
 * Write a debug line into a per-session log file.
 * The file is always **appended** — it is never cleared within a session.
 * Files live under `logsDir()/<sessionId>.log`.
 */
export function debugLogSession(
  sessionId: string,
  eventName: string,
  payload?: unknown,
): void {
  if (!isDebugEnabled())
    return
  const dir = logsDir()
  ensureDir(dir)
  const sanitized = sessionId.replace(/[^\w-]/g, '_')
  const filePath = path.join(dir, `${sanitized}.log`)
  writeLine(filePath, formatLine(eventName, payload))
}
