import * as path from 'path';

// 动态导入平台加载器（支持ESM和CommonJS）
let loadNativeAddon: () => any;
try {
    // 尝试使用require (CommonJS)
    loadNativeAddon = require('./platform-loader').loadNativeAddon;
} catch (e) {
    // 如果require失败，将在运行时使用动态import (ESM)
    loadNativeAddon = null as any;
}

// 接口定义
export interface MQConfig {
    endpoint: string;
    accessKeyId: string;
    accessKeySecret: string;
    instanceId: string;
    logLevel?: string;    // 可选：日志级别 (debug, info, warn, error, fatal)
    thread?: number;      // 可选：消费者并发线程数，默认为 20
}

export interface MessageData {
    messageId: string;
    receiptHandle: string;
    body: string;
    tag: string;
    properties: { [key: string]: string };
    bornTimestamp: number;
    reconsumeTimes: number;
}

export interface SendResult {
    messageId: string;
    receiptHandle: string;
}

export interface DelayOptions {
    delayTimeLevel?: number;
    startDeliverTime?: number;
}

// MessageProperties类
export class MessageProperties {
    public properties: { [key: string]: string } = {};
    public message_key: string = '';
    public sharding_key: string = '';
    public start_deliver_time: number = 0;
    public trans_check_immunity_time: number = 0;

    putProperty(key: string, value: string | number): MessageProperties {
        this.properties[key] = String(value);
        return this;
    }

    messageKey(key: string): MessageProperties {
        this.message_key = String(key);
        return this;
    }

    shardingKey(key: string): MessageProperties {
        this.sharding_key = String(key);
        return this;
    }

    startDeliverTime(time: number): MessageProperties {
        this.start_deliver_time = Number(time);
        // 同时设置RocketMQ标准属性
        this.properties['__STARTDELIVERTIME'] = String(time);
        return this;
    }

    transCheckImmunityTime(time: number): MessageProperties {
        this.trans_check_immunity_time = Number(time);
        return this;
    }

    toJSON(): any {
        const result: any = {
            properties: this.properties,
            messageKey: this.message_key,
            shardingKey: this.sharding_key,
            transCheckImmunityTime: this.trans_check_immunity_time
        };

        // 只有在没有设置 __STARTDELIVERTIME 属性时才包含 startDeliverTime
        if (!this.properties['__STARTDELIVERTIME'] && this.start_deliver_time > 0) {
            result.startDeliverTime = this.start_deliver_time;
        }

        return result;
    }
}

// Native客户端实现
class NativeClient {
    private nativeClient: any;
    private config: MQConfig;

    constructor(config: MQConfig) {
        this.config = config;
    }

    public async initNativeClient() {
        try {
            // 如果是ESM环境，使用动态导入
            if (!loadNativeAddon) {
                // @ts-ignore - 动态导入平台加载器
                const module = await import('./platform-loader.js');
                loadNativeAddon = module.loadNativeAddon;
            }

            // 使用平台加载器加载Native Addon
            const addon = loadNativeAddon();
            this.nativeClient = new addon.RocketMQClient();

            // 初始化RocketMQ
            const configJson = {
                endpoint: this.config.endpoint,
                accessKeyId: this.config.accessKeyId,
                accessKeySecret: this.config.accessKeySecret,
                instanceId: this.config.instanceId,
                ...(this.config.logLevel && { logLevel: this.config.logLevel }),
                ...(this.config.thread && { thread: this.config.thread })
            };

            const result = this.nativeClient.initRocketMQ(configJson);
            if (!result.success) {
                throw new Error(`Failed to initialize RocketMQ: ${result.message}`);
            }

            console.log('🚀 RocketMQ Native Client initialized successfully');
        } catch (error: any) {
            throw new Error(`Failed to load Native Addon: ${error.message}`);
        }
    }

    async getProducer(instanceId: string, topic: string): Promise<Producer> {
        const configJson = JSON.stringify(this.config);
        const producer = this.nativeClient.createProducer(configJson, topic);
        if (producer.success === false) {
            throw new Error(`Failed to create producer: ${producer.message}`);
        }
        return new NativeProducer(producer, this.nativeClient);
    }

