// 导入指纹生成器
const { generateFingerprint } = require('./fingerprint');

// 自定义Base64字符表
const CUSTOM_BASE64_CHARS = "DGi0YA7BemWnQjCl4_bR3f8SKIF9tUz/xhr2oEOgPpac=61ZqwTudLkM5vHyNXsVJ";

// 哈希字段位置（这些字段需要随机生成）
const HASH_FIELDS = {
    16: 'split',  // 插件哈希（格式: count|hash，只替换hash部分）
    17: 'full',   // Canvas指纹哈希
    18: 'full',   // UserAgent哈希
    31: 'full',   // UserAgent哈希2
    34: 'full',   // 文档URL哈希
    36: 'full'    // 文档属性哈希
};

// ==================== LZW压缩算法 ====================

function lzwCompress(data, bits, charFunc) {
    if (data == null) return '';

    let dict = {};
    let dictToCreate = {};
    let c = '';
    let wc = '';
    let w = '';
    let enlargeIn = 2;
    let dictSize = 3;
    let numBits = 2;
    let result = [];
    let value = 0;
    let position = 0;

    for (let i = 0; i < data.length; i++) {
        c = data.charAt(i);

        if (!Object.prototype.hasOwnProperty.call(dict, c)) {
            dict[c] = dictSize++;
            dictToCreate[c] = true;
        }

        wc = w + c;

        if (Object.prototype.hasOwnProperty.call(dict, wc)) {
            w = wc;
        } else {
            if (Object.prototype.hasOwnProperty.call(dictToCreate, w)) {
                if (w.charCodeAt(0) < 256) {
                    for (let j = 0; j < numBits; j++) {
                        value = (value << 1);
                        if (position === bits - 1) {
                            position = 0;
                            result.push(charFunc(value));
                            value = 0;
                        } else {
                            position++;
                        }
                    }

                    let charCode = w.charCodeAt(0);
                    for (let j = 0; j < 8; j++) {
                        value = (value << 1) | (charCode & 1);
                        if (position === bits - 1) {
                            position = 0;
                            result.push(charFunc(value));
                            value = 0;
                        } else {
                            position++;
                        }
                        charCode >>= 1;
                    }
                } else {
                    let charCode = 1;
                    for (let j = 0; j < numBits; j++) {
                        value = (value << 1) | charCode;
                        if (position === bits - 1) {
                            position = 0;
                            result.push(charFunc(value));
                            value = 0;
                        } else {
                            position++;
                        }
                        charCode = 0;
                    }

                    charCode = w.charCodeAt(0);
                    for (let j = 0; j < 16; j++) {
                        value = (value << 1) | (charCode & 1);
                        if (position === bits - 1) {
                            position = 0;
                            result.push(charFunc(value));
                            value = 0;
                        } else {
                            position++;
                        }
                        charCode >>= 1;
                    }
                }

                enlargeIn--;
                if (enlargeIn === 0) {
                    enlargeIn = Math.pow(2, numBits);
                    numBits++;
                }
                delete dictToCreate[w];
            } else {
                let charCode = dict[w];
                for (let j = 0; j < numBits; j++) {
                    value = (value << 1) | (charCode & 1);
                    if (position === bits - 1) {
                        position = 0;
                        result.push(charFunc(value));
                        value = 0;
                    } else {
                        position++;
                    }
                    charCode >>= 1;
                }
            }

            enlargeIn--;
            if (enlargeIn === 0) {
                enlargeIn = Math.pow(2, numBits);
                numBits++;
            }

            dict[wc] = dictSize++;
            w = String(c);
        }
    }

    if (w !== '') {
        if (Object.prototype.hasOwnProperty.call(dictToCreate, w)) {
            if (w.charCodeAt(0) < 256) {
                for (let j = 0; j < numBits; j++) {
                    value = (value << 1);
                    if (position === bits - 1) {
                        position = 0;
                        result.push(charFunc(value));
                        value = 0;
                    } else {
                        position++;
                    }
                }

                let charCode = w.charCodeAt(0);
                for (let j = 0; j < 8; j++) {
                    value = (value << 1) | (charCode & 1);
                    if (position === bits - 1) {
                        position = 0;
                        result.push(charFunc(value));
                        value = 0;
                    } else {
                        position++;
                    }
                    charCode >>= 1;
                }
            } else {
                let charCode = 1;
                for (let j = 0; j < numBits; j++) {
                    value = (value << 1) | charCode;
                    if (position === bits - 1) {
                        position = 0;
                        result.push(charFunc(value));
                        value = 0;
                    } else {
                        position++;
                    }
                    charCode = 0;
                }

                charCode = w.charCodeAt(0);
                for (let j = 0; j < 16; j++) {
                    value = (value << 1) | (charCode & 1);
                    if (position === bits - 1) {
                        position = 0;
                        result.push(charFunc(value));
                        value = 0;
                    } else {
                        position++;
                    }
                    charCode >>= 1;
                }
            }

            enlargeIn--;
            if (enlargeIn === 0) {
                enlargeIn = Math.pow(2, numBits);
                numBits++;
            }
            delete dictToCreate[w];
        } else {
            let charCode = dict[w];
            for (let j = 0; j < numBits; j++) {
                value = (value << 1) | (charCode & 1);
                if (position === bits - 1) {
                    position = 0;
                    result.push(charFunc(value));
                    value = 0;
                } else {
                    position++;
                }
                charCode >>= 1;
            }
        }

        enlargeIn--;
        if (enlargeIn === 0) {
            enlargeIn = Math.pow(2, numBits);
            numBits++;
        }
    }

    let charCode = 2;
    for (let j = 0; j < numBits; j++) {
        value = (value << 1) | (charCode & 1);
        if (position === bits - 1) {
            position = 0;
            result.push(charFunc(value));
            value = 0;
        } else {
            position++;
        }
        charCode >>= 1;
    }

    while (true) {
        value = (value << 1);
        if (position === bits - 1) {
            result.push(charFunc(value));
            break;
        }
        position++;
    }

    return result.join('');
}

