const fs = require('fs');
const os = require('os');
const path = require('path');

const DEFAULT_CONNECTION = 'default';

function configDir() {
  return process.env.CIELARA_HOME
    ? path.resolve(process.env.CIELARA_HOME)
    : path.join(os.homedir(), '.cielara');
}

function configPath() {
  return process.env.CIELARA_CONNECTOR_CONFIG
    ? path.resolve(process.env.CIELARA_CONNECTOR_CONFIG)
    : path.join(configDir(), 'connector.json');
}

function packageRoot() {
  return path.resolve(__dirname, '..');
}

function readJSON(file, fallback) {
  try {
    return JSON.parse(fs.readFileSync(file, 'utf8'));
  } catch (error) {
    if (error && error.code === 'ENOENT') {
      return fallback;
    }
    throw error;
  }
}

function readConfig() {
  const file = configPath();
  const data = readJSON(file, null);
  if (!data) {
    return { version: 1, active: DEFAULT_CONNECTION, connections: {} };
  }
  if (!data.connections) {
    return {
      version: 1,
      active: DEFAULT_CONNECTION,
      connections: { [DEFAULT_CONNECTION]: data },
    };
  }
  return data;
}

function writeConfig(config) {
  const file = configPath();
  fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
  const tmp = `${file}.${process.pid}.tmp`;
  fs.writeFileSync(tmp, `${JSON.stringify(config, null, 2)}\n`, { mode: 0o600 });
  fs.renameSync(tmp, file);
  try {
    fs.chmodSync(file, 0o600);
  } catch (_) {
    // chmod is best-effort on Windows.
  }
}

function normalizeBaseUrl(raw) {
  const trimmed = String(raw || '').trim();
  if (!trimmed) {
    throw new Error('Cielara URL is required');
  }
  const url = new URL(trimmed);
  url.hash = '';
  url.search = '';
  return url.toString().replace(/\/$/, '');
}

function safeNormalizeBaseUrl(raw) {
  try {
    return normalizeBaseUrl(raw);
  } catch {
    return null;
  }
}

function getConfiguredPortalUrl(config = readConfig()) {
  return safeNormalizeBaseUrl(config.portalUrl);
}

function setConfiguredPortalUrl(raw) {
  const portalUrl = normalizeBaseUrl(raw);
  const config = readConfig();
  writeConfig({
    ...config,
    version: 1,
    portalUrl,
  });
  return portalUrl;
}

function clearConfiguredPortalUrl() {
  const config = readConfig();
  delete config.portalUrl;
  writeConfig({
    ...config,
    version: 1,
  });
}

function defaultMemoryApiUrl(baseUrl) {
  return `${baseUrl.replace(/\/$/, '')}/api/agent-memory`;
}

/** Insights backend reverse proxy to Agent Fabric (same path in dev and prod when the proxy is enabled). */
function defaultWorldModelApiUrl(baseUrl) {
  return `${baseUrl.replace(/\/$/, '')}/api/world-model`;
}

function upsertConnection(config, name, connection) {
  const key = name || DEFAULT_CONNECTION;
  const next = {
    ...config,
    version: 1,
    active: key,
    connections: {
      ...(config.connections || {}),
      [key]: {
        ...(config.connections || {})[key],
        ...connection,
      },
    },
  };
  return next;
}

function activeConnection(config = readConfig()) {
  const active = config.active || DEFAULT_CONNECTION;
  const connection = (config.connections || {})[active];
  if (!connection) {
    throw new Error('No Cielara connection found. Run `cielara login` first.');
  }
  return { name: active, connection };
}

/**
 * Whether to capture the search query (the grep pattern an agent ran) on
 * telemetry events. Opt-OUT: defaults to true; the user can disable it.
 * Precedence: env override > connection setting > default(true).
 * NOTE: this is the search pattern, NOT the natural-language LLM prompt —
 * the connector never sees the latter.
 */
function captureQueryEnabled() {
  if (process.env.CIELARA_TELEMETRY_NO_QUERY === '1') return false;
  if (process.env.CIELARA_TELEMETRY_CAPTURE_QUERY === '0') return false;
  try {
    const { connection } = activeConnection(readConfig());
    const t = connection.telemetry || {};
    if (t.capture_query === false) return false;
  } catch (_) {
    // no connection yet — fall through to default
  }
  return true;
}

/** Persist the prompt/query-capture preference on the active connection. */
function setCaptureQuery(enabled) {
  const config = readConfig();
  const { name, connection } = activeConnection(config);
  const next = upsertConnection(config, name, {
    telemetry: { ...(connection.telemetry || {}), capture_query: Boolean(enabled) },
  });
  writeConfig(next);
}

module.exports = {
  DEFAULT_CONNECTION,
  activeConnection,
  captureQueryEnabled,
  clearConfiguredPortalUrl,
  setCaptureQuery,
  getConfiguredPortalUrl,
  setConfiguredPortalUrl,
  configDir,
  configPath,
  defaultMemoryApiUrl,
  defaultWorldModelApiUrl,
  normalizeBaseUrl,
  packageRoot,
  readConfig,
  upsertConnection,
  writeConfig,
};
