import * as fs from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';

// 假设 IPage 接口定义如下
interface IPage {
    SetInstanceId(id: string): void;
}

// 假设 PageContainer 类定义如下
class PageContainer {
    ModalInvoke(action: () => void, message: string) {
        action();
    }
}

// 假设 PlatformSettings 类定义如下
class PlatformSettings {
    static IsDebugMode = false;
    static PagesDirectory = 'pages';
}

// 假设 ConfigManager 类定义如下
class ConfigManager {
    private static instance: ConfigManager;

    static GetInstance() {
        if (!this.instance) {
            this.instance = new ConfigManager();
        }
        return this.instance;
    }

    GetConfigValue(key: string, configType: any) {
        return 'false';
    }
}

// 假设 ConfigType 枚举定义如下
enum ConfigType {
    System
}

// 假设 FilesHandle 类定义如下
class FilesHandle {
    static UpdateAssemblys: { [key: string]: boolean } = {};

    static UpdateTradeDll(actionName: string) {
        return true;
    }
}

// 假设 FileHandle 类定义如下
class FileHandle {
    static GetFileMD5(fileInfo: { path: string }) {
        const data = fs.readFileSync(fileInfo.path);
        return crypto.createHash('md5').update(data).digest('hex');
    }
}

// 假设 PlatformLogger 类定义如下
class PlatformLogger {
    static SystemInfo(message: string) {
        console.log(message);
    }
}

class PageFactory {
    private static Logger = {
        Error(message: string) {
            console.error(message);
        }
    };

    private static LoadedActionTypes: { [key: string]: any } = {};
    private static LoadedActionMD5: { [key: string]: string } = {};

    static CreatePage(actionName: string, pageContainer?: PageContainer): IPage | null {
        let actionType: any = null;
        if (!pageContainer) {
            actionType = this.GetActionType(actionName);
        } else {
            pageContainer.ModalInvoke(() => {
                actionType = this.GetActionType(actionName);
            }, "正在加载交易页面，请稍后...");
        }
        if (!actionType) {
            this.Logger.Error(`加载文件名为：【${actionName}】的交易失败！`);
            return null;
        } else {
            const page = new actionType() as IPage;
            if (page) {
                page.SetInstanceId(this.generateGuid());
            }
            return page;
        }
    }

    private static GetActionType(actionName: string): any {
        let actionType: any = null;

        if (!PlatformSettings.IsDebugMode) {
            let flag = false;
            flag = Boolean(ConfigManager.GetInstance().GetConfigValue("IsFromProjectDownLoadTradeDll", ConfigType.System));
            if (!flag) {
                PlatformLogger.SystemInfo(`Update Trade File,FileName:[${actionName}]`);
                if (!FilesHandle.UpdateTradeDll(actionName)) {
                    return null;
                }
            } else {
                PlatformLogger.SystemInfo(`已由项目层检测和下载交易的dll:[${actionName}]`);
            }
        }

        if (PlatformSettings.IsDebugMode || !this.LoadedActionTypes[actionName]
            || (FilesHandle.UpdateAssemblys[actionName] && FilesHandle.UpdateAssemblys[actionName])) {
            const fileName = `${actionName}.dll`;
            const pagesDirectory = PlatformSettings.PagesDirectory;
            const filePath = path.join(process.cwd(), pagesDirectory, fileName);
            if (fs.existsSync(filePath)) {
                const fileMD5 = FileHandle.GetFileMD5({ path: filePath });
                if (PlatformSettings.IsDebugMode && this.LoadedActionMD5[actionName] && this.LoadedActionMD5[actionName] === fileMD5
                    && this.LoadedActionTypes[actionName]) {
                    return this.LoadedActionTypes[actionName];
                } else {
                    this.LoadedActionMD5[actionName] = fileMD5;
                }

                const rawAssembly = this.loadFile(filePath);
                // 这里无法直接加载 DLL，仅作示例
                // 假设存在一个模块加载函数
                const assembly = this.loadModule(rawAssembly);
                if (!assembly) return null;
                for (const key in assembly) {
                    if (assembly.hasOwnProperty(key)) {
                        const type = assembly[key];
                        if (this.isIPage(type)) {
                            this.LoadedActionTypes[type.name] = type;
                        }
                    }
                }
                actionType = this.LoadedActionTypes[actionName];
            }
        }

        return actionType;
    }

    private static loadFile(filename: string): Buffer {
        if (!fs.existsSync(filename)) {
            return Buffer.alloc(0);
        }
        return fs.readFileSync(filename);
    }

    private static generateGuid() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            const r = Math.random() * 16 | 0;
            const v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

    private static isIPage(type: any): boolean {
        // 简单判断是否实现了 IPage 接口
        return typeof type.prototype.SetInstanceId === 'function';
    }

    private static loadModule(rawAssembly: Buffer): any {
        // 这里无法直接加载 DLL，仅作示例
        return {};
    }
}

export { PageFactory };