<!-- 灵活用工地图模式 -->
<script setup lang="ts">
    import * as turf from '@turf/turf'
    import RegisterDialog from './register-dialog.vue'
    import type { Page } from './config'
    import Navigate from '@/utils/page/navigate'
    import { flyTo, useMapbox } from '@/components/Map/Mapbox/hook'
    import { getText } from '@/utils/dict/area'
    import * as LinghuoyonggongAPI from '@/api/model/linghuoyonggong'
    import { reactive, ref, onMounted, toRefs } from 'vue'
    import { onLoad } from '@dcloudio/uni-app'

    // 页面参数
    const page = reactive<Page>({
        id: 'example-mapbox',
        init: false,
        requests: 0,
        latest: null,
        query: {},
    })

    const model = reactive({
        id: '',
        name: '',
        lonlat: `${uni.getStorageSync('location')?.lon || ''},${uni.getStorageSync('location')?.lat || ''}`,
        employmentId: null,
        showConfirmDialog: false,
        contactName: '',
        contactMobile: '',

        categoryTabs: [
            { id: null, name: '全部' },
            { id: 1, name: '种植' },
            { id: 2, name: '养殖' },
            { id: 3, name: '采摘' },
            { id: 4, name: '其他' },
        ],
        search: {
            pageNo: 1,
            pageSize: 200, // 地图模式加载更多点位以展现全局视野
            publishstatu: 1,
            type: null,
            createBy: '',
        },
        employmentList: [],
        loading: false,
        total: 0,
        userLocation: {
            longitude: uni.getStorageSync('location')?.lon || 112.982273,
            latitude: uni.getStorageSync('location')?.lat || 28.19409,
        },
        searchText: '',
        currentEmploymentId: 1,
        markerIds: [], // 用于跟踪当前地图上的 Marker
    })

    onLoad((options) => {
        model.id = options.id
        // 确保从 URL 参数中获取正确的业务 Tab ID
        if (options.currentEmploymentId) {
            model.currentEmploymentId = Number(options.currentEmploymentId)
        }
        model.name = decodeURIComponent(options.name || '')
        
        // 尝试获取精准位置
        uni.getLocation({
            type: 'wgs84',
            success: (res) => {
                model.userLocation.longitude = res.longitude
                model.userLocation.latitude = res.latitude
                // 定位成功后，如果地图已加载，渲染用户图标
                if (map) renderUserLocation()
            }
        })
        
        getEmploymentList()
    })

    // 地图组件
    const loc = uni.getStorageSync('location')
    const center: [number, number] = [loc?.lon || 112.982273, loc?.lat || 28.19409]
    const registerDialogRef = ref()
    
    let mapReady = false

    const [registerMap, map] = useMapbox({
        style: { center, zoom: 11 },
        onLoaded: () => {
            mapReady = true
            renderUserLocation()
            // 地图就绪后，如果数据已先到达，立即渲染
            if (model.employmentList.length) {
                renderEmploymentMarkers()
            }
        },
        onMapEvent: (event) => {
            if (event.type === 'custom' && event.name === 'navigateToDetail') {
                if (model.currentEmploymentId == 2) {
                    model.employmentId = event.data
                    getLaborAppDetail()
                } else {
                    registerDialogRef.value.open({ id: event.data })
                }
            }
        },
    })

    async function getLaborAppDetail() {
        const res = await LinghuoyonggongAPI.getLaborAppDetail({ id: model.employmentId })
        model.contactMobile = res.contactMobile
        model.contactName = res.contactName ? (res.contactName.substring(0, 1) + '**') : '负责人'
        model.showConfirmDialog = true
    }

    function makePhoneCall() {
        uni.makePhoneCall({ phoneNumber: model.contactMobile })
    }

    // 创建更美观的弹框HTML
    function createPopupHTML(item) {
        if (!item) return ''
        const isLabor = model.currentEmploymentId == 2
        const title = isLabor ? item.villageName : item.name
        const subTitle = isLabor ? item.villageFullName : item.area
        const distance = isLabor ? getDistanceText2(item) : getDistanceText(item)
        const btnText = isLabor ? '拨号联系' : '我也去'
        const stats = isLabor ? `待工人数 ${item.workers} 名` : `💰 ${item.price}元/天 · 👥 需${item.workers}人`
        const image = isLabor ? './static/images/linghuoyonggong/avatar.png' : item.picture

        return `
            <div class="map-popup-card">
                <div class="popup-header">
                    <div class="popup-title-row">
                        <span class="p-title">${title}</span>
                        <span class="p-dist">📍 ${distance}</span>
                    </div>
                    <div class="p-subtitle">${subTitle}</div>
                </div>
                <div class="popup-body">
                    <div class="p-stats">${stats}</div>
                    ${!isLabor && item.productSpecs ? `<div class="p-specs">${item.productSpecs}</div>` : ''}
                </div>
                <div class="popup-footer" onclick="window.navigateToDetail('${item.id}')">
                    ${btnText}
                </div>
            </div>
        `
    }

    function renderUserLocation() {
        const imageUrl = './static/images/local-map.png'
        map.addMarker('user-local', [model.userLocation.longitude, model.userLocation.latitude], '', false, imageUrl, [40, 40])
    }

    function renderEmploymentMarkers() {
        if (!map) return
        
        // 1. 先清空旧的 Marker
        clearMarkers()
        
        // 2. 渲染新的 Marker
        const points = []
        model.employmentList.forEach((item) => {
            const lon = model.currentEmploymentId == 2 ? item.lon : item.longitude
            const lat = model.currentEmploymentId == 2 ? item.lat : item.latitude
            if (lon && lat) {
                points.push([Number(lon), Number(lat)])
                let imageUrl = item.picture || './static/images/linghuoyonggong/default-icon.png'
                // #ifdef APP-PLUS
                if (imageUrl.startsWith('/static/')) imageUrl = `.${imageUrl}`
                // #endif
                const markerId = `emp-${item.id}`
                map.addMarker(markerId, [Number(lon), Number(lat)], createPopupHTML(item), false, imageUrl, [42, 42])
                model.markerIds.push(markerId)
            }
        })

        // 3. 自动调整地图视角
        fitMapToMarkers(points)
    }

    function clearMarkers() {
        if (!map || !model.markerIds.length) return
        model.markerIds.forEach(id => map.removeMarker(id))
        model.markerIds = []
    }

    function fitMapToMarkers(points) {
        if (!map) return
        
        if (points.length === 0) {
            // 如果没有点位，平滑回到用户当前位置
            backToUserLocation()
            return
        }
        
        if (points.length === 1) {
            map.flyTo({ center: points[0], zoom: 14, speed: 0.8 })
        } else {
            const features = points.map(p => turf.point(p))
            const collection = turf.featureCollection(features)
            const bbox = turf.bbox(collection)
            // 自动缩放视角以包含所有点位
            map.fitBounds([[bbox[0], bbox[1]], [bbox[2], bbox[3]]], {
                padding: 120, // 增加边距，确保边缘点位不被遮挡
                maxZoom: 16,
                duration: 1200
            })
        }
    }

    function onCategoryTabClick(tab: any) {
        model.search.type = tab.id
        model.search.pageNo = 1
        model.employmentList = []
        // 切换类型时立即清空地图上的点位，提供即时反馈
        clearMarkers()
        getEmploymentList()
    }

    function onSearch() {
        if (model.currentEmploymentId == 1) {
            model.search.createBy = model.searchText
        } else {
            model.search.keyword = model.searchText
        }
        model.search.pageNo = 1
        model.employmentList = []
        getEmploymentList()
    }

    function onListModeClick() {
        uni.navigateBack()
    }

    async function getEmploymentList() {
        model.loading = true
        try {
            const api = model.currentEmploymentId == 2 ? LinghuoyonggongAPI.getLaborAppList : LinghuoyonggongAPI.employmentList
            const res = await api(model.search)
            const { records, total } = res
            model.employmentList = records.map(item => {
                item.area = getText(item.area || item.scope, ' / ')
                return item
            })
            model.total = total
            // 数据到达后：如果地图已就绪则立即渲染，否则等 onLoaded 回调时再渲染
            if (mapReady) {
                renderEmploymentMarkers()
            }
        } finally {
            model.loading = false
        }
    }

    function backToUserLocation() {
        console.log('backToUserLocation clicked', model.userLocation)
        if (!model.userLocation.longitude) {
            uni.showToast({ title: '尚未获取到定位信息', icon: 'none' })
            return
        }
        if (map) {
            // 直接调用包装好的 flyTo 方法，确保参数正确
            map.flyTo({
                center: [model.userLocation.longitude, model.userLocation.latitude],
                zoom: 14,
                essential: true,
                speed: 0.8
            })
        }
    }

    function getDistanceText2(item) {
        if (!item.lon || !model.userLocation.longitude) return '未知'
        const d = turf.distance(turf.point([model.userLocation.longitude, model.userLocation.latitude]), turf.point([item.lon, item.lat]), { units: 'kilometers' })
        return d < 1 ? `${Math.round(d * 1000)}m` : `${d.toFixed(1)}km`
    }

    function getDistanceText(item) {
        if (!item.longitude || !model.userLocation.longitude) return '未知'
        const d = turf.distance(turf.point([model.userLocation.longitude, model.userLocation.latitude]), turf.point([item.longitude, item.latitude]), { units: 'kilometers' })
        return d < 1 ? `${Math.round(d * 1000)}m` : `${d.toFixed(1)}km`
    }
