import { AsyncIOResult } from 'happy-rusty';

/**
 * 日志系统核心类型定义。
 */
/**
 * 日志级别，从低到高排列。
 *
 * @since 2.6.0
 */
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
/**
 * 单条日志记录。
 *
 * @since 2.6.0
 */
interface LogEntry {
    /**
     * 日志时间戳（毫秒，epoch millis）。
     *
     * 使用 `number` 而非 `Date` 以减少 GC 开销，并保证 JSON 序列化无歧义。
     */
    timestamp: number;
    /**
     * 日志级别。
     */
    level: LogLevel;
    /**
     * 已格式化的日志消息。
     */
    message: string;
}
/**
 * 日志过滤函数。
 *
 * @since 2.6.0
 */
type LogFilter = (level: LogLevel, ...args: unknown[]) => boolean;
/**
 * 日志格式化函数。
 *
 * @since 2.6.0
 */
type LogFormatter = (entry: LogEntry) => string;
/**
 * Plugin 初始化上下文。
 *
 * @since 2.6.0
 */
interface PluginContext {
    /**
     * 全局最低日志级别（来自 `LoggerConfig.level`）。
     */
    globalLevel: LogLevel;
    /**
     * 全局日志过滤函数。
     *
     * 可能为 `undefined`（未设置全局 filter）。
     */
    filter?: LogFilter;
}
/**
 * 日志插件接口。
 *
 * @since 2.6.0
 */
interface LoggerPlugin {
    /**
     * 插件名称，用于标识和调试。
     */
    readonly name: string;
    /**
     * 插件初始化回调。
     *
     * logger 核心在 `init` 时调用，传入全局上下文，插件可据此继承全局配置。
     */
    onInit?: (ctx: PluginContext) => void;
    /**
     * 日志分发回调。
     *
     * logger 核心在每条日志通过级别与 filter 后调用，接收原始参数
     *（`level, ...args`），由插件自行决定格式化与落盘策略。
     */
    onLog?: (level: LogLevel, ...args: unknown[]) => void;
    /**
     * 插件销毁回调。
     *
     * 由 logger 核心在 `init` 重新初始化时对旧插件调用，用于清理资源
     *（如 `clearInterval`、移除事件监听等）。
     */
    onDestroy?: () => void;
}
/**
 * 控制台输出配置。
 *
 * @since 2.6.0
 */
interface ConsolePluginConfig {
    /**
     * 是否启用控制台输出。
     *
     * @defaultValue `true`
     */
    enabled?: boolean;
    /**
     * 控制台最低输出级别。
     *
     * @defaultValue 继承 `LoggerConfig.level`
     */
    level?: LogLevel;
}
/**
 * 日志系统配置。
 *
 * @since 2.6.0
 */
interface LoggerConfig {
    /**
     * 全局最低日志级别。
     *
     * @defaultValue `'info'`
     */
    level?: LogLevel;
    /**
     * 全局日志过滤函数。
     */
    filter?: LogFilter;
    /**
     * 控制台输出配置。
     */
    console?: ConsolePluginConfig;
    /**
     * 插件列表。
     *
     * @defaultValue `[]`
     */
    plugins?: LoggerPlugin[];
    /**
     * 是否拦截全局 `console` 方法并重定向到 logger。
     *
     * 设为 `true` 后，`console.debug`/`info`/`warn`/`error`/`log` 会经过
     * logger 的 `dispatchLog`，触发插件 pipeline。
     *
     * **注意**：此方式不提供 restore 功能。如需恢复原始 `console`，
     * 请使用独立的 {@link injectConsole} 函数（返回 restore 函数）。
     *
     * @defaultValue `false`
     */
    injectConsole?: boolean;
}

/**
 * 日志系统核心逻辑：单例状态管理、日志流水线、插件调度。
 */

/**
 * 初始化日志系统。
 *
 * @param config - 日志系统配置。
 * @since 2.6.0
 * @example
 * ```ts
 * const file = fileLog({ level: 'debug' });
 * logger.init({ plugins: [file, wxLog({ level: 'warn' })] });
 * ```
 */
