// ============================================================
// config.ts — 中心化配置模块（YAML 驱动）
// ============================================================
// 职责：
//   1. 从项目根目录 env.yaml 加载配置
//   2. 使用 validateConfig() 校验并类型收窄
//   3. 导出按职责分组的强类型配置对象（pgsql / redis / logging）
//
// 使用方式：
//   import { pgsql, redis, logging } from "./config";
//   const ds = new DataSource({ ...pgsql });
//   const redisClient = new Redis(redis.url);
//
// 配置文件位置：data/env.yaml（软链接 → 项目根目录 env.yaml）
// TypeScript / Python 模块共享同一份配置。
// ============================================================

import { readFileSync } from "node:fs";
import { resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { parse as parseYaml } from "yaml";
import { validateConfig, type EnvConfig } from "./validators";

// ============================================================
// 1. 定位并读取 env.yaml
// ============================================================

/**
 * 计算项目根目录的绝对路径。
 * data/config.ts → data/ → <project_root>/
 *
 * 兼容 ESM（无 __dirname）和 Bun 运行时。
 */
function getProjectRoot(): string {
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = dirname(__filename);
    // config/index.ts → config/ → data/ → <project_root>
    return resolve(__dirname, "../..");
}

/**
 * 读取 data/env.yaml（软链接指向项目根目录 env.yaml）并解析为原始对象。
 * 文件不存在时抛出明确错误，不做静默降级。
 */
function loadYamlConfig(): unknown {
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = dirname(__filename);
    // config/index.ts → config/ → data/env.yaml
    const yamlPath = resolve(__dirname, "../env.yaml");

    let content: string;
    try {
        content = readFileSync(yamlPath, "utf-8");
    } catch {
        throw new Error(
            `[config] 无法读取配置文件: ${yamlPath}\n` +
            `请确保 data/env.yaml 软链接指向项目根目录的 env.yaml。`,
        );
    }

    const parsed = parseYaml(content);
    if (parsed === null || parsed === undefined) {
        throw new Error(`[config] env.yaml 解析结果为空: ${yamlPath}`);
    }

    return parsed;
}

// ============================================================
// 2. 加载 & 校验
// ============================================================

/** 经校验后的 env.yaml 配置（强类型） */
const rawConfig: EnvConfig = (() => {
    const raw = loadYamlConfig();
    return validateConfig(raw);
})();

// ============================================================
// 3. 按职责分组的导出配置对象
// ============================================================

/**
 * PostgreSQL / TimescaleDB 连接配置
 *
 * 连接池参数（max / idleTimeoutMillis / connectionTimeoutMillis）
 * 为硬编码常量，不在 env.yaml 中暴露，避免误调导致连接耗尽。
 */
export const pgsql = {
    host: rawConfig.db.host,
    port: rawConfig.db.port,
    database: rawConfig.db.name,
    user: rawConfig.db.user,
    password: rawConfig.db.password,
    /** pg.Pool 连接上限，避免连接数暴涨 */
    max: 20,
    /** 连接空闲超时（毫秒） */
    idleTimeoutMillis: 30000,
    /** 连接获取超时（毫秒） */
    connectionTimeoutMillis: 5000,
} as const;

/**
 * Redis 连接与发布配置
 *
 * channelPrefix / retryDelayBaseMs / maxRetries 为硬编码常量，
 * 跨模块保持一致，不需要通过配置文件修改。
 */
export const redis = {
    /** Redis 连接 URL（ioredis 可直接使用） */
    url: rawConfig.redis.url,
    /** 是否启用 Pub/Sub 发布行情数据（开发环境可关闭以节省资源） */
    publishEnabled: rawConfig.redis.publish_enabled,
    /** 频道前缀，避免多环境 key 冲突 */
    channelPrefix: "trade",
    /** 重连策略：指数退避基数（毫秒） */
    retryDelayBaseMs: 1000,
    /** 最大重试次数 */
    maxRetries: 10,
} as const;

/**
 * 日志配置
 *
 * pretty 由 NODE_ENV 自动推导，不在 env.yaml 中独立配置。
 */
export const logging = {
    /** 日志级别：trace / debug / info / warn / error / fatal */
    level: rawConfig.logging.level,
    /** 运行环境（production 时 pino 输出 JSON 便于日志采集） */
    nodeEnv: rawConfig.logging.node_env,
    /** 是否启用 pino-pretty（开发环境友好输出） */
    pretty: rawConfig.logging.node_env === "development",
} as const;

/**
 * 交易所 API 密钥配置
 *
 * 按交易所 ID 索引，目前仅 binance。
 * 新增交易所时在 env.yaml 的 exchange 段添加对应子配置即可。
 */
export const exchange = {
    binance: {
        apiKey: rawConfig.exchange.binance.api_key,
        apiSecret: rawConfig.exchange.binance.api_secret,
    },
    /** USDT-M 永续合约 API Key */
    binanceFutures: {
        apiKey: rawConfig.exchange.binance_futures.api_key,
        apiSecret: rawConfig.exchange.binance_futures.api_secret,
    },
} as const;

// ============================================================
// 4. 工具：运行时打印配置概要（不含敏感信息）
// ============================================================

/** 打印脱敏后的配置概要，便于启动排查 */
export function printConfigSummary(): void {
    const summary = {
        projectRoot: getProjectRoot(),
        pgsql: {
            host: pgsql.host,
            port: pgsql.port,
            database: pgsql.database,
            user: pgsql.user,
            password: "***",
        },
        redis: {
            url: redis.url.replace(/\/\/.*@/, "//***@"), // 隐藏密码
            publishEnabled: redis.publishEnabled,
        },
        exchange: {
            binance: {
                apiKey: exchange.binance.apiKey.slice(0, 6) + "***",
                apiSecret: "***",
            },
            binanceFutures: {
                apiKey: exchange.binanceFutures.apiKey.slice(0, 6) + "***",
                apiSecret: "***",
            },
        },
        logging: {
            level: logging.level,
            nodeEnv: logging.nodeEnv,
            pretty: logging.pretty,
        },
    };
    console.log("[config] 配置概要:", JSON.stringify(summary, null, 2));
}