</script>

<template>
    <view class="page map-mode">
        <!-- 顶部悬浮搜索与筛选 -->
        <view class="floating-top-bar">
            <view class="search-inner">
                <fui-icon name="search" color="#999" :size="32"></fui-icon>
                <input class="search-input" v-model="model.searchText" placeholder="搜地点、技能..." placeholder-style="color:#ccc" @confirm="onSearch" />
            </view>
            <scroll-view scroll-x class="tab-scroll">
                <view class="tabs-row">
                    <view
                        v-for="tab in model.categoryTabs"
                        :key="tab.id"
                        class="tab-pill"
                        :class="{ active: tab.id === model.search.type }"
                        @tap="onCategoryTabClick(tab)"
                    >
                        {{ tab.name }}
                    </view>
                </view>
            </scroll-view>
        </view>

        <!-- 地图容器 -->
        <view class="map-container">
            <Mapbox @register="registerMap" />
            
            <!-- 悬浮控制按钮组 -->
            <view class="map-ctrl-group">
                <view class="map-ctrl location" @click="backToUserLocation">
                    <fui-icon name="location" color="#5db66f" :size="28"></fui-icon>
                    <text class="ctrl-text">定位</text>
                </view>
                <view class="map-ctrl list-btn" @click="onListModeClick">
                    <fui-icon name="list" color="#fff" :size="28"></fui-icon>
                    <text class="ctrl-text">列表</text>
                </view>
            </view>
        </view>

        <RegisterDialog ref="registerDialogRef" />
        <ConfirmDialog
            v-model:show="model.showConfirmDialog"
            title="拨号确认"
            :content="`确认拨打负责人【${model.contactName}】的电话吗？`"
            @confirm="makePhoneCall"
        />
    </view>