declare function init(config?: LoggerConfig): void;
/**
 * 输出 debug 级别日志。
 * @since 2.6.0
 */
declare function debug(...args: unknown[]): void;
/**
 * 输出 info 级别日志。
 * @since 2.6.0
 */
declare function info(...args: unknown[]): void;
/**
 * 输出 warn 级别日志。
 * @since 2.6.0
 */
declare function warn(...args: unknown[]): void;
/**
 * 输出 error 级别日志。
 * @since 2.6.0
 */
declare function error(...args: unknown[]): void;
/**
 * 拦截全局 `console` 方法，将其重定向到 logger。
 *
 * 调用后，`console.debug`/`info`/`warn`/`error`（以及 `console.log`）会经过
 * logger 的 `dispatchLog`，触发插件 pipeline（如 `fileLog`）。
 *
 * logger 自身的 console 输出使用模块加载时捕获的原始方法（`CONSOLE_FN`），
 * 不会递归。
 *
 * @returns restore 函数，调用后恢复原始 `console` 方法。
 * @since 2.6.0
 * @example
 * ```ts
 * logger.init({ plugins: [fileLog()] });
 * const restore = injectConsole();
 * // 之后所有 console.info(...) 会走 logger pipeline
 * console.info('App started'); // → file 写入 + console 输出
 * restore(); // 需要时恢复
 * ```
 */
declare function injectConsole(): () => void;

/**
 * Plugin 相关类型定义。
 */

/**
 * Plugin 可覆盖的基础配置，所有 plugin 配置应继承此接口。
 *
 * @since 2.6.0
 */
interface PluginConfigBase {
    /**
     * 最低日志级别。
     *
     * @defaultValue 继承全局 `LoggerConfig.level`
     */
    level?: LogLevel;
    /**
     * 日志过滤函数。
     *
     * - `undefined`：继承全局 `LoggerConfig.filter`
     * - `null`：显式禁用过滤
     * - 函数：使用自定义过滤逻辑
     */
    filter?: LogFilter | null;
}

/**
 * 文件日志插件：fileLog 工厂，提供缓冲写入、日志分割（period + size）、旧文件清理。
 */

/**
 * 日志分割（split）配置。
 *
 * @since 2.6.0
 */
interface FileSplitConfig {
    /**
     * 日志文件分割的时间粒度（毫秒）。
     *
     * 同一 period 内的日志写入同一个文件，到期自动切换。
     *
     * @defaultValue `3600000`（1 小时）
     */
    period?: number;
    /**
     * 单个日志文件最大大小（字节）。
     *
     * @defaultValue `10 * 1024 * 1024`（10MB）
     */
    maxSize?: number;
    /**
     * 最多保留的日志文件数。
     *
     * @defaultValue `24`（period 为 1 小时时即一天的日志量）
     */
    maxCount?: number;
    /**
     * 文件最大保留时间（毫秒），创建时间超过此值的文件将被删除。
     *
     * 与 `maxCount` 叠加：先按时间过期删除，剩余文件若仍超 `maxCount` 再按数量删最旧的。
     *
     * @defaultValue `undefined`（不按时间清理）
     */
    maxAge?: number;
    /**
     * 是否使用 UTF-8 字节数计算文件大小（`true`）而非字符数（`false`）。
     *
     * @defaultValue `false`
     */
    useByteSize?: boolean;
    /**
     * 是否在切分时压缩旧日志文件（`.log` → `.log.gz`）。
     *
     * 压缩后原始 `.log` 被删除，压缩是 fire-and-forget，不阻塞日志写入。
     * 注意：压缩后文件变为 `.log.gz`，读取/合并时需先解压。
     * `maxCount` 为 1 时压缩产物 `.log.gz` 会临时占用额外名额，建议 `maxCount >= 2`。
     *
     * @defaultValue `false`
     */
    compress?: boolean;
}
/**
 * 文件插件配置。
 *
 * @since 2.6.0
 */
