/**
 * 地址数据懒加载器 - 按需加载，大幅减少首次加载时间
 * 优化方案：
 * 1. 首次只加载省份列表（数据量很小，< 1MB）
 * 2. 选择省份后，按需加载该省份的市数据
 * 3. 逐级懒加载，避免一次性加载90M+数据
 */
import IndexedDBHelper from '@/common/IndexedDBHelper.js';

class AddressDataLoaderLazy {
    constructor() {
        this.dbHelper = null;
        this.dbName = 'AddressDataLazyDB';
        this.storeName = 'addressDataLazy';
        this.isInitialized = false;
        
        // 缓存配置
        this.cacheExpireDays = 7;
        
        // 数据源配置
        this.baseUrl = 'http://124.243.245.42/ks_cms';
        this.fullDataUrl = `${this.baseUrl}/address.json`; // 完整地址数据
        this.provinceListUrl = `${this.baseUrl}/address_provinces.json`; // 省份列表（轻量级，可选）
        this.provinceDetailUrl = `${this.baseUrl}/address_province_{code}.json`; // 省份详情（按需加载，可选）
        
        // 是否启用分片接口（如果服务器提供了分片接口，设置为true）
        this.useSplitApi = false; // 默认false，从完整数据中提取
        
        // 内存缓存（避免重复请求）
        this.memoryCache = new Map();
    }

    /**
     * 初始化数据库
     */
    async init() {
        if (this.isInitialized && this.dbHelper) {
            return;
        }

        try {
            this.dbHelper = new IndexedDBHelper(this.dbName, 1);
            await this.dbHelper.openDB([{
                name: this.storeName,
                keyPath: 'key',
                indexes: [
                    { name: 'type', key: 'type', unique: false },
                    { name: 'updateTime', key: 'updateTime', unique: false }
                ]
            }]);
            this.isInitialized = true;
            console.log('✅ 地址数据懒加载器初始化成功');
        } catch (error) {
            console.error('❌ 地址数据懒加载器初始化失败:', error);
            this.isInitialized = true;
        }
    }

    /**
     * 从缓存获取数据
     */
    async getCachedData(key) {
        // 先检查内存缓存
        if (this.memoryCache.has(key)) {
            const cached = this.memoryCache.get(key);
            if (cached.expireTime > Date.now()) {
                return cached.data;
            } else {
                this.memoryCache.delete(key);
            }
        }

        // 检查 IndexedDB 缓存
        try {
            if (this.dbHelper) {
                const cached = await this.dbHelper.get(this.storeName, key);
                if (cached && cached.data) {
                    const updateTime = cached.updateTime || 0;
                    const expireTime = this.cacheExpireDays * 24 * 60 * 60 * 1000;
                    if (Date.now() - updateTime < expireTime) {
                        // 同时更新内存缓存
                        this.memoryCache.set(key, {
                            data: cached.data,
                            expireTime: Date.now() + expireTime
                        });
                        return cached.data;
                    }
                }
            }
        } catch (e) {
            console.warn('从 IndexedDB 读取缓存失败:', e);
        }

        // 降级方案：从 uni.storage 读取
        try {
            const cached = uni.getStorageSync(key);
            if (cached && cached.data) {
                const updateTime = cached.updateTime || 0;
                const expireTime = this.cacheExpireDays * 24 * 60 * 60 * 1000;
                if (Date.now() - updateTime < expireTime) {
                    this.memoryCache.set(key, {
                        data: cached.data,
                        expireTime: Date.now() + expireTime
                    });
                    return cached.data;
                }
            }
        } catch (e) {
            console.warn('从 uni.storage 读取缓存失败:', e);
        }

        return null;
    }

    /**
     * 保存数据到缓存
     */
    async saveToCache(key, data, type = 'province') {
        const cacheData = {
            key: key,
            type: type,
            data: data,
            updateTime: Date.now()
        };

        // 更新内存缓存（1小时有效期）
        this.memoryCache.set(key, {
            data: data,
            expireTime: Date.now() + 60 * 60 * 1000
        });

        try {
            if (this.dbHelper) {
                try {
                    const existing = await this.dbHelper.get(this.storeName, key);
                    if (existing) {
                        await this.dbHelper.update(this.storeName, cacheData);
                    } else {
                        await this.dbHelper.add(this.storeName, cacheData);
                    }
                } catch (e) {
                    await this.dbHelper.add(this.storeName, cacheData);
                }
            }
        } catch (e) {
            console.warn('保存到 IndexedDB 失败，降级到 uni.storage:', e);
        }

        // 降级方案：保存到 uni.storage
        try {
            uni.setStorageSync(key, cacheData);
        } catch (e) {
            if (e.errMsg?.includes('exceed')) {
                console.warn('存储空间不足，清理部分缓存');
                await this.clearOldCache();
            }
        }
    }

