
import botlogger from "./logger.js";
import { promises as fsPromises } from 'fs';
import { HtmlImg } from "./Puppeteer.js";
import type {
    GroupMessage,
    PrivateFriendMessage,
    PrivateGroupMessage
} from 'node-napcat-ts/dist/Interfaces.js';
import * as cron from 'node-cron';
import 'reflect-metadata';
import { Command, ParamMetadata, Plugin, } from '../interface/plugin.js';
import * as fs from 'fs'
import * as path from 'path'
// 获取指令前缀
import { Botconfig as config, economy, load, PermissionConfig, saveConfig } from './config.js'
import { FileSegment, ImageSegment, Receive, ReplySegment, TextSegment } from "node-napcat-ts/dist/Structs.js";
import { fileURLToPath } from 'node:url';
import { qqBot } from "../app.js";
import { IsPermission } from "./Permission.js";
import { download } from "./download.js";
import { commandList, economyCommands, paramMetadata } from "./decorators.js";
import { addCoins, removeCoins } from "./economy.js";
import { url } from "node:inspector";

//WSSendParam
const CMD_PREFIX = config?.cmd?.prefix ?? '#';
// 导出装饰器
// export { param, ParamType };
// export const plugins = pluginsDecorator;
export { config };  // 导出配置对象
// 创建消息工厂函数
function createTextMessage(text: string): TextSegment {
    return {
        type: "text",
        data: {
            text: text,
        }
    };
}

function createImageMessage(base64Data: string): ImageSegment {
    //动画表情
    if(base64Data.startsWith('data:image/gif;base64,')){
        return {
            type: "image",
            data: {
                file: `base64://${base64Data}`,
            }
        };
    }
    return {
        type: "image",
        data: {
            file: `base64://${base64Data}`,
        }
    };
}

function createReplyMessage(messageId: number | string): ReplySegment {
    return {
        type: "reply",
        data: {
            id: String(messageId)
        }
    };
}

// 修改插件查找函数
function findPlugin(pluginId: string): Plugin | undefined {
    return commandList.find((p: Plugin) => p.id === pluginId);
}
function findeasycmdPlugin(commandId: string): Plugin | undefined {
    return commandList.find((p: Plugin) => p.config.easycmd === true && p.commands.find((c: Command) => c.cmd === commandId || c.aliases?.includes(commandId)));
}
// 修改命令查找函数
function findCommand(plugin: Plugin, cmdName: string): Command | undefined {
    return plugin.commands.find((cmd: Command) => {
        // 从完整命令中提取命令名
        const cmdParts = cmd.cmd.split(/\s+/);
        const matchCmd = cmdParts[cmdParts.length - 1] === cmdName;

        // 检查别名
        const matchAlias = cmd.aliases?.some((alias: string) => {
            const aliasParts = alias.split(/\s+/);
            return aliasParts[aliasParts.length - 1] === cmdName;
        });

        return matchCmd || matchAlias;
    });
}

// 添加插件加载函数
async function loadPlugins(): Promise<void> {
    try {
        const __dirname = path.dirname(fileURLToPath(import.meta.url));

        const pluginsDir = path.join(__dirname, '..', 'plugins');

        // 删除require缓存相关代码
        const files = await fsPromises.readdir(pluginsDir);

        for (const file of files) {
            if (file.endsWith('.ts') && file !== 'index.ts') {
                const filePath = path.join(pluginsDir, file);
                try {
                    // 使用ESM动态导入并添加时间戳防止缓存
                    const module = await import(`${filePath}?t=${Date.now()}`);
                    const pluginClasses = Object.values(module).filter(
                        value => typeof value === 'function' && value.prototype?.plugincfg
                    );

                    for (const PluginClass of pluginClasses) {
                        const instance = new (PluginClass as any)();
                        const pluginConfig = instance.constructor.prototype.plugincfg;

                        if (pluginConfig) {
                            const plugin: Plugin = {
                                id: pluginConfig.id,
                                name: pluginConfig.name,
                                commands: [] as Command[],
                                class: instance.constructor,
                                version: pluginConfig.version,
                                author: pluginConfig.author,
                                describe: pluginConfig.describe,
                                config: pluginConfig
                            };
                            // 触发装饰器
                            await initializePluginCommands(instance);

                            // 初始化定时任务
                            await initializeScheduledTasks(instance);
                        }
                    }
                } catch (error: any) {
                    botlogger.error(`加载插件文件失败 ${file}:`+ error.message);
                }
            }
        }
    } catch (error) {
        botlogger.error("加载插件目录失败:", error);
    }
}