    async getConsumer(instanceId: string, topic: string, groupId: string, tagExpression: string = '*'): Promise<Consumer> {
        const configJson = JSON.stringify(this.config);
        const consumer = this.nativeClient.createConsumer(configJson, topic, groupId, tagExpression);
        if (consumer.success === false) {
            throw new Error(`Failed to create consumer: ${consumer.message}`);
        }
        return new NativeConsumer(consumer, this.nativeClient);
    }

    async healthCheck(): Promise<any> {
        return {
            status: 'healthy',
            mode: 'native',
            timestamp: Date.now()
        };
    }
}

// 生产者抽象类
export abstract class Producer {
    abstract publishMessage(messageBody: any, tag?: string, properties?: MessageProperties | null): Promise<SendResult>;
    abstract publishOrderedMessage(messageBody: any, tag?: string, properties?: MessageProperties | null, shardingKey?: string): Promise<SendResult>;
    abstract publishDelayMessage(messageBody: any, tag?: string, properties?: MessageProperties | null, options?: DelayOptions): Promise<SendResult>;
    abstract shutdown(): Promise<any>;
}

// Native生产者实现
class NativeProducer extends Producer {
    constructor(private producerInfo: any, private nativeClient: any) {
        super();
    }

    async publishMessage(messageBody: any, tag: string = '', properties: MessageProperties | null = null): Promise<SendResult> {
        const body = typeof messageBody === 'object' ? JSON.stringify(messageBody) : String(messageBody);
        const props = properties ? JSON.stringify(properties.toJSON()) : '{}';

        const result = this.nativeClient.sendMessage(this.producerInfo.producerId, body, tag, props);
        if (!result || typeof result === 'string') {
            // 如果返回字符串，假设是成功的消息ID
            return {
                messageId: result || 'unknown',
                receiptHandle: result || 'unknown'
            };
        }

        if (!result.success) {
            throw new Error(`Failed to send message: ${result.message}`);
        }

        return {
            messageId: result.messageId,
            receiptHandle: result.receiptHandle
        };
    }

    async publishOrderedMessage(messageBody: any, tag: string = '', properties: MessageProperties | null = null, shardingKey?: string): Promise<SendResult> {
        const body = typeof messageBody === 'object' ? JSON.stringify(messageBody) : String(messageBody);
        const props = properties ? JSON.stringify(properties.toJSON()) : '{}';

        const result = this.nativeClient.sendOrderedMessage(this.producerInfo.producerId, body, tag, props, shardingKey || '');
        if (!result || typeof result === 'string') {
            // 如果返回字符串，假设是成功的消息ID
            return {
                messageId: result || 'unknown',
                receiptHandle: result || 'unknown'
            };
        }

        if (!result.success) {
            throw new Error(`Failed to send ordered message: ${result.message}`);
        }

        return {
            messageId: result.messageId,
            receiptHandle: result.receiptHandle
        };
    }

    async publishDelayMessage(messageBody: any, tag: string = '', properties: MessageProperties | null = null, options: DelayOptions = {}): Promise<SendResult> {
        // 对于延迟消息，将延迟时间设置到properties中
        const props: any = properties ? properties.toJSON() : {};

        // RocketMQ任意精度延迟消息：使用 __STARTDELIVERTIME 属性
        if (options.startDeliverTime) {
            props.properties = props.properties || {};
            props.properties['__STARTDELIVERTIME'] = String(options.startDeliverTime);
        }

        // RocketMQ传统延迟等级：使用 delayTimeLevel
        if (options.delayTimeLevel) {
            props.delayTimeLevel = options.delayTimeLevel;
        }

        const body = typeof messageBody === 'object' ? JSON.stringify(messageBody) : String(messageBody);
        const result = this.nativeClient.sendMessage(this.producerInfo.producerId, body, tag, JSON.stringify(props));

        if (!result || typeof result === 'string') {
            // 如果返回字符串，假设是成功的消息ID
            return {
                messageId: result || 'unknown',
                receiptHandle: result || 'unknown'
            };
        }

        if (!result.success) {
            throw new Error(`Failed to send delay message: ${result.message}`);
        }

        return {
            messageId: result.messageId,
            receiptHandle: result.receiptHandle
        };
    }