    /**
     * 从服务器加载数据
     */
    async fetchData(url, cacheKey = null) {
        return new Promise((resolve, reject) => {
            console.log(`📥 开始加载: ${url}`);
            const startTime = Date.now();

            uni.request({
                url: url,
                method: 'GET',
                timeout: 60000, // 60秒超时
                success: (res) => {
                    const endTime = Date.now();
                    const duration = ((endTime - startTime) / 1000).toFixed(2);
                    console.log(`✅ 数据加载完成，耗时 ${duration} 秒`);

                    if (res.statusCode === 200) {
                        let data = res.data;
                        if (typeof data === 'string') {
                            try {
                                data = JSON.parse(data);
                            } catch (e) {
                                reject(new Error('JSON解析失败: ' + e.message));
                                return;
                            }
                        }
                        
                        // 如果提供了缓存key，自动保存
                        if (cacheKey) {
                            this.saveToCache(cacheKey, data).catch(e => {
                                console.warn('保存缓存失败:', e);
                            });
                        }
                        
                        resolve(data);
                    } else {
                        reject(new Error(`请求失败，状态码: ${res.statusCode}`));
                    }
                },
                fail: (err) => {
                    console.error('❌ 数据加载失败:', err);
                    reject(err);
                }
            });
        });
    }

    /**
     * 加载省份列表（轻量级，只包含省份基本信息，不包含children）
     * 这是首次加载，数据量很小（< 1MB）
     */
    async loadProvinceList(forceRefresh = false) {
        await this.init();
        
        const cacheKey = 'address_provinces_list';
        
        // 如果不是强制刷新，先尝试从缓存加载
        if (!forceRefresh) {
            const cached = await this.getCachedData(cacheKey);
            if (cached) {
                console.log('✅ 从缓存加载省份列表');
                return cached;
            }
        }

        uni.showLoading({
            title: '加载省份列表...',
            mask: true
        });

        try {
            let data = null;
            
            // 方案1：如果启用了分片接口，尝试从分片接口加载
            if (this.useSplitApi) {
                try {
                    data = await this.fetchData(this.provinceListUrl, cacheKey);
                    if (data && Array.isArray(data) && data.length > 0) {
                        console.log('✅ 从分片接口加载省份列表');
                        return data;
                    }
                } catch (error) {
                    console.warn('⚠️ 分片接口不可用，降级到完整数据提取:', error.message);
                }
            }
            
            // 方案2：从完整数据中提取省份列表（默认方案）
            // 如果完整数据已缓存，提取会很快；如果未缓存，需要加载完整数据
            data = await this.loadProvinceListFromFullData(forceRefresh);
            return data;
        } catch (error) {
            console.error('❌ 加载省份列表失败:', error);
            
            // 如果加载失败，尝试使用缓存（即使已过期）
            if (!forceRefresh) {
                const cached = await this.getCachedData(cacheKey);
                if (cached) {
                    console.log('⚠️ 使用过期缓存数据');
                    return cached;
                }
            }
            
            throw error;
        } finally {
            uni.hideLoading();
        }
    }

