import { existsSync, readFileSync } from 'fs';
import { join } from 'path';

export interface CliConfig {
  prekeyServer: string;
  storage: string;
  observerToken?: string | undefined;
  observerUrl?: string | undefined;
  address?: string | undefined;
}

const DEFAULT_STORAGE = 'sqlite:./.shade/client.db';

/** Read config from .shaderc.json in cwd, then env vars as fallback */
export function loadConfig(cwd: string = process.cwd()): CliConfig {
  const configPath = join(cwd, '.shaderc.json');
  let fileConfig: Partial<CliConfig> = {};

  if (existsSync(configPath)) {
    try {
      fileConfig = JSON.parse(readFileSync(configPath, 'utf-8'));
    } catch (err) {
      throw new Error(`Failed to parse .shaderc.json: ${(err as Error).message}`);
    }
  }

  const prekeyServer = fileConfig.prekeyServer ?? process.env.SHADE_PREKEY_SERVER;
  if (!prekeyServer) {
    throw new Error(
      'Missing prekeyServer. Set it in .shaderc.json or via SHADE_PREKEY_SERVER env var.',
    );
  }

  return {
    prekeyServer,
    storage: fileConfig.storage ?? process.env.SHADE_DB_PATH ?? DEFAULT_STORAGE,
    observerToken: fileConfig.observerToken ?? process.env.SHADE_OBSERVER_TOKEN,
    observerUrl: fileConfig.observerUrl ?? process.env.SHADE_OBSERVER_URL,
    address: fileConfig.address ?? process.env.SHADE_ADDRESS,
  };
}

/** Check config is loadable without throwing; for `shade doctor`. */
export function tryLoadConfig(cwd: string = process.cwd()): { ok: true; config: CliConfig } | { ok: false; error: string } {
  try {
    return { ok: true, config: loadConfig(cwd) };
  } catch (err) {
    return { ok: false, error: (err as Error).message };
  }
}