// 初始化插件命令
async function initializePluginCommands(instance: any): Promise<void> {
    const methods = Object.getOwnPropertyNames(instance.constructor.prototype)
        .filter(name => name !== 'constructor');

    for (const methodName of methods) {
        const method = instance.constructor.prototype[methodName];
        try {
            if (typeof method === 'function') {
                method.call(instance, '', '');
            }
        } catch (error) {
            if (error instanceof TypeError && error.message.includes('Cannot read properties of undefined')) {
                continue;
            }
            botlogger.error(`触发装饰器时出错: ${error instanceof Error ? error.message : '未知错误'}`);
        }
    }
}

// 初始化定时任务
async function initializeScheduledTasks(instance: any): Promise<void> {
    const methods = Object.getOwnPropertyNames(instance.constructor.prototype)
        .filter(name => name !== 'constructor');

    for (const methodName of methods) {
        const method = instance.constructor.prototype[methodName];
        if (method.isScheduled) {
            try {
                // 创建定时任务
                cron.schedule(method.cron, async () => {
                    try {
                        await method.call(instance);
                    } catch (error) {
                        botlogger.error(`执行定时任务失败 [${methodName}]:`, error);
                    }
                });
                botlogger.info(`注册定时任务 [${methodName}]: ${method.cron}`);
            } catch (error) {
                botlogger.error(`注册定时任务失败 [${methodName}]:`, error);
            }
        }
    }
}