    /**
     * 从完整数据中提取省份列表（默认方案）
     * 优化策略：
     * 1. 优先从缓存获取已提取的省份列表（最快）
     * 2. 如果未缓存，尝试从缓存的完整数据中提取（快速）
     * 3. 如果完整数据也未缓存，使用分段加载策略：
     *    - 先尝试只加载前2MB数据来提取省份列表（快速）
     *    - 同时在后台加载完整数据（不阻塞用户）
     */
    async loadProvinceListFromFullData(forceRefresh = false) {
        const cacheKey = 'address_full_data';
        const provinceListCacheKey = 'address_provinces_extracted';
        
        // 先尝试从缓存获取已提取的省份列表
        if (!forceRefresh) {
            const cached = await this.getCachedData(provinceListCacheKey);
            if (cached) {
                console.log('✅ 从缓存加载已提取的省份列表');
                // 如果完整数据未缓存，在后台预加载
                this.preloadFullDataInBackground();
                return cached;
            }
        }
        
        // 尝试从缓存获取完整数据（如果已缓存，提取会很快）
        let fullData = await this.getCachedData(cacheKey);
        
        if (!fullData || forceRefresh) {
            // 如果完整数据未缓存，使用分段加载策略
            console.log('📥 完整数据未缓存，使用分段加载策略...');
            
            // 方案1：尝试分段加载（只加载前2MB来提取省份列表）
            try {
                const provinceList = await this.loadProvinceListFromPartialData();
                if (provinceList && provinceList.length > 0) {
                    console.log('✅ 从部分数据提取省份列表成功');
                    // 缓存提取的省份列表
                    await this.saveToCache(provinceListCacheKey, provinceList, 'province_list');
                    // 在后台预加载完整数据
                    this.preloadFullDataInBackground();
                    return provinceList;
                }
            } catch (error) {
                console.warn('⚠️ 分段加载失败，降级到完整加载:', error.message);
            }
            
            // 方案2：如果分段加载失败，加载完整数据
            console.log('📥 开始加载完整数据...');
            console.log('💡 提示：首次加载需要一些时间，加载后会缓存，后续使用会很快');
            
            uni.showLoading({
                title: '加载地址数据...',
                mask: true
            });
            
            try {
                fullData = await this.fetchData(this.fullDataUrl, cacheKey);
                console.log('✅ 完整数据加载完成，已缓存');
            } finally {
                uni.hideLoading();
            }
        } else {
            console.log('✅ 从缓存提取省份列表（快速）');
        }
        
        // 提取省份列表（只保留基本信息，移除children）
        let provinceList = [];
        if (Array.isArray(fullData)) {
            provinceList = fullData.map(province => ({
                code: province.code,
                name: province.name,
                // 不包含children，减少数据量
                _hasChildren: !!province.children && province.children.length > 0
            }));
            
            // 缓存提取的省份列表
            await this.saveToCache(provinceListCacheKey, provinceList, 'province_list');
        }
        
        return provinceList;
    }

    /**
     * 尝试从部分数据中提取省份列表（只加载前2MB）
     * 这样可以快速显示省份列表，而不需要等待90M数据加载完成
     */
    async loadProvinceListFromPartialData() {
        // 尝试使用Range请求只加载前2MB数据
        const maxBytes = 2 * 1024 * 1024; // 2MB
        
        return new Promise((resolve, reject) => {
            console.log('📥 尝试分段加载（前2MB）...');
            
            // 在H5环境可以使用fetch + Range请求
            // #ifdef H5
            if (typeof fetch !== 'undefined') {
                fetch(this.fullDataUrl, {
                    headers: {
                        'Range': `bytes=0-${maxBytes - 1}`
                    }
                })
                .then(response => {
                    if (response.status === 206 || response.status === 200) {
                        return response.text();
                    } else {
                        throw new Error(`Range请求失败，状态码: ${response.status}`);
                    }
                })
                .then(text => {
                    // 尝试解析部分JSON
                    const provinceList = this.extractProvincesFromPartialJson(text);
                    if (provinceList && provinceList.length > 0) {
                        console.log(`✅ 从部分数据提取到 ${provinceList.length} 个省份`);
                        resolve(provinceList);
                    } else {
                        reject(new Error('无法从部分数据中提取省份列表'));
                    }
                })
                .catch(error => {
                    reject(error);
                });
            } else {
                reject(new Error('当前环境不支持Range请求'));
            }
            // #endif
            
            // #ifndef H5
            // 小程序环境不支持Range请求，直接拒绝
            reject(new Error('小程序环境不支持Range请求，将使用完整加载'));
            // #endif
        });
    }