</template>

<style lang="scss" scoped>
    .page.map-mode {
        height: 100vh;
        background-color: #f0f4f2;
        font-family: 'DingTalk Sans', sans-serif;
        position: relative;
        overflow: hidden;
    }

    .floating-top-bar {
        position: absolute;
        top: calc(env(safe-area-inset-top) + 20rpx);
        left: 30rpx;
        right: 30rpx;
        z-index: 100;
        
        .search-inner {
            background-color: rgba(255, 255, 255, 0.95);
            backdrop-filter: blur(10px);
            height: 88rpx;
            border-radius: 44rpx;
            display: flex;
            align-items: center;
            padding: 0 32rpx;
            box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.08);
            .search-input {
                flex: 1;
                margin-left: 16rpx;
                font-size: 28rpx;
                color: #333;
            }
        }

        .tab-scroll {
            margin-top: 20rpx;
            width: 100%;
            .tabs-row {
                display: flex;
                padding-bottom: 10rpx;
                .tab-pill {
                    flex-shrink: 0;
                    padding: 10rpx 32rpx;
                    background-color: rgba(255, 255, 255, 0.9);
                    backdrop-filter: blur(8px);
                    border-radius: 30rpx;
                    font-size: 24rpx;
                    color: #666;
                    margin-right: 16rpx;
                    box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05);
                    &.active {
                        background-color: #5db66f;
                        color: #fff;
                        font-weight: bold;
                    }
                }
            }
        }
    }

    .map-container {
        width: 100%;
        height: 100vh;
        position: relative;
    }

    .map-ctrl-group {
        position: absolute;
        right: 24rpx;
        bottom: 100rpx;
        display: flex;
        flex-direction: column;
        gap: 16rpx;
        z-index: 200;

        .map-ctrl {
            position: relative;
            width: 88rpx;
            height: 88rpx;
            background-color: #fff;
            border-radius: 50%;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.15);
            transition: all 0.2s;

            &:active {
                transform: scale(0.92);
            }

            .ctrl-text {
                font-size: 18rpx;
                color: #fff;
                margin-top: 2rpx;
            }

            &.location {
                .ctrl-text {
                    color: #5db66f;
                }
            }

            &.list-btn {
                width: 100rpx;
                height: 100rpx;
                background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
                box-shadow: 0 6rpx 20rpx rgba(24, 144, 255, 0.4);
            }
        }
    }

    /* Mapbox 弹窗样式重写 */
    :deep(.mapboxgl-popup-content) {
        padding: 0 !important;
        border-radius: 24rpx !important;
        overflow: hidden;
        box-shadow: 0 10rpx 30rpx rgba(0,0,0,0.15) !important;
    }
    :deep(.mapboxgl-popup-close-button) {
        color: #999 !important;
        font-size: 40rpx !important;
        padding: 10rpx !important;
        right: 10rpx !important;
        top: 10rpx !important;
    }

    /* 自定义弹窗卡片 CSS */
    :deep(.map-popup-card) {
        width: 480rpx;
        background: #fff;
        .popup-header {
            padding: 24rpx 24rpx 16rpx;
            background: linear-gradient(to bottom, #f8fbf9, #fff);
            .popup-title-row {
                display: flex; justify-content: space-between; align-items: center;
                .p-title { font-size: 32rpx; font-weight: bold; color: #1a1a1a; }
                .p-dist { font-size: 22rpx; color: #5db66f; font-weight: bold; }
            }
            .p-subtitle { font-size: 22rpx; color: #94a3b8; margin-top: 8rpx; }
        }
        .popup-body {
            padding: 0 24rpx 24rpx;
            .p-stats { font-size: 24rpx; color: #475569; font-weight: 500; }
            .p-specs { font-size: 22rpx; color: #94a3b8; margin-top: 8rpx; padding: 12rpx; background: #f1f5f9; border-radius: 8rpx; }
        }
        .popup-footer {
            height: 88rpx;
            background-color: #5db66f;
            color: #fff;
            display: flex; align-items: center; justify-content: center;
            font-size: 28rpx; font-weight: bold;
            &:active { opacity: 0.9; }
        }
    }
</style>