// 修改 runplugins 函数
export async function runplugins() {
    try {
        // 清理旧实例
        commandList.forEach(plugin => {
            plugin.commands.forEach(cmd => {
                // 检查 cmd.fn 是否存在，并且是否有 close 方法
                if (cmd.fn && typeof (cmd.fn as any).close === 'function') {
                    (cmd.fn as any).close();
                }
            });
        });

        // 清空现有命令列表
        commandList.length = 0;
        // 注册插件
        botlogger.info("开始注册插件...");
        // 自动加载插件
        await loadPlugins();
        // 设置消息处理器
        qqBot.on('message', async (context) => {
            try {
                if(context.message[0].type === "reply" && context.message[1].type === "text"){
                    //交换
                    const temp = context.message[0];
                    context.message[0] = context.message[1];
                    context.message[1] = temp;
                }
                if (context.message[0].type !== 'text') {
                    return;
                }
                const msg = context.message[0].data.text || '';

                if (msg == CMD_PREFIX) {
                    context.quick_action([{
                        type: 'text',
                        data: {
                            text: "可用的命令有：\n" +
                                commandList.map(p => `${CMD_PREFIX}${p.id}: ${p.name}`).join('\n') +
                                "\n\n" +
                                `使用 “${CMD_PREFIX}插件名 help” 或 “${CMD_PREFIX}插件名 ?” 查询命令的详情 ^_^`
                        }
                    }]);
                    return;
                }

                botlogger.info('收到消息:' + context.message[0].data.text);
                // 检查是否是命令
                if (!msg.startsWith(CMD_PREFIX)) {
                    return;
                }

                // 解析命令
                const parts = msg.slice(CMD_PREFIX.length).trim().split(/\s+/);
                const pluginId = parts[0];
                const cmdName = parts[1];
                const args = parts.slice(2);

                botlogger.info('尝试匹配插件:', pluginId);

                // 显示可用插件
                botlogger.info('可用插件:');
                commandList.forEach(p => {
                    botlogger.info(`  [${p.id}]: ${p.name}`);
                });

                // 查找插件
                const plugin = findPlugin(pluginId);
                if (!plugin) {
                    botlogger.info(`插件未找到: ${pluginId}`);
                    //尝试easycmd开启的插件
                    const easyplugin = findeasycmdPlugin(pluginId)
                    if (!easyplugin) {
                        botlogger.info(`插件未找到: ${pluginId}`);
                        return;
                    }
                    let command: Command | undefined = undefined;
                    command = findCommand(easyplugin, pluginId);
                    if (!command) {
                        botlogger.info(`命令未找到: ${pluginId}`);
                        return;
                    }
                    //指令权限检查
                    if (context.message_type === 'private') {
                        if (!await IsPermission(context.user_id, easyplugin.id, command.fnName, false)) {
                            botlogger.info(`[${context.user_id}]无权限执行命令: ${CMD_PREFIX}${easyplugin.id} ${command.cmd}`);
                            context.quick_action([{
                                type: 'text',
                                data: { text: `你没有权限执行此命令` }
                            }]);
                            return;
                        }
                    }
                    if (context.message_type === 'group') {
                        if (!await IsPermission(context.sender.user_id, easyplugin.id, command.fnName,true)) {
                            botlogger.info(`[${context.group_id}]无权限执行命令: ${CMD_PREFIX}${easyplugin.id} ${command.cmd}`);
                            context.quick_action([{
                                type: 'text',
                                data: { text: `你没有权限执行此命令` }
                            }])
                            return;
                        }
                    }
                    // 响应回应
                    qqBot.set_msg_emoji_like({
                        message_id: context.message_id,
                        set: true,
                        emoji_id: '124'
                    })
                    await handleCommand(context, easyplugin, command, parts.slice(1), true);
                    return;
                }
                botlogger.info(`找到插件[${plugin.id}]: ${plugin.name}`);

                // 显示可用命令
                botlogger.info('可用命令:');
                plugin.commands.forEach(cmd => {
                    botlogger.info(`${CMD_PREFIX}${plugin.id} ${cmd.cmd}`);
                });

                let command: Command | undefined = undefined;
                if (cmdName == undefined) {
                    botlogger.info(`未检测到第二个参数，运行默认命令: ${plugin.config.defaultCommandId}`);

                    const commandId = plugin.config.defaultCommandId ?? "help";

                    command = findCommand(plugin, commandId);
                } else {
                    command = findCommand(plugin, cmdName);
                }

                if (!command) {
                    botlogger.info(`命令未找到: ${cmdName}`);
                    return;
                }

                botlogger.info(`找到命令: ${CMD_PREFIX}${plugin.id} ${command.cmd}`);
                //指令权限检查
                if (context.message_type === 'private') {
                    if (!await IsPermission(context.user_id, plugin.id, command.fnName,false)) {
                        botlogger.info(`[${context.user_id}]无权限执行命令: ${CMD_PREFIX}${plugin.id} ${command.cmd}`);
                        context.quick_action([{
                            type: 'text',
                            data: { text: `你没有权限执行此命令` }
                        }]);
                        return;
                    }
                }
                if (context.message_type === 'group') {
                    if (!await IsPermission(context.sender.user_id, plugin.id, command.fnName, true)) {
                        botlogger.info(`[${context.group_id}]无权限执行命令: ${CMD_PREFIX}${plugin.id} ${command.cmd}`);
                        context.quick_action([{
                            type: 'text',
                            data: { text: `你没有权限执行此命令` }
                        }])
                        return;
                    }
                }
                // 执行命令
                qqBot.set_msg_emoji_like({
                    message_id: context.message_id,
                    set: true,
                    emoji_id: '124'
                })
                await handleCommand(context, plugin, command, args);

            } catch (error) {
                botlogger.error("处理消息时出错:", error);
                await context.quick_action([{
                    type: 'text',
                    data: { text: `处理消息时出错: ${error instanceof Error ? error.message : '未知错误'}` }
                }]);
            }
        });

        botlogger.info("插件注册完成");
        botlogger.info("命令表:");
        for (const plugin of commandList) {
            botlogger.info(`[${plugin.id}]:`);
            for (const cmd of plugin.commands) {
                botlogger.info(`  ${CMD_PREFIX}${plugin.id} ${cmd.cmd}`);
            }
        }

    } catch (error) {
        botlogger.error("注册插件时出错:", error);
    }
}