    /**
     * 从部分JSON字符串中提取省份列表
     * 由于JSON可能不完整，需要智能解析
     */
    extractProvincesFromPartialJson(partialJson) {
        try {
            const provinces = [];
            const seenCodes = new Set();
            
            // 方法1：使用正则表达式提取所有省份（code和name）
            // 匹配模式：{"code":"31","name":"上海市",...} 或 "code":"31","name":"上海市"
            const patterns = [
                // 标准格式：{"code":"31","name":"上海市"}
                /\{\s*"code"\s*:\s*"([^"]+)"\s*,\s*"name"\s*:\s*"([^"]+)"[^}]*\}/g,
                // 简化格式："code":"31","name":"上海市"
                /"code"\s*:\s*"([^"]+)"\s*,\s*"name"\s*:\s*"([^"]+)"/g
            ];
            
            for (const pattern of patterns) {
                let match;
                while ((match = pattern.exec(partialJson)) !== null) {
                    const code = match[1];
                    const name = match[2];
                    
                    // 省份code通常是2位数字（如"31"），或者6位数字（如"310000"）
                    // 根据实际数据结构，code可能是"31"格式
                    if (code && name && !seenCodes.has(code)) {
                        // 判断是否为省份code（2位或6位数字）
                        if ((code.length === 2 && /^\d{2}$/.test(code)) || 
                            (code.length === 6 && /^\d{6}$/.test(code))) {
                            seenCodes.add(code);
                            provinces.push({
                                code: code,
                                name: name,
                                _hasChildren: true // 假设都有下级
                            });
                        }
                    }
                }
            }
            
            // 方法2：如果正则提取失败，尝试解析JSON（可能不完整）
            if (provinces.length === 0) {
                try {
                    // 尝试修复不完整的JSON
                    let jsonStr = partialJson.trim();
                    
                    // 如果以[开头，尝试找到所有完整的省份对象
                    if (jsonStr.startsWith('[')) {
                        // 查找所有省份对象的开始位置
                        let pos = 1; // 跳过开头的[
                        while (pos < jsonStr.length) {
                            // 找到下一个{的位置
                            const objStart = jsonStr.indexOf('{', pos);
                            if (objStart === -1) break;
                            
                            // 尝试找到这个对象的结束位置（简单的匹配）
                            let braceCount = 0;
                            let objEnd = objStart;
                            for (let i = objStart; i < jsonStr.length; i++) {
                                if (jsonStr[i] === '{') braceCount++;
                                if (jsonStr[i] === '}') braceCount--;
                                if (braceCount === 0) {
                                    objEnd = i + 1;
                                    break;
                                }
                            }
                            
                            if (objEnd > objStart) {
                                const objStr = jsonStr.substring(objStart, objEnd);
                                try {
                                    const obj = JSON.parse(objStr);
                                    if (obj.code && obj.name && !seenCodes.has(obj.code)) {
                                        seenCodes.add(obj.code);
                                        provinces.push({
                                            code: obj.code,
                                            name: obj.name,
                                            _hasChildren: true
                                        });
                                    }
                                } catch (e) {
                                    // 解析失败，继续下一个
                                }
                            }
                            
                            pos = objEnd;
                        }
                    }
                } catch (e) {
                    // 解析失败，忽略
                }
            }
            
            // 去重并排序
            const uniqueProvinces = Array.from(new Map(provinces.map(p => [p.code, p])).values());
            
            return uniqueProvinces.length > 0 ? uniqueProvinces : null;
        } catch (error) {
            console.warn('从部分JSON提取省份列表失败:', error);
            return null;
        }
    }

    /**
     * 在后台预加载完整数据（不阻塞用户操作）
     */
    async preloadFullDataInBackground() {
        const cacheKey = 'address_full_data';
        
        // 检查是否已缓存
        const cached = await this.getCachedData(cacheKey);
        if (cached) {
            console.log('✅ 完整数据已缓存，无需预加载');
            return;
        }
        
        console.log('🔄 开始在后台预加载完整数据...');
        
        // 使用setTimeout让出主线程，避免阻塞
        setTimeout(async () => {
            try {
                await this.fetchData(this.fullDataUrl, cacheKey);
                console.log('✅ 后台预加载完成，完整数据已缓存');
            } catch (error) {
                console.warn('⚠️ 后台预加载失败:', error);
            }
        }, 100);
    }

    /**
     * 加载省份详情（包含该省份的所有下级数据）
     * 按需加载，只有用户选择该省份时才加载
     */
    async loadProvinceDetail(provinceCode, forceRefresh = false) {
        await this.init();
        
        const cacheKey = `address_province_${provinceCode}`;
        
        // 如果不是强制刷新，先尝试从缓存加载
        if (!forceRefresh) {
            const cached = await this.getCachedData(cacheKey);
            if (cached) {
                console.log(`✅ 从缓存加载省份详情: ${provinceCode}`);
                return cached;
            }
        }

        uni.showLoading({
            title: '加载城市数据...',
            mask: true
        });

        try {
            let data = null;
            
            // 方案1：如果启用了分片接口，尝试从分片接口加载
            if (this.useSplitApi) {
                try {
                    const url = this.provinceDetailUrl.replace('{code}', provinceCode);
                    data = await this.fetchData(url, cacheKey);
                    if (data && data.code === provinceCode) {
                        console.log(`✅ 从分片接口加载省份详情: ${provinceCode}`);
                        return data;
                    }
                } catch (error) {
                    console.warn(`⚠️ 分片接口不可用，降级到完整数据提取: ${error.message}`);
                }
            }
            
            // 方案2：从完整数据中提取省份详情（默认方案）
            data = await this.loadProvinceDetailFromFullData(provinceCode, forceRefresh);
            return data;
        } catch (error) {
            console.error(`❌ 加载省份详情失败: ${provinceCode}`, error);
            
            // 如果加载失败，尝试使用缓存
            if (!forceRefresh) {
                const cached = await this.getCachedData(cacheKey);
                if (cached) {
                    console.log('⚠️ 使用过期缓存数据');
                    return cached;
                }
            }
            
            throw error;
        } finally {
            uni.hideLoading();
        }
    }

    /**
     * 从完整数据中提取省份详情（默认方案）
     * 如果完整数据已缓存，提取会很快
     */
    async loadProvinceDetailFromFullData(provinceCode, forceRefresh = false) {
        const cacheKey = 'address_full_data';
        
        // 先尝试从缓存获取完整数据（如果已缓存，提取会很快）
        let fullData = await this.getCachedData(cacheKey);
        
        if (!fullData || forceRefresh) {
            // 如果完整数据未缓存，需要加载完整数据
            console.log(`📥 完整数据未缓存，开始加载完整数据以获取省份 ${provinceCode}...`);
            
            uni.showLoading({
                title: '加载地址数据...',
                mask: true
            });
            
            try {
                fullData = await this.fetchData(this.fullDataUrl, cacheKey);
                console.log('✅ 完整数据加载完成，已缓存');
            } finally {
                uni.hideLoading();
            }
        } else {
            console.log(`✅ 从缓存提取省份详情: ${provinceCode}（快速）`);
        }
        
        // 查找并返回指定省份的完整数据
        // 注意：根据实际数据结构，code可能是"31"格式，需要精确匹配
        if (Array.isArray(fullData)) {
            const province = fullData.find(p => p.code === provinceCode || p.code === String(provinceCode));
            if (province) {
                return province;
            } else {
                console.warn(`⚠️ 未找到省份: ${provinceCode}`);
                return null;
            }
        }
        
        return null;
    }

    /**
     * 清除缓存
     */
    async clearCache() {
        await this.init();
        
        try {
            if (this.dbHelper) {
                await this.dbHelper.clearStore(this.storeName);
            }
            // 清除 uni.storage
            const keys = uni.getStorageInfoSync().keys;
            keys.forEach(key => {
                if (key.startsWith('address_')) {
                    uni.removeStorageSync(key);
                }
            });
            // 清除内存缓存
            this.memoryCache.clear();
            console.log('✅ 已清除所有地址数据缓存');
        } catch (e) {
            console.error('清除缓存失败:', e);
        }
    }

    /**
     * 清除旧缓存
     */
    async clearOldCache() {
        try {
            // 清除7天前的缓存
            const expireTime = this.cacheExpireDays * 24 * 60 * 60 * 1000;
            const now = Date.now();
            
            if (this.dbHelper) {
                const allData = await this.dbHelper.getAll(this.storeName);
                for (const item of allData) {
                    if (item.updateTime && (now - item.updateTime) > expireTime) {
                        await this.dbHelper.delete(this.storeName, item.key);
                    }
                }
            }
        } catch (e) {
            console.warn('清理旧缓存失败:', e);
        }
    }
}

// 单例模式
const addressDataLoaderLazy = new AddressDataLoaderLazy();

export default addressDataLoaderLazy;