    async shutdown(): Promise<any> {
        const result = this.nativeClient.shutdownProducer(this.producerInfo.producerId);
        if (!result || typeof result === 'string') {
            return { success: true, message: 'Producer shutdown' };
        }

        if (!result.success) {
            throw new Error(`Failed to shutdown producer: ${result.message}`);
        }
        return result;
    }
}

// 消费者抽象类
export abstract class Consumer {
    protected messageHandlers: Array<(message: MessageData) => void | Promise<void>> = [];

    abstract onMessage(handler: (message: MessageData) => void | Promise<void>): void;
    abstract startReceiving(tagExpression?: string): any;
    abstract ackMessage(receiptHandle: string): Promise<any>;
    abstract shutdown(): Promise<any>;
}

// Native消费者实现
class NativeConsumer extends Consumer {
    constructor(private consumerInfo: any, private nativeClient: any) {
        super();
    }

    onMessage(handler: (message: MessageData) => void | Promise<void>): void {
        this.messageHandlers.push(handler);

        // 注册消息处理器到Native Addon
        this.nativeClient.registerMessageHandler(this.consumerInfo.consumerId, (messageJson: string) => {
            try {
                // 解析消息JSON
                const messageData = JSON.parse(messageJson);

                // 调用所有注册的处理器
                for (const h of this.messageHandlers) {
                    try {
                        h(messageData);
                    } catch (error) {
                        console.error('Error in message handler:', error);
                    }
                }
            } catch (error) {
                console.error('Error parsing message JSON:', error);
            }
        });
    }

    startReceiving(tagExpression: string = '*'): any {
        const result = this.nativeClient.startConsumer(this.consumerInfo.consumerId, this.consumerInfo.topic || '', tagExpression);
        if (!result || typeof result === 'string') {
            return { success: true, message: 'Consumer started' };
        }

        if (!result.success) {
            throw new Error(`Failed to start receiving: ${result.message}`);
        }
        return result;
    }

    async ackMessage(receiptHandle: string): Promise<any> {
        const result = this.nativeClient.ackMessage(this.consumerInfo.consumerId, receiptHandle);
        if (!result || typeof result === 'string') {
            return { success: true, message: 'Message acknowledged' };
        }

        if (!result.success) {
            throw new Error(`Failed to ack message: ${result.message}`);
        }
        return result;
    }

    async shutdown(): Promise<any> {
        const result = this.nativeClient.shutdownConsumer(this.consumerInfo.consumerId);
        if (!result || typeof result === 'string') {
            return { success: true, message: 'Consumer shutdown' };
        }

        if (!result.success) {
            throw new Error(`Failed to shutdown consumer: ${result.message}`);
        }
        return result;
    }
}

// 主客户端类
export class MQClient {
    private client: NativeClient;
    private initialized: boolean = false;

    constructor(config: MQConfig) {
        this.client = new NativeClient(config);
    }

    private async ensureInitialized() {
        if (!this.initialized) {
            await this.client.initNativeClient();
            this.initialized = true;
        }
    }

    /**
     * 创建生产者
     * @param instanceId 实例ID
     * @param topic 主题
     * @returns 生产者实例
     */
    async getProducer(instanceId: string, topic: string): Promise<Producer> {
        await this.ensureInitialized();
        return this.client.getProducer(instanceId, topic);
    }

    /**
     * 创建消费者
     * @param instanceId 实例ID
     * @param topic 主题
     * @param groupId 消费者组ID
     * @param tagExpression 标签表达式 (默认为'*')
     * @returns 消费者实例
     */
    async getConsumer(instanceId: string, topic: string, groupId: string, tagExpression: string = '*'): Promise<Consumer> {
        await this.ensureInitialized();
        return this.client.getConsumer(instanceId, topic, groupId, tagExpression);
    }

    /**
     * 健康检查
     */
    async healthCheck(): Promise<any> {
        await this.ensureInitialized();
        return this.client.healthCheck();
    }

    /**
     * 获取客户端模式
     */
    getMode(): string {
        return 'native';
    }
}

// 导出所有类型和类
export default MQClient; 