// 修改 handleCommand 函数
async function handleCommand(context: PrivateFriendMessage | PrivateGroupMessage | GroupMessage, plugin: Plugin, command: Command, args: string[],easycmd:boolean=false): Promise<void> {
    try {
        // 解析参数 - 传入完整消息文本
        if (!context.message[0].type || context.message[0].type !== 'text') {
            throw new Error('消息内容为空');
        }
        const message = context.message[0].data.text || '';
        const parsedArgs = await parseCommandParams(message, context, command,easycmd);

        botlogger.info('命令参数解析完成:' + JSON.stringify({
            command: command.cmd,
            args: parsedArgs.slice(0, -1) // 不显示 context 对象
        }));
        await cost(context, command);
        // 执行命令
        const pluginInstance = new (command.class)();
        const result = await command.fn.apply(pluginInstance, parsedArgs);

        // 检查是否是群消息
        const isGroupMessage = context.message_type === 'group';
        const baseMessage = isGroupMessage && context.message_id
            ? [createReplyMessage(context.message_id)]
            : [];

        // 检查是否有模板配置
        if (result?.template?.enabled) {
            try {
                let templateIsPath: boolean = true;
                const templateHtml = result.template.html;
                const templatePath = result.template.path;
                const url= result.template.render.url;
                const isgif = result.template.render?.isgif || false;
                
                if (templateHtml) {
                    templateIsPath = false;
                } else if (url) {
                    templateIsPath = false;
                }else if (!templatePath || !fs.existsSync(templatePath)) {
                    throw new Error(`Template not found: ${templatePath}`);
                }

                // 生成图片
                const htmlImg = new HtmlImg();
                try {
                    const img = await htmlImg.render({
                        template: templateIsPath ? templatePath : templateHtml,
                        templateIsPath,
                        data: result,
                        url: url,
                        isgif: isgif,
                        width: result.template.render?.width || 800,
                        height: result.template.render?.height || 600,
                        type: result.template.render?.type || 'png',
                        quality: result.template.render?.quality || 100,
                        fullPage: result.template.render?.fullPage || false,
                        background: result.template.render?.background || true
                    });

                    // 发送图片
                    const base64Data = Buffer.from(img).toString('base64');
                    const imageMessage = createImageMessage(base64Data);
                    const message = [...baseMessage, imageMessage];

                    if (isGroupMessage && context.group_id) {
                        await qqBot.send_group_msg({
                            group_id: Number(context.group_id),
                            message: message as any[]
                        });
                    } else {
                        await qqBot.send_private_msg({
                            user_id: Number(context.user_id),
                            message: message as any[]
                        });
                    }

                    // 如果配置了同时发送文字
                    if (result.template.sendText) {
                        const text = result?.toString?.() || String(result);
                        const textMessage = createTextMessage(text);
                        const textOnlyMessage = [...baseMessage, textMessage];

                        if (isGroupMessage && context.group_id) {
                            await qqBot.send_group_msg({
                                group_id: Number(context.group_id),
                                message: textOnlyMessage as any[]
                            });
                        } else {
                            await qqBot.send_private_msg({
                                user_id: Number(context.user_id),
                                message: textOnlyMessage as any[]
                            });
                        }
                    }
                } finally {
                    await htmlImg.close();
                }
            } catch (error) {
                botlogger.error('图片生成失败:', error);
                // 如果图片生成失败，发送文本
                const text = result?.toString?.() || String(result);
                const textMessage = createTextMessage(text);
                const message = [...baseMessage, textMessage];

                if (isGroupMessage && context.group_id) {
                    await qqBot.send_group_msg({
                        group_id: Number(context.group_id),
                        message: message as any[]
                    });
                } else {
                    await qqBot.send_private_msg({
                        user_id: Number(context.user_id),
                        message: message as any[]
                    });
                }
            }
        } else if (result?.picture?.enabled) {

            const messages: any[] = [createImageMessage(result.picture.base64)];

            if (typeof result.picture.supplement == "string") {
                messages.push(createTextMessage(result.picture.supplement));
            }

            if (isGroupMessage && context.group_id) {
                await qqBot.send_group_msg({
                    group_id: Number(context.group_id),
                    message: messages
                });
            } else {
                await qqBot.send_private_msg({
                    user_id: Number(context.user_id),
                    message: messages
                });
            }

        }

        else if (typeof result?.redirect == "string") {
            const targetCommand = findCommand(plugin, result.redirect);
            if (!targetCommand) {
                botlogger.info(`命令未找到: ${result.redirect}`);
                return;
            }
            return await handleCommand(context, plugin, targetCommand, args);
        }

        else {
            // 发送普通文本响应
            const message = [...baseMessage, createTextMessage(result)];

            if (isGroupMessage && context.group_id) {
                await qqBot.send_group_msg({
                    group_id: Number(context.group_id),
                    message: message
                });
            } else {
                await qqBot.send_private_msg({
                    user_id: Number(context.user_id),
                    message: message
                });
            }
        }

    } catch (error: unknown) {
        botlogger.error('执行命令出错:', error);
        const errorMessage = error instanceof Error ? error.message : '未知错误';
        await context.quick_action([{
            type: 'text',
            data: { text: `执行命令时出错: ${errorMessage}` }
        }]);
    }
}

// 导出加载插件函数
export async function loadplugins() {
    await runplugins();
}