// ==================== 编码函数 ====================

function customEncode(data, urlSafe) {
    if (data == null) return '';

    const base64Chars = CUSTOM_BASE64_CHARS;

    let compressed = lzwCompress(data, 6, function(index) {
        return base64Chars.charAt(index);
    });

    if (!urlSafe) {
        switch (compressed.length % 4) {
            case 1: return compressed + '===';
            case 2: return compressed + '==';
            case 3: return compressed + '=';
            default: return compressed;
        }
    }

    return compressed;
}

// ==================== 辅助函数 ====================

function randomHash() {
    return Math.floor(Math.random() * 4294967296);
}

function generateDeviceId() {
    return Array.from({ length: 20 }, () =>
        Math.floor(Math.random() * 16).toString(16)
    ).join('');
}

// ==================== 数据解析和处理 ====================

function parseRealData(realData) {
    const fields = realData.split('^');
    return fields;
}

function processFields(fields) {
    const processed = [...fields];
    const currentTimestamp = Date.now();

    // 替换哈希字段
    for (const [index, type] of Object.entries(HASH_FIELDS)) {
        const idx = parseInt(index);

        if (type === 'split') {
            // 字段16: 格式为 "count|hash"，只替换hash部分
            const parts = processed[idx].split('|');
            if (parts.length === 2) {
                processed[idx] = `${parts[0]}|${randomHash()}`;
            }
        } else if (type === 'full') {
            // 完全替换为随机哈希
            if (idx === 36) {
                // 字段36: 文档属性哈希（10-100的随机整数）
                processed[idx] = Math.floor(Math.random() * 91) + 10;
            } else {
                processed[idx] = randomHash();
            }
        }
    }

    processed[33] = currentTimestamp;  // 字段33: 当前时间戳

    return processed;
}

// ==================== Cookie生成 ====================

function generateCookies(realData = null, fingerprintOptions = {}) {
    // 使用传入的指纹或生成新的随机指纹
    const fingerprint = realData || generateFingerprint(fingerprintOptions);

    // 解析指纹数据
    const fields = parseRealData(fingerprint);

    // 处理字段（随机化哈希，更新时间戳）
    const processedFields = processFields(fields);

    // 生成 ssxmod_itna (37字段)
    const ssxmod_itna_data = processedFields.join('^');
    const ssxmod_itna = '1-' + customEncode(ssxmod_itna_data, true);

    // 生成 ssxmod_itna2 (18字段)
    // 只使用: 字段0, 字段1, 字段23, 字段32, 字段33
    const ssxmod_itna2_data = [
        processedFields[0],   // 设备ID
        processedFields[1],   // SDK版本
        processedFields[23],  // 模式 (P/M)
        0, '', 0, '', '', 0,  // 事件相关（P模式下为空）
        0, 0,
        processedFields[32],  // 常量 (11)
        processedFields[33],  // 当前时间戳
        0, 0, 0, 0, 0
    ].join('^');
    const ssxmod_itna2 = '1-' + customEncode(ssxmod_itna2_data, true);

    return {
        ssxmod_itna,
        ssxmod_itna2,
        timestamp: parseInt(processedFields[33]),
        rawData: ssxmod_itna_data,
        rawData2: ssxmod_itna2_data
    };
}

function generateBatch(count = 10, realData = null, fingerprintOptions = {}) {
    const results = [];
    for (let i = 0; i < count; i++) {
        results.push(generateCookies(realData, fingerprintOptions));
    }
    return results;
}

// ==================== 主程序 ====================

if (require.main === module) {
    const result = generateCookies();
    console.log('ssxmod_itna:', result.ssxmod_itna);
    console.log('ssxmod_itna2:', result.ssxmod_itna2);
}

// ==================== 导出 ====================

module.exports = {
    generateCookies,
    generateBatch,
    customEncode,
    randomHash,
    generateDeviceId,
    parseRealData,
    generateFingerprint
};
