import { readFileSync, writeFileSync, existsSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import { randomBytes } from 'crypto';

const __dirname = dirname(fileURLToPath(import.meta.url));
const CONFIG_PATH = join(__dirname, 'config.json');

const DEFAULTS = {
  cli: 'claude',
  port: 4000,
  loopMinutes: 5,
  compactThreshold: 40,
  compactKeepRecent: 10,
  agentName: 'AI-Do',
  workspaceRoot: join(__dirname, 'workspace'),
  models: {},
  maxUserTaskConcurrency: 2,
  autonomyActiveChatPauseMs: 180000,
  desktopHotkey: 'CommandOrControl+Shift+A',
  dailyBudget: null,
  authToken: null,

  // v3.0 — Workspace management
  activeWorkspace: 'default',
  workspaces: {},

  // v3.0 — Ingestion engine
  ingestion: { enabled: true, maxConcurrent: 2 },

  // v3.0 — Cognitive reasoning modules
  cognitive: {
    plannerEnabled: true,
    reflectorEnabled: true,
    reflectorInterval: 6,
    thinkerDepth: 'balanced'
  },

  // v3.0 — Multimodal I/O
  multimodal: { sttEnabled: false, ttsEnabled: false, visionEnabled: false },

  // v3.0 — Knowledge graph
  kgEnabled: true,

  // v3.1 — Voice activation (openWakeWord + ONNX Runtime)
  voice: {
    enabled: false,
    wakeWordModel: 'hey_jarvis_v0.1',
    detectionThreshold: 0.5,
    modelsPath: null,
    nativeMode: true,
    browserMode: true,
    transcriptionProvider: 'whisper',
    autoInjectToChat: true,
    feedbackSound: true,
    listenHotkey: 'CommandOrControl+Shift+Space',
    ringBufferSeconds: 15
  },

  // v4.0 — Persona system
  persona: {
    name: 'AI-Do',
    greeting: 'Hello! I\'m AI-Do, your personal AI.',
    avatarStyle: 'default',
    traits: { creativity: 0.7, verbosity: 0.5, formality: 0.3, humor: 0.5 }
  },

  // v4.0 — Vector embedding cache (optional, degrades gracefully)
  vector: {
    enabled: true,
    embeddingModel: 'nomic-embed-text',
    embeddingEndpoint: 'http://localhost:11434/api/embeddings',
    dimensions: 768
  }
};

let _config = null;

// Keys that are nested objects requiring deep merge (not replacement)
const NESTED_KEYS = ['models', 'workspaces', 'ingestion', 'cognitive', 'multimodal', 'voice', 'persona', 'vector'];

function mergeConfig(userConfig) {
  const merged = { ...DEFAULTS, ...userConfig };
  for (const key of NESTED_KEYS) {
    if (typeof DEFAULTS[key] === 'object' && DEFAULTS[key] !== null) {
      merged[key] = { ...DEFAULTS[key], ...(userConfig[key] || {}) };
    }
  }
  return merged;
}

function tryRepairMalformedWorkspacePath(raw) {
  const repairedRaw = raw.replace(
    /("workspaceRoot"\s*:\s*")([^"]*)(")/,
    (_, prefix, value, suffix) => `${prefix}${value.replace(/\\/g, '\\\\')}${suffix}`
  );
  if (repairedRaw === raw) return null;
  try {
    const parsed = JSON.parse(repairedRaw);
    return { parsed, repairedRaw };
  } catch {
    return null;
  }
}

export function loadConfig() {
  if (existsSync(CONFIG_PATH)) {
    const raw = readFileSync(CONFIG_PATH, 'utf-8');
    try {
      const userConfig = JSON.parse(raw);
      _config = mergeConfig(userConfig);
    } catch (err) {
      const repaired = tryRepairMalformedWorkspacePath(raw);
      if (repaired) {
        _config = mergeConfig(repaired.parsed);
        try {
          writeFileSync(CONFIG_PATH, JSON.stringify(_config, null, 2) + '\n', 'utf-8');
          console.log('[config] Repaired malformed workspaceRoot path in config.json');
        } catch (writeErr) {
          console.error(`[config] Repaired config in memory but could not save: ${writeErr.message}`);
        }
      } else {
        console.error(`[config] Failed to parse config.json: ${err.message}. Using defaults.`);
        _config = { ...DEFAULTS };
      }
    }
  } else {
    _config = { ...DEFAULTS };
  }

  // Auto-generate auth token if not set
  if (!_config.authToken) {
    _config.authToken = randomBytes(24).toString('hex');
    try {
      writeFileSync(CONFIG_PATH, JSON.stringify(_config, null, 2) + '\n', 'utf-8');
      console.log(`[config] Generated auth token. Access UI at: http://localhost:${_config.port}?token=${_config.authToken}`);
    } catch (err) {
      console.error(`[config] Could not save generated auth token: ${err.message}`);
    }
  }

  return _config;
}

export function getConfig() {
  if (!_config) loadConfig();
  return _config;
}

export function updateConfig(updates) {
  const current = getConfig();
  const merged = { ...current, ...updates };
  for (const key of NESTED_KEYS) {
    if (updates[key] && typeof updates[key] === 'object') {
      merged[key] = { ...current[key], ...updates[key] };
    }
  }
  writeFileSync(CONFIG_PATH, JSON.stringify(merged, null, 2) + '\n', 'utf-8');
  _config = merged;
  return merged;
}

export function getDbPath() {
  return process.env.AGENT_DB_PATH || join(__dirname, 'agent.db');
}

export function getAgentRoot() {
  return __dirname;
}

export { DEFAULTS };