// 修改 runcod 装饰器
export function runcod(cmd: string | string[], desc: string): MethodDecorator {
    return function decorator(target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor {
        // 获取插件配置
        const pluginConfig = target.constructor.prototype.plugincfg;
        if (!pluginConfig) {
            botlogger.error(`未找到插件配置: ${target.constructor.name}`);
            return descriptor;
        }

        const pluginId = pluginConfig.id;
        const pluginName = pluginConfig.name;

        // 获或创建插件的命令列表
        let plugin = commandList.find((p: Plugin) => p.class === target.constructor);
        if (!plugin) {
            plugin = {
                id: pluginId,
                name: pluginName,
                commands: [],
                class: target.constructor,
                config: pluginConfig
            };
            commandList.push(plugin);
            botlogger.info(`创建新插件[${pluginId}]: ${pluginName}`);
        }

        // 使用新的命令格式
        const cmdList = Array.isArray(cmd) ? cmd : [cmd];
        const [mainCmd, ...aliases] = cmdList;

        // 修改命令创建
        const command: Command = {
            cmd: mainCmd,
            desc,
            fn: descriptor.value,
            fnName: propertyKey.toString(),
            aliases,
            cmdPrefix: CMD_PREFIX,
            pluginId: pluginId,
            class: target.constructor,
            template: {
                enabled: false,
                sendText: true
            },
        };

        plugin.commands.push(command);
        botlogger.info(`注册命令[${pluginId}]: ${CMD_PREFIX}${pluginId} ${mainCmd}`);

        return descriptor;
    };
}

// 指令花费金币
export async function cost( context: PrivateFriendMessage | PrivateGroupMessage | GroupMessage,command: Command){
    if (economy.enable == false) {
        return;
    }
    const ecocmd = economyCommands.get(command.pluginId + "." + command.fnName);
    if (ecocmd) {
      if (ecocmd.type ==='add') {
        addCoins(context.sender.user_id.toString(), ecocmd.amount, ecocmd.reason);
      }else{
        removeCoins(context.sender.user_id.toString(), ecocmd.amount, ecocmd.reason);
      }
    }
}

// 修改参数解析函数
async function parseCommandParams(message: string, context: PrivateFriendMessage | PrivateGroupMessage | GroupMessage, command: Command,easycmd:boolean): Promise<any[]> {
    const cmdArgs = message.split(/\s+/).filter(Boolean);
    // 移除命令前缀和命令名
    const parts = message.split(/\s+/);
    let cmdIndex = 2;
    if (easycmd) {
        cmdIndex = 1;
    }
    const paramArgs: Receive[keyof Receive][] = [];
    parts.slice(cmdIndex).forEach((part) => {
        if (part !== '') {
            const Args: Receive["text"] ={
                type: 'text',
                data: {
                    text: part
                }
            }
            paramArgs.push(Args)
        }
    }); 
    // 插入其他类别的消息
    for(let i = 0;i<context.message.length;i++){
        if(i !== 0){
            const msg= context.message[i]
            if (msg.type === 'text') {
                const parts = msg.data.text.split(/\s+/);
                parts.forEach((part) => {
                    if (part!== '') {
                        const Args: Receive["text"] ={
                            type: 'text',
                            data: {
                                text: part
                            }
                        }
                        paramArgs.push(Args)
                    }
                });
            }else{
                paramArgs.push(context.message[i])
            }
            
        }
    }

    botlogger.info('DEBUG - 命令参数:' + JSON.stringify(paramArgs));

    const params: any[] = [];
    const param = paramMetadata.get(command.pluginId + "." + command.fnName);
    if (param) {
        let defaultValuei = 0
        param.forEach((paramData) => {
            if (paramData.defaultValue) {
                defaultValuei++    
            }
        })
        for (const paramData of param) {
            const { name, type, index, optional } = paramData;
            const msg = `正确格式为: ${CMD_PREFIX}${command.pluginId} ${command.cmd} ${param.map(p => p.optional ? `[${p.name}]` : `<${p.name}>`).join(' ')}`
            
            if (paramArgs.length + defaultValuei < param?.length) {
                throw new Error(`参数不足,${msg}`);
            }
            if (!optional && !paramArgs[index]) {
                throw new Error(`参数 <${name}> 是必需的,${msg}`);
            }
            // 检查参数类型
            if (optional && paramArgs[index] === undefined) {
                params[index] = paramData.defaultValue;
            }
            
            let msgtype = paramArgs[index]?.type ?? paramData.defaultValue?.type
            if (type === msgtype) {
                params[index] = paramArgs[index];
            }else{
                throw new Error(`参数 <${name}> 类型错误,${msg}`);
            }

            
        }
    }
    // 添加 context 参数
    params.push(context);

    // 调试日志
    botlogger.info('DEBUG - 最终参数:' + JSON.stringify({
        params: params.slice(0, -1), // 不显示 context
        paramCount: params.length,
        paramArgs
    }));

    return params;
}