import { getCity } from '@/api/index.js'; 

let TIANDITU_KEY = '92c4ddd919f4e41a30e765680e3a29b7';
if (process.env.NODE_ENV == 'development') {
    TIANDITU_KEY = '9bcf63358817bfb878e8236de8bf1423';
}

class LocationService {
    /**
     * 初始化定位 (主入口)
     * 策略：优先 GPS -> 失败则 IP兜底 -> 统一逆地理编码
     * @returns {Promise<Object>} 返回最终的定位数据
     */
    async initLocation() {
        console.log('--- 开始初始化定位 ---');
        
        try {
            if (uni.getSystemInfoSync().uniPlatform === 'web') {

            }
            // Step 1: 优先尝试 GPS 精准定位, 竞速机制避免超时
            const gpsResult = await Promise.race([this.getGPSLocation(), this.timePromise()]);
            
            // Step 2: 如果 GPS 定位失败（如用户拒绝权限或超时），则降级使用 IP 定位
            if (gpsResult.status !== 'success') {
                console.log('GPS定位失败或被拒绝，降级使用 IP 定位');
                await this.getIPLocation();
            }
            
            // 等待逆地理编码完成（获取城市名），没有cityCode才去查
            if (!uni.getStorageSync('cityCode')) {
                await this.updateGeocode();
            }

            // Step 3: 确保数据已更新到 Storage，返回最新数据
            const finalLocation = uni.getStorageSync('positioning');
            return finalLocation;

        } catch (error) {
            console.error('定位流程异常:', error);
            // 即使报错，也尝试返回缓存中的旧数据，避免页面崩溃
            return uni.getStorageSync('positioning') || {};
        }
    }
    // 获取 IP 定位
    getIPLocation() {
        return new Promise(async (resolve) => {
            if (process.env.NODE_ENV === 'development') {
                let url = 'https://ip9.com.cn/get';
                // #ifdef H5
                // 正则匹配规则：覆盖 localhost、127.0.0.1、192.168.x.x、::1（IPv6回环）
                const localReg = /^(localhost|::1|127\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})|192\.168\.(\d{1,3})\.(\d{1,3}))$/;
                if (localReg.test(window.location.hostname.toLowerCase())) {
                    url = '/getIp/get';
                }
                // #endif
                uni.request({
                    url: url,   
                    method: 'GET',
                    success: (res) => {
                        if (res.data.ret == 200) {
                            this.updateData({
                                latitude: res.data.data.lat,
                                longitude: res.data.data.lng,
                                source: 'ip'
                            });
                        }
                        resolve();
                    },
                    fail: () => resolve() // 失败也 resolve，不阻断流程
                });
            } else {
                try {
                    const res = await getCity();
                    if (res.code === 200 && res.result.lat !== 0) {
                        if (!uni.getStorageSync('cityCode')) {
                            uni.setStorageSync('city', res.result.areaCname);
                            uni.setStorageSync('cityCode', res.result.areaCode);
                        }

                        this.updateData({
                            latitude: res.result.lat,
                            longitude: res.result.lng,
                            source: 'ip'
                        });
                    }
                    resolve();
                } catch (e) {
                    resolve();
                }
            }
        });
    }
    // 获取 GPS 原生定位
    getGPSLocation() {
        return new Promise((resolve) => {
            uni.getLocation({
                // #ifdef H5
                type: 'wgs84',
                // #endif
                // #ifndef H5
                type: 'gcj02',
                // #endif
                geocode: true,
                isHighAccuracy: true,
                success: async (res) => {
                    console.log('GPS 定位成功', res);
                    this.updateData({
                        latitude: res.latitude,
                        longitude: res.longitude,
                        source: 'gps',
                        isRefuse: ''
                    });
                    
                    resolve({ status: 'success', data: res });
                },
                fail: (err) => {
                    console.log('GPS 定位失败或拒绝', err);
                    // 记录拒绝状态
                    this.updateData({
                        isRefuse: 1
                    });
                    
                    resolve({ status: 'fail', error: err });
                }
            });
        });
    }
    // 超时Promise
    timePromise(wait = 1000) {
        return new Promise((resolve) => {
            // 2秒超时阈值
            setTimeout(() => {
                // 超时后返回「超时标识」，方便后续区分
                resolve({ status: 'fail', error: 'GPS定位超时' });
            }, wait); 
        })
    } 
    // 更新storage
    updateData(data) {
        const current = uni.getStorageSync('positioning') || {};
        uni.setStorageSync('positioning', {
            ...current,
            ...data
        });
    }
    // 天地图逆地理编码 (经纬度 -> 城市信息)，e为搜索时传值
    updateGeocode(e) {
        return new Promise((resolve) => {
            let location = e || uni.getStorageSync('positioning');
            if (!location || !location.longitude || !location.latitude) {
                return resolve();
            }

            let postStr = { 'lon': location.longitude, 'lat': location.latitude };
            uni.request({
                url: `https://api.tianditu.gov.cn/geocoder?postStr=${encodeURIComponent(JSON.stringify(postStr))}&type=geocode&tk=${TIANDITU_KEY}`,
                success: (res) => {
                    if (res.statusCode == 200 && res.data.status == 0) {
                        let obj = res.data.result.addressComponent;
                        uni.setStorageSync('city', obj.city);
                        uni.setStorageSync('cityCode', obj.city_code.slice(3));
                        uni.setStorageSync('addressName', obj.county);
                        uni.setStorageSync('addressCode', obj.county_code.slice(3));
                        // 经纬度所属城市，没有e说明是上面定位流程过来的
                        if (!e) this.updateData({
                            cityName: obj.city
                        });
                        console.log('逆地理编码更新成功:', obj.city);
                    }
                    resolve();
                },
                fail: () => resolve()
            });
        });
    }
    // 天地图地理编码 (城市信息 -> 经纬度)
    searchGeocode(e) {
        return new Promise((resolve) => {
            if (!e) {
                return resolve();
            }

            let postStr = { 'keyWord': e };
            uni.request({
                url: `https://api.tianditu.gov.cn/geocoder?ds=${encodeURIComponent(JSON.stringify(postStr))}&tk=${TIANDITU_KEY}`,
                success: (res) => {
                    if (res.statusCode == 200 && res.data.status == 0) {
                        let obj = res.data.location;
                        this.updateGeocode({
                            latitude: obj.lat,
                            longitude: obj.lon,
                        });
                        console.log('地理编码更新成功:', obj.keyWord);
                    }
                    resolve();
                },
                fail: () => resolve()
            });
        });
    }
    // 跳转到对应平台的系统设置页面
    openSystemSettings() {
        console.log('--- 尝试打开系统设置，准备重新定位 ---');
        
        // #ifdef APP-PLUS
        // App 端：直接调用 uni.openAppAuthorizeSetting
        uni.openAppAuthorizeSetting({
            success(res) {
                console.log('App: 成功打开授权设置界面', res);
            },
            fail(err) {
                console.error('App: 打开授权设置界面失败', err);
            },
            complete: async () => {
                // 确保 App 重新获得焦点且系统状态已更新
                await new Promise(r => setTimeout(r, 500)); 
                
                // 重新执行完整的定位流程
                console.log('App: 从系统设置返回，重新执行 initLocation');
                await this.initLocation();
            }
        });
        // #endif

        // #ifdef MP
        // 小程序端：提示用户进入设置页。实际的小程序权限设置需要用户在页面内点击 open-type="openSetting" 按钮触发。
        uni.showModal({
            title: '授权提示',
            content: '请在小程序设置页中手动开启“位置信息”权限。',
            confirmText: '去设置',
            success: (res) => {
                if (res.confirm) {
                    // 注意：uni.openSetting 在部分小程序平台可能已被废弃，且需要在用户交互后才能调用。
                    // 最佳实践是引导用户去一个包含 <button open-type="openSetting"></button> 的页面。
                    uni.openSetting({
                        success: async (settingRes) => {
                            console.log('MP: 用户完成设置', settingRes);
                            if (settingRes.authSetting['scope.userLocation']) {
                                // 权限开启，重新定位
                                await this.initLocation();
                            }
                        },
                        fail: () => {
                            console.log('MP: 打开设置页失败');
                        }
                    });
                }
            }
        });
        // #endif

        // #ifdef H5
        // H5 端：通常无法直接打开系统设置，只能提示用户手动操作
        uni.showModal({
            title: '授权提示',
            content: '请在浏览器或系统设置中手动开启定位权限。',
            showCancel: false,
            confirmText: '知道了'
        });
        // #endif
    }
}

export default new LocationService();