interface FilePluginConfig extends PluginConfigBase {
    /**
     * 日志格式化器。
     *
     * @defaultValue `defaultFormatter`（`[时间] [级别] 消息\n`）
     */
    formatter?: LogFormatter;
    /**
     * 日志文件根目录。
     *
     * @defaultValue `'/.minigame-std-logs'`
     */
    rootDir?: string;
    /**
     * 日志分割配置。
     */
    split?: FileSplitConfig;
    /**
     * 缓冲区最大条目数，达到后触发 flush。
     *
     * @defaultValue `100`
     */
    maxBufferSize?: number;
    /**
     * 定时 flush 间隔（毫秒），`0` 表示仅靠缓冲区阈值触发。
     *
     * @defaultValue `5000`
     */
    flushInterval?: number;
}
/**
 * 日志文件查询条件。
 *
 * @since 2.6.0
 */
interface LogFileQuery {
    /**
     * 起始时间戳（毫秒，含）。按文件创建时间（文件名时间戳）筛选。
     */
    from?: number;
    /**
     * 结束时间戳（毫秒，含）。按文件创建时间（文件名时间戳）筛选。
     */
    to?: number;
}
/**
 * 文件插件 API 接口。
 *
 * @since 2.6.0
 */
interface FilePluginAPI extends LoggerPlugin {
    /**
     * 立即将缓冲区内容写入文件，并等待所有在途写入完成。
     *
     * 写入失败不会 reject，也不会返回错误（错误由内部统一处理）。
     */
    flush(): Promise<void>;
    /**
     * 获取日志文件列表，可按文件创建时间筛选。
     *
     * 返回完整路径（`rootDir/文件名.log`），结果按文件名排序。
     * 文件名无法解析时间戳的文件不受 `query` 过滤，始终包含在结果中。
     */
    getFiles(query?: LogFileQuery): AsyncIOResult<string[]>;
    /**
     * 获取日志文件根目录。
     */
    getRootDir(): string;
}
/**
 * 创建文件日志插件。
 *
 * 插件在创建时即完成初始化（恢复/创建活跃文件、启动定时 flush、注册切后台监听），
 * 因此即使不传给 `logger.init()` 也能独立工作。传给 `logger.init()` 后，
 * `onInit` 会用全局配置（`level`/`filter`）refinement 自身配置。
 *
 * **注意**：`onInit`/`onLog` 由 logger 核心调度，不应手动调用。
 *
 * @param config - 文件插件配置。
 * @returns 支持 LoggerPlugin 和文件管理 API 的插件实例。
 * @since 2.6.0
 * @example
 * ```ts
 * const file = fileLog({ level: 'debug' });
 * logger.init({ plugins: [file] });
 * await file.flush();
 * ```
 */
declare function fileLog(config?: FilePluginConfig): FilePluginAPI;

/**
 * wx.getLogManager 插件：声明式创建 wxLog。
 */

/**
 * wx.getLogManager 插件配置（仅小游戏生效）。
 *
 * @since 2.6.0
 */
interface WxLogPluginConfig extends PluginConfigBase {
    /**
     * 透传给 `wx.getLogManager` 的参数。
     *
     * {@link WechatMinigame.GetLogManagerOption.level}
     *
     * @defaultValue `0`
     */
    rawLevel?: 0 | 1;
}
/**
 * 创建 wx.getLogManager 插件（仅小游戏生效）。
 *
 * @param config - 插件配置。
 * @returns LoggerPlugin 实例。
 * @since 2.6.0
 * @example
 * ```ts
 * logger.init({ plugins: [wxLog({ level: 'warn' })] });
 * ```
 */
declare function wxLog(config?: WxLogPluginConfig): LoggerPlugin;

export { debug, error, fileLog, info, init, injectConsole, warn, wxLog };
export type { ConsolePluginConfig, FilePluginAPI, FilePluginConfig, FileSplitConfig, LogEntry, LogFileQuery, LogFilter, LogFormatter, LogLevel, LoggerConfig, LoggerPlugin, PluginConfigBase, PluginContext, WxLogPluginConfig };
