import * as fs from 'node:fs';
import * as path from 'node:path';
import * as yaml from 'js-yaml';

export interface ExternalAppConfig {
  server: { port: number };
  data: { dir: string };
  autoOpenBrowser: boolean;
  database: {
    type: 'mysql';
    host: string;
    port: number;
    username: string;
    password: string;
    database: string;
  };
}

export type LoadedExternalConfig = { source: 'file' | 'fallback' } & ExternalAppConfig;

declare global {
  var __NETA_EXTERNAL_CONFIG__: ExternalAppConfig | undefined;
}

function assertConfig(config: any): asserts config is ExternalAppConfig {
  if (!config?.data?.dir || typeof config.data.dir !== 'string')
    throw new Error('config.yaml 缺少 data.dir');
  if (!config?.server?.port || typeof config.server.port !== 'number')
    throw new Error('config.yaml 缺少 server.port');
  if (!config?.database?.host || !config?.database?.username || !config?.database?.database)
    throw new Error('config.yaml 缺少数据库配置');
}

export function loadExternalConfig(options?: {
  isPkg?: boolean;
  execPath?: string;
  cwd?: string;
}): LoadedExternalConfig {
  const isPkg = options?.isPkg ?? Boolean((process as any).pkg);

  if (!isPkg) {
    return {
      source: 'fallback',
      server: { port: 8003 },
      data: { dir: path.join(options?.cwd ?? process.cwd(), 'dist') },
      autoOpenBrowser: false,
      database: { type: 'mysql', host: '', port: 3306, username: '', password: '', database: '' },
    };
  }

  const execPath = options?.execPath ?? process.execPath;
  const configPath =
    process.env.NETA_CONFIG_PATH ?? path.join(path.dirname(execPath), 'config.yaml');

  let raw: string;
  try {
    raw = fs.readFileSync(configPath, 'utf8');
  } catch {
    throw new Error(
      `找不到配置文件: ${configPath}，请确认 config.yaml 与 backend.exe 在同一目录`
    );
  }

  const parsed = yaml.load(raw);
  assertConfig(parsed);
  return { source: 'file', ...parsed };
}
