<template>
  <div class="dispatch-container">
    <!-- Top Filter Bar -->
    <div class="top-filter-bar glass-panel-sm">
      <div class="filter-left">
        <el-radio-group v-model="filters.orderType" size="default" fill="#2d8cf0">
          <el-radio-button label="all">全部</el-radio-button>
          <el-radio-button label="transport">宠物接送</el-radio-button>
          <el-radio-button label="feeding">上门喂遛</el-radio-button>
          <el-radio-button label="washing">上门洗护</el-radio-button>
        </el-radio-group>
      </div>
      <div class="filter-right">
        <el-select v-model="filters.city" placeholder="选择城市" style="width: 120px; margin-right: 10px">
          <el-option label="北京市" value="beijing" />
          <el-option label="上海市" value="shanghai" />
        </el-select>
        <el-select v-model="filters.station" placeholder="选择站点" style="width: 140px">
          <el-option label="朝阳大悦城站" value="cy" />
          <el-option label="国贸核心站" value="gm" />
        </el-select>
      </div>
    </div>

    <div class="main-content">
      <!-- Left: Real Baidu Map Area -->
      <div class="map-wrapper">
        <div id="baidu-map" class="map-view"></div>

        <!-- Bottom Left: Map Controls & Stats -->
        <div class="map-controls-panel">
          <div class="control-group">
            <div class="c-btn" :class="{ active: activeMapFilter === 'all' }" @click="setMapFilter('all')">全部</div>
            <div class="c-btn red" :class="{ active: activeMapFilter === 'merchants' }" @click="setMapFilter('merchants')">商家(16)</div>
            <div class="c-btn green" :class="{ active: activeMapFilter === 'fulfillers' }" @click="setMapFilter('fulfillers')">履约者(12)</div>
            <div class="c-btn blue" :class="{ active: activeMapFilter === 'orders' }" @click="setMapFilter('orders')">订单(5)</div>
            <div class="c-btn gray">灰色表示离线</div>
          </div>
        </div>
      </div>

      <!-- Right: Dispatch Control Panel -->
      <div class="right-panel">
        <!-- 1. Order Management Section -->
        <div class="panel-section order-mgmt">
          <div class="sec-header">
            <span class="tit">订单</span>
            <!-- Right Aligned Tabs -->
            <div class="header-right-tabs">
              <span class="h-tab-item" :class="{ active: currentOrderTab === 'PendingDispatch' }" @click="currentOrderTab = 'PendingDispatch'">
                <span class="txt">待派单</span>
                <span class="num danger">{{ orderStats.pendingDispatch }}</span>
              </span>
              <span class="h-tab-item" :class="{ active: currentOrderTab === 'PendingAccept' }" @click="currentOrderTab = 'PendingAccept'">
                <span class="txt">待接单</span>
                <span class="num warning">{{ orderStats.pendingAccept }}</span>
              </span>
              <span class="h-tab-item" :class="{ active: currentOrderTab === 'Processing' }" @click="currentOrderTab = 'Processing'">
                <span class="txt">进行中</span>
                <span class="num primary">{{ orderStats.processing }}</span>
              </span>
            </div>
          </div>

          <!-- Order List -->
          <div class="list-wrapper">
            <el-scrollbar>
              <div v-if="filteredOrders.length === 0" class="empty-state">暂无数据</div>
              <div v-else v-for="order in filteredOrders" :key="order.id" class="list-card order-card" @click="focusMapPoint(order.lng, order.lat)">
                <div class="card-left">
                  <div class="type-tag" :class="order.typeCode">
                    {{ getShortType(order.typeCode) }}
                  </div>
                </div>
                <div class="card-main">
                  <template v-if="order.typeCode === 'transport'">
                    <div class="row-addr" :title="order.pickAddr"><span class="tag pick">取</span> {{ order.pickAddr }}</div>
                    <div class="row-addr" :title="order.dropAddr"><span class="tag drop">送</span> {{ order.dropAddr }}</div>
                    <div class="row-time">
                      <el-icon><Clock /></el-icon> {{ order.time }}
                      <span class="days-tag" v-if="order.daysLater">{{ order.daysLater }}</span>
                    </div>
                  </template>
                  <template v-else>
                    <div class="row-addr" :title="order.address"><span class="tag home">址</span> {{ order.address }}</div>
                    <div class="row-time" style="margin-top: 4px">
                      <el-icon><Clock /></el-icon> {{ order.time }}
                      <span class="days-tag" v-if="order.daysLater">{{ order.daysLater }}</span>
                    </div>
                  </template>
                </div>

                <!-- Right: Status & Actions -->
                <div class="card-right">
                  <el-tag size="small" :type="getOrderStatusType(order.status)" effect="plain">{{ getOrderStatusText(order.status) }}</el-tag>
                  <div class="actions">
                    <el-button v-if="order.status === 'pending_dispatch'" type="primary" size="small" @click.stop="openDispatchDialog(order)"
                      >派单</el-button
                    >
                    <el-button
                      v-else-if="['pending_accept', 'processing'].includes(order.status)"
                      type="primary"
                      size="small"
                      plain
                      @click.stop="openDispatchDialog(order)"
                      >重新派单</el-button
                    >
                  </div>
                </div>
              </div>
            </el-scrollbar>
          </div>
        </div>

        <!-- 2. Fulfiller Management Section -->
        <div class="panel-section fulfiller-mgmt">
          <div class="sec-header no-border">
            <span class="tit">履约者</span>
            <!-- Right Aligned Tabs -->
            <div class="header-right-tabs">
              <span class="h-tab-item" :class="{ active: currentRiderTab === 'All' }" @click="currentRiderTab = 'All'">
                <span class="txt">全部</span>
                <span class="num">12</span>
              </span>
              <span class="h-tab-item" :class="{ active: currentRiderTab === 'Working' }" @click="currentRiderTab = 'Working'">
                <span class="txt">接单中</span>
                <span class="num success">8</span>
              </span>
              <span class="h-tab-item" :class="{ active: currentRiderTab === 'Resting' }" @click="currentRiderTab = 'Resting'">
                <span class="txt">休息中</span>
                <span class="num info">3</span>
              </span>
              <span class="h-tab-item" :class="{ active: currentRiderTab === 'Disabled' }" @click="currentRiderTab = 'Disabled'">
                <span class="txt">禁用</span>
                <span class="num danger">1</span>
              </span>
            </div>
          </div>

          <!-- Rider List -->
          <div class="list-wrapper">
            <el-scrollbar>
              <div v-for="rider in filteredRiders" :key="rider.id" class="list-card rider-card" @click="focusMapPoint(rider.lng, rider.lat)">
                <div class="card-left relative">
                  <el-avatar :src="rider.avatar" :size="40" />
                  <div class="dot" :class="rider.status"></div>
                </div>
                <div class="card-main">
                  <!-- Box 1: Name + Phone + Status (Right) -->
                  <div class="row-1" style="justify-content: space-between; align-items: flex-start">
                    <div style="display: flex; align-items: baseline; gap: 8px">
                      <span class="r-name">{{ rider.name }}</span>
                      <span class="r-phone">{{ rider.maskPhone }}</span>
                    </div>
                    <div class="status-right">
                      <span class="status-badge" :class="rider.status">{{ getRiderStatusText(rider.status) }}</span>
                    </div>
                  </div>

                  <!-- Box 2: Categories -->
                  <div class="row-2 categories-row" style="margin-top: 6px; display: flex; gap: 4px; flex-wrap: wrap">
                    <span v-for="cat in rider.categories" :key="cat" class="cat-tag" :class="getCategoryClass(cat)">{{ cat }}</span>
                  </div>

                  <!-- Box 3: Last Service Time -->
                  <div class="row-3 time-row" style="margin-top: 4px">
                    <span class="last-time"
                      >下一单: {{ rider.status === 'offline' || rider.status === 'disabled' ? '--' : rider.lastServiceTime }}</span
                    >
                  </div>
                </div>
                <div class="card-right-stats">
                  <div class="stat-box">
                    <span class="lbl">待接</span>
                    <span class="val danger">{{ rider.pendingCount }}</span>
                  </div>
                  <div class="stat-box">
                    <span class="lbl">待服</span>
                    <span class="val warning">{{ rider.todoCount }}</span>
                  </div>
                  <el-button link type="primary" size="small" style="margin-top: 4px; padding: 0" @click.stop="handleViewRiderOrders(rider)"
                    >查看订单</el-button
                  >
                </div>
              </div>
            </el-scrollbar>
          </div>
        </div>
      </div>
    </div>

    <!-- Rider Orders Dialog -->
    <el-dialog v-model="riderOrdersVisible" title="履约者订单详情" width="1100px" top="6vh" custom-class="rider-orders-dialog">
      <div class="dialog-content">
        <!-- 1. Rider Summary Info -->
        <div class="rider-summary" v-if="currentRiderInfo">
          <div class="summary-item">
            <span class="lbl">姓名：</span>
            <span class="val bold">{{ currentRiderInfo.name }}</span>
          </div>
          <div class="summary-item">
            <span class="lbl">手机号：</span>
            <span class="val">{{ currentRiderInfo.maskPhone }}</span>
          </div>
          <div class="summary-item">
            <span class="lbl">所属区域：</span>
            <span class="val">{{ currentRiderInfo.station }}</span>
          </div>
          <div class="summary-item">
            <span class="lbl">工作类型：</span>
            <span class="val">{{ currentRiderInfo.workType }}</span>
          </div>
          <div class="summary-item" style="flex: 1">
            <span class="lbl">服务类目：</span>
            <el-tag v-for="tag in currentRiderInfo.categories" :key="tag" size="small" effect="plain" style="margin-right: 4px">{{ tag }}</el-tag>
          </div>
        </div>

        <!-- 2. Orders Table -->
        <div class="rider-orders-list">
          <el-table :data="currentRiderOrders" stripe style="width: 100%" :header-cell-style="{ background: '#f5f7fa', color: '#606266' }">
            <el-table-column prop="orderNo" label="订单号" width="150" />
            <el-table-column prop="serviceName" label="服务项目" width="120" show-overflow-tooltip />
            <el-table-column prop="petName" label="服务宠物" width="100" />
            <el-table-column prop="customerName" label="客户" width="100" />
            <el-table-column prop="address" label="服务详细地址" min-width="200" show-overflow-tooltip />
            <el-table-column prop="time" label="预约时间" width="160" />
            <el-table-column label="状态" width="100">
              <template #default="{ row }">
                <el-tag v-if="row.status === 'pending_accept'" type="warning" size="small">待接单</el-tag>
                <el-tag v-else-if="row.status === 'pending_service'" type="primary" size="small">待服务</el-tag>
                <el-tag v-else type="info" size="small">{{ row.status }}</el-tag>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </div>
    </el-dialog>

    <!-- Dispatch Dialog -->
    <el-dialog v-model="dispatchDialogVisible" title="派单调度" width="900px" top="5vh" destroy-on-close append-to-body>
      <div class="dispatch-dialog-content">
        <!-- Top: Order Info -->
        <div class="dispatch-order-info box-card" v-if="currentDispatchOrder">
          <div class="list-card order-card" style="margin: 0; box-shadow: none; cursor: default; border: none">
            <div class="card-left">
              <div class="type-tag" :class="currentDispatchOrder.typeCode">
                {{ getShortType(currentDispatchOrder.typeCode) }}
              </div>
            </div>
            <div class="card-main">
              <template v-if="currentDispatchOrder.typeCode === 'transport'">
                <div class="row-addr" :title="currentDispatchOrder.pickAddr">
                  <span class="tag pick">取</span> {{ currentDispatchOrder.pickAddr }}
                </div>
                <div class="row-addr" :title="currentDispatchOrder.dropAddr">
                  <span class="tag drop">送</span> {{ currentDispatchOrder.dropAddr }}
                </div>
              </template>
              <template v-else>
                <div class="row-addr" :title="currentDispatchOrder.address"><span class="tag home">址</span> {{ currentDispatchOrder.address }}</div>
              </template>
              <div class="row-time" style="margin-top: 4px">
                <el-icon><Clock /></el-icon> {{ currentDispatchOrder.time }}
                <span class="days-tag" v-if="currentDispatchOrder.daysLater">{{ currentDispatchOrder.daysLater }}</span>
              </div>
            </div>
          </div>
        </div>

        <!-- Current Rider Info (For Re-dispatch) -->
        <div class="current-rider-section" v-if="currentRider">
          <div class="select-header" style="margin-bottom: 8px">
            <span class="tit">当前派单履约者</span>
          </div>
          <div class="list-card rider-card" style="margin-bottom: 20px; border: 1px solid #e4e7ed; background: #fafafa; cursor: default">
            <!-- Reusing Rider Card Layout -->
            <div class="card-left relative">
              <el-avatar :src="currentRider.avatar" :size="40" />
              <div class="dot" :class="currentRider.status"></div>
            </div>
            <div class="card-main">
              <div class="row-1" style="justify-content: space-between; align-items: flex-start">
                <div style="display: flex; align-items: baseline; gap: 8px">
                  <span class="r-name">{{ currentRider.name }}</span>
                  <span class="r-phone">{{ currentRider.maskPhone }}</span>
                </div>
                <div class="status-right">
                  <span class="status-badge" :class="currentRider.status">{{ getRiderStatusText(currentRider.status) }}</span>
                </div>
              </div>

              <div class="row-2 categories-row" style="margin-top: 6px; display: flex; gap: 4px; flex-wrap: wrap">
                <span v-for="cat in currentRider.categories" :key="cat" class="cat-tag" :class="getCategoryClass(cat)">{{ cat }}</span>
              </div>

              <div class="row-3 time-row" style="margin-top: 4px">
                <span class="last-time"
                  >下一单: {{ currentRider.status === 'offline' || currentRider.status === 'disabled' ? '--' : currentRider.lastServiceTime }}</span
                >
              </div>
            </div>
          </div>
        </div>

        <!-- Middle: Rider Selection -->
        <div class="dispatch-rider-select">
          <div class="select-header">
            <span class="tit">选择履约者 (下一单时间由近及远排序)</span>
            <el-input v-model="dispatchSearchQuery" placeholder="搜索履约者姓名/手机号" prefix-icon="Search" clearable style="width: 240px" />
          </div>

          <div class="rider-grid-wrapper">
            <el-scrollbar height="400px">
              <div class="rider-grid">
                <div
                  v-for="rider in filteredDispatchRiders"
                  :key="rider.id"
                  class="list-card rider-card select-card"
                  :class="{ active: selectedRiderId === rider.id }"
                  @click="selectedRiderId = rider.id"
                >
                  <!-- Reusing Rider Card Layout -->
                  <div class="card-left relative">
                    <el-avatar :src="rider.avatar" :size="40" />
                    <div class="dot" :class="rider.status"></div>
                  </div>
                  <div class="card-main">
                    <div class="row-1" style="justify-content: space-between; align-items: flex-start">
                      <div style="display: flex; align-items: baseline; gap: 8px">
                        <span class="r-name">{{ rider.name }}</span>
                        <span class="r-phone">{{ rider.maskPhone }}</span>
                      </div>
                      <div class="status-right">
                        <span class="status-badge" :class="rider.status">{{ getRiderStatusText(rider.status) }}</span>
                      </div>
                    </div>

                    <div class="row-2 categories-row" style="margin-top: 6px; display: flex; gap: 4px; flex-wrap: wrap">
                      <span v-for="cat in rider.categories" :key="cat" class="cat-tag" :class="getCategoryClass(cat)">{{ cat }}</span>
                    </div>

                    <div class="row-3 time-row" style="margin-top: 4px">
                      <span class="last-time"
                        >下一单: {{ rider.status === 'offline' || rider.status === 'disabled' ? '--' : rider.lastServiceTime }}</span
                      >
                    </div>
                  </div>

                  <!-- Selected Check -->
                  <div class="selected-mark" v-if="selectedRiderId === rider.id">
                    <el-icon><Check /></el-icon>
                  </div>
                </div>

                <div v-if="filteredDispatchRiders.length === 0" class="empty-text">暂无符合条件的履约者</div>
              </div>
            </el-scrollbar>
          </div>
        </div>

        <!-- Bottom: Fee & Submit -->
        <div class="dispatch-footer">
          <div class="fee-input">
            <span class="label">服务费用：</span>
            <el-input-number v-model="dispatchFee" :min="0" :precision="2" :step="10" placeholder="请输入" style="width: 140px" />
            <span class="unit">元</span>
          </div>
          <div class="btns">
            <el-button @click="dispatchDialogVisible = false">取消</el-button>
            <el-button type="primary" @click="handleDispatchSubmit">确认派单</el-button>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed, reactive, onMounted, watch } from 'vue';
import { ElMessage } from 'element-plus';

// --- Data & State ---
const riderOrdersVisible = ref(false);
const currentRiderOrders = ref([]);
const currentRiderInfo = ref(null);

const handleViewRiderOrders = (rider) => {
  // Mock Rider Info
  currentRiderInfo.value = {
    name: rider.name,
    maskPhone: rider.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2'),
    station: rider.station + ' - 东城片区',
    workType: '全职专送',
    categories: ['宠物接送', '上门喂遛', '洗护套餐']
  };

  // Mock Data for specific rider
  currentRiderOrders.value = [
    {
      orderNo: 'ORD20240205001',
      serviceName: '上门喂遛',
      petName: '金毛(大黄)',
      customerName: '张先生',
      address: '北京市朝阳区三里屯SOHO A座 1202',
      time: '2024-02-05 14:00',
      status: 'pending_accept'
    },
    {
      orderNo: 'ORD20240205002',
      serviceName: '宠物接送',
      petName: '布偶(咪咪)',
      customerName: '李女士',
      address: '北京市朝阳区国贸三期 35层',
      time: '2024-02-05 16:30',
      status: 'pending_service'
    },
    {
      orderNo: 'ORD20240205003',
      serviceName: '洗护套餐',
      petName: '泰迪(可乐)',
      customerName: '王小姐',
      address: '北京市海淀区中关村软件园 5号楼',
      time: '2024-02-06 10:00',
      status: 'pending_service'
    }
  ];
  riderOrdersVisible.value = true;
};
const filters = reactive({
  orderType: 'all',
  city: 'beijing',
  station: 'cy'
});

const currentOrderTab = ref('PendingDispatch');
const currentRiderTab = ref('All');
const activeMapFilter = ref('all');

// Mock Stats
const orderStats = reactive({
  pendingDispatch: 3,
  pendingAccept: 4,
  processing: 8,
  delivering: 2,
  merchants: 16
});

// Real Params (Beijing Chaoyang Area)
// Center: 116.4551, 39.9255

// Mock Orders Data (With Real Coords)
const ordersList = ref([
  {
    id: 1,
    type: '宠物接送',
    typeCode: 'transport',
    status: 'pending_dispatch',
    pickAddr: '北京市朝阳区三里屯SOHO A座',
    dropAddr: '北京市朝阳区朝阳大悦城',
    time: '2024-02-07 14:30',
    daysLater: '今天',
    lng: 116.4552,
    lat: 39.9338
  },
  {
    id: 2,
    type: '上门喂遛',
    typeCode: 'feeding',
    status: 'pending_accept',
    address: '北京市海淀区中关村软件园',
    riderId: 101,
    time: '2024-02-08 15:00',
    daysLater: '明天',
    lng: 116.298,
    lat: 40.044
  },
  {
    id: 3,
    type: '上门洗护',
    typeCode: 'washing',
    status: 'processing',
    address: '北京市朝阳区望京SOHO T3',
    riderId: 102,
    time: '2024-02-07 10:00',
    daysLater: '进行中',
    lng: 116.486,
    lat: 39.998
  },
  {
    id: 4,
    type: '宠物接送',
    typeCode: 'transport',
    status: 'completed',
    pickAddr: '北京市通州区万达广场',
    dropAddr: '北京市通州区北苑',
    time: '2024-02-06 09:00',
    daysLater: '',
    lng: 116.643,
    lat: 39.905
  },
  {
    id: 5,
    type: '上门喂遛',
    typeCode: 'feeding',
    status: 'pending_dispatch',
    address: '北京市朝阳区朝阳公园南门',
    time: '2024-02-09 16:00',
    daysLater: '2天后',
    lng: 116.488,
    lat: 39.932
  },
  {
    id: 6,
    type: '宠物接送',
    typeCode: 'transport',
    status: 'pending_dispatch',
    pickAddr: '北京市朝阳区国贸三期',
    dropAddr: '北京市朝阳区双井富力城',
    time: '2024-02-07 16:30',
    daysLater: '今天',
    lng: 116.463,
    lat: 39.907
  }
]);

// Mock Riders Data (With Real Coords)
const ridersList = ref([
  {
    id: 101,
    name: '王大力',
    station: '朝阳站',
    phone: '13800138000',
    maskPhone: '138****8000',
    status: 'online',
    categories: ['接送', '喂遛'],
    lastServiceTime: '2024-02-07 11:00',
    avatar: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
    pendingCount: 0,
    todoCount: 2,
    lng: 116.46,
    lat: 39.92
  },
  {
    id: 102,
    name: '李小龙',
    station: '海淀站',
    phone: '13912345678',
    maskPhone: '139****5678',
    status: 'online',
    categories: ['接送', '洗护'],
    lastServiceTime: '2024-02-07 10:30',
    avatar: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png',
    pendingCount: 1,
    todoCount: 3,
    lng: 116.45,
    lat: 39.915
  },
  {
    id: 103,
    name: '张小美',
    station: '望京站',
    phone: '13666666666',
    maskPhone: '136****6666',
    status: 'online',
    categories: ['喂遛'],
    lastServiceTime: '2024-02-07 10:45',
    avatar: '',
    pendingCount: 0,
    todoCount: 0,
    lng: 116.47,
    lat: 39.93
  },
  {
    id: 104,
    name: '赵铁柱',
    station: '通州站',
    phone: '13555555555',
    maskPhone: '135****5555',
    status: 'offline',
    categories: ['接送'],
    lastServiceTime: '2024-02-06 18:00',
    avatar: '',
    pendingCount: 0,
    todoCount: 0,
    lng: 116.44,
    lat: 39.91
  },
  {
    id: 105,
    name: '孙悟空',
    station: '花果山',
    phone: '13888888888',
    maskPhone: '138****8888',
    status: 'online',
    categories: ['接送', '喂遛', '洗护'],
    lastServiceTime: '2024-02-07 09:30',
    avatar: '',
    pendingCount: 0,
    todoCount: 1,
    lng: 116.48,
    lat: 39.925
  }
]);

// Mock Merchants (Static Coords)
const merchantList = ref([
  { id: 201, name: '萌它宠物', orders: 5, lng: 116.453, lat: 39.923, icon: '' },
  { id: 202, name: '宠爱国际', orders: 0, lng: 116.465, lat: 39.928, icon: '' },
  { id: 203, name: '顽皮狗', orders: 8, lng: 116.448, lat: 39.918, icon: '' }
]);

// --- Map Logic ---
let map = null;
const ak = 'E4805d16520de693a3fe707cdc962045'; // Public Key

const loadBMapScript = () => {
  return new Promise((resolve, reject) => {
    if (window.BMap) {
      resolve(window.BMap);
      return;
    }
    window.initBMapCallback = () => resolve(window.BMap);
    const script = document.createElement('script');
    script.src = `https://api.map.baidu.com/api?v=3.0&ak=${ak}&callback=initBMapCallback`;
    script.onerror = reject;
    document.head.appendChild(script);
  });
};

const initMap = () => {
  if (!window.BMap) return;
  map = new BMap.Map('baidu-map');
  const point = new BMap.Point(116.4551, 39.9255); // Chaoyang center
  map.centerAndZoom(point, 14);
  map.enableScrollWheelZoom(true);
  map.setMapStyleV2({
    styleId: '3d71dc5a4ce6228d3e9680188e982438'
  });

  refreshMarkers();
};

const refreshMarkers = () => {
  if (!map) return;
  map.clearOverlays();

  const filter = activeMapFilter.value;

  // 1. Merchants
  if (filter === 'all' || filter === 'merchants') {
    merchantList.value.forEach((m) => {
      const pt = new BMap.Point(m.lng, m.lat);
      const iconImg = m.icon || 'https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png';

      const html = `
            <div style="position:absolute; transform:translate(-50%, -100%); width: 220px; filter: drop-shadow(0 4px 10px rgba(0,0,0,0.2));">
                <div style="background:#fff; border-radius:8px; padding: 12px; display: flex; align-items: center; gap: 10px; position: relative;">
                     <!-- Close Icon -->
                    <div style="position: absolute; top: 4px; right: 8px; color: #999; font-size: 16px; cursor: pointer;">×</div>

                    <!-- Icon Ring -->
                    <div style="width: 48px; height: 48px; border-radius: 50%; border: 4px solid #F56C6C; padding: 2px; flex-shrink: 0; box-sizing: border-box; display: flex; align-items: center; justify-content: center;">
                         <img src="${iconImg}" style="width: 100%; height: 100%; border-radius: 50%; object-fit: cover;">
                    </div>

                    <!-- Info -->
                    <div style="flex: 1; overflow: hidden;">
                        <div style="font-weight: bold; font-size: 14px; color: #333; margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">${m.name}</div>
                        <div style="font-size: 12px; color: #666;">今日 <span style="color: #F56C6C; font-weight: bold; font-size: 14px;">${m.orders}</span> 单</div>
                    </div>
                </div>
                <!-- Triangle -->
                <div style="width: 0; height: 0; border-left: 8px solid transparent; border-right: 8px solid transparent; border-top: 10px solid #fff; margin: 0 auto;"></div>
            </div>
            `;

      const label = new BMap.Label(html, { position: pt, offset: new BMap.Size(0, 0) });
      label.setStyle({ border: 'none', background: 'transparent' });
      map.addOverlay(label);
    });
  }

  // 2. Fulfiller
  if (filter === 'all' || filter === 'fulfillers') {
    ridersList.value.forEach((r) => {
      const pt = new BMap.Point(r.lng, r.lat);
      const borderColor = r.status === 'online' ? '#67C23A' : r.status === 'busy' ? '#409EFF' : '#DCDFE6';
      const pendingText =
        r.pendingCount > 0 ? `<span style="color:#67C23A;font-weight:bold;">挂${r.pendingCount}单</span>` : `<span style="color:#999;">挂0单</span>`;
      const avatar = r.avatar || 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png';

      const html = `
            <div style="position:absolute; transform:translate(-50%, -100%); width: 200px; filter: drop-shadow(0 4px 10px rgba(0,0,0,0.2));">
                <div style="background:#fff; border-radius:8px; padding: 10px; display: flex; align-items: center; gap: 10px; position: relative;">
                    <!-- Close Icon -->
                    <div style="position: absolute; top: 2px; right: 6px; color: #999; font-size: 14px; cursor: pointer;">×</div>

                    <!-- Avatar Ring -->
                    <div style="width: 44px; height: 44px; border-radius: 50%; border: 3px solid ${borderColor}; padding: 1px; flex-shrink: 0; box-sizing: border-box;">
                        <img src="${avatar}" style="width: 100%; height: 100%; border-radius: 50%; object-fit: cover;">
                    </div>

                    <!-- Info -->
                    <div style="flex: 1; overflow: hidden;">
                        <div style="font-weight: bold; font-size: 13px; color: #333; margin-bottom: 2px;">[履约者]${r.name}</div>
                        <div style="font-size: 12px; color: #999;">${pendingText}</div>
                    </div>
                </div>
                 <!-- Triangle -->
                <div style="width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 8px solid #fff; margin: 0 auto;"></div>
            </div>
            `;

      const label = new BMap.Label(html, { position: pt, offset: new BMap.Size(0, 0) });
      label.setStyle({ border: 'none', background: 'transparent' });
      map.addOverlay(label);
    });
  }

  // 3. Orders (Blue/Purple)
  if (filter === 'all' || filter === 'orders') {
    filteredOrders.value.forEach((o) => {
      const pt = new BMap.Point(o.lng, o.lat);
      const marker = new BMap.Marker(pt);

      const labelContent = `<div style="border:1px solid #409EFF;background:#fff;color:#409EFF;padding:2px 6px;border-radius:4px;font-size:12px;">${o.type}</div>`;
      const label = new BMap.Label(labelContent, { position: pt, offset: new BMap.Size(-20, -35) });
      label.setStyle({ border: 'none', background: 'transparent' });

      map.addOverlay(marker);
      map.addOverlay(label);
    });
  }
};

const setMapFilter = (val) => {
  activeMapFilter.value = val;
};

const focusMapPoint = (lng, lat) => {
  if (!map) return;
  const pt = new BMap.Point(lng, lat);
  map.panTo(pt);
  map.setZoom(16);
};

watch(activeMapFilter, () => {
  refreshMarkers();
});

// Also refresh when tab changes if logic depends on it (e.g. only showing active orders)
watch([currentOrderTab, currentRiderTab], () => {
  refreshMarkers();
});

onMounted(() => {
  loadBMapScript()
    .then(() => {
      initMap();
    })
    .catch((err) => {
      console.error('Map loading failed', err);
      ElMessage.error('地图加载失败，请检查网络');
    });
});

const dispatchDialogVisible = ref(false);
const currentDispatchOrder = ref(null);
const currentRider = ref(null);
const dispatchSearchQuery = ref('');
const selectedRiderId = ref(null);
const dispatchFee = ref(0);

const openDispatchDialog = (order) => {
  currentDispatchOrder.value = order;
  dispatchDialogVisible.value = true;
  dispatchSearchQuery.value = '';
  selectedRiderId.value = null;
  dispatchFee.value = 0;

  // Find current rider for re-dispatch
  if (order.riderId) {
    currentRider.value = ridersList.value.find((r) => r.id === order.riderId) || null;
  } else {
    currentRider.value = null;
  }
};

const filteredDispatchRiders = computed(() => {
  // User said "Select Accepting Riders". Usually means "Online/Busy".
  // But the main list logic for "Working" includes online and busy.
  // Let's filter for riders who are NOT disabled or offline?
  // Or just show all eligible. Let's show 'online' and 'busy'.
  let result = ridersList.value.filter((r) => r.status === 'online' || r.status === 'busy');

  if (dispatchSearchQuery.value) {
    const q = dispatchSearchQuery.value.toLowerCase();
    result = result.filter((r) => r.name.includes(q) || r.phone.includes(q));
  }
  // Sort by Next Order Time
  // Mock sort: just string compare for now since format is YYYY-MM-DD HH:mm
  result.sort((a, b) => {
    return a.lastServiceTime.localeCompare(b.lastServiceTime);
  });
  return result;
});

const handleDispatchSubmit = () => {
  if (!selectedRiderId.value) {
    ElMessage.warning('请选择履约者');
    return;
  }
  if (!dispatchFee.value) {
    ElMessage.warning('请输入服务费用');
    return;
  }
  dispatchDialogVisible.value = false;
  ElMessage.success('派单成功');

  // update status locally
  if (currentDispatchOrder.value && currentDispatchOrder.value.status === 'pending_dispatch') {
    const idx = ordersList.value.findIndex((o) => o.id === currentDispatchOrder.value.id);
    if (idx !== -1) ordersList.value[idx].status = 'pending_accept';
  }
};
const filteredOrders = computed(() => {
  let result = ordersList.value;
  // Tab Filter
  const statusMap = {
    'PendingDispatch': 'pending_dispatch',
    'PendingAccept': 'pending_accept',
    'Processing': 'processing'
  };
  const targetStatus = statusMap[currentOrderTab.value];
  if (targetStatus) {
    result = result.filter((o) => o.status === targetStatus);
  }
  // Type Filter
  if (filters.orderType !== 'all') {
    result = result.filter((o) => o.typeCode === filters.orderType);
  }
  return result;
});

const filteredRiders = computed(() => {
  if (currentRiderTab.value === 'All') return ridersList.value;
  const map = {
    'Working': ['online', 'busy'],
    'Resting': ['offline'],
    'Disabled': ['disabled']
  };
  const allowed = map[currentRiderTab.value] || [];
  return ridersList.value.filter((r) => allowed.includes(r.status));
});

// --- Helpers ---
const getShortType = (code) => {
  const map = { 'transport': '接送', 'feeding': '喂遛', 'washing': '洗护' };
  return map[code] || '订单';
};
const getOrderTabLabel = (key) => map[key]; // Simplified in template
const getOrderStatusText = (status) => {
  const map = { 'pending_dispatch': '待派单', 'pending_accept': '待接单', 'processing': '进行中', 'completed': '已完成' };
  return map[status];
};
const getOrderStatusType = (status) => {
  const map = { 'pending_dispatch': 'danger', 'pending_accept': 'warning', 'processing': 'primary', 'completed': 'success' };
  return map[status];
};
const getRiderStatusText = (status) => {
  const map = { 'online': '接单中', 'busy': '接单中', 'offline': '休息中', 'disabled': '禁用' };
  return map[status];
};
const getCategoryClass = (cat) => {
  const map = { '接送': 'cat-transport', '喂遛': 'cat-feeding', '洗护': 'cat-washing' };
  return map[cat] || '';
};
</script>

<style scoped>
.dispatch-container {
  height: calc(100vh - 84px);
  display: flex;
  flex-direction: column;
  background-color: #f0f2f5;
  overflow: hidden;
}

/* 1. Top Bar */
.top-filter-bar {
  height: 56px;
  background: #fff;
  border-bottom: 1px solid #e4e7ed;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.02);
  z-index: 20;
}

/* 2. Main Content */
.main-content {
  flex: 1;
  display: flex;
  position: relative;
  overflow: hidden;
}

/* Left Map Area */
.map-wrapper {
  flex: 1;
  position: relative;
  background: #fcf9f2;
  overflow: hidden;
}
.map-view {
  width: 100%;
  height: 100%;
}

/* Map Controls */
.map-controls-panel {
  position: absolute;
  bottom: 24px;
  left: 24px;
  display: flex;
  align-items: center;
  gap: 16px;
  z-index: 10;
}
.control-group {
  background: #fff;
  border-radius: 8px;
  padding: 6px;
  display: flex;
  gap: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.c-btn {
  padding: 6px 16px;
  border-radius: 6px;
  font-size: 13px;
  cursor: pointer;
  background: #f5f7fa;
  color: #606266;
  font-weight: 500;
  transition: all 0.2s;
}
.c-btn.active {
  background: #2d8cf0;
  color: #fff;
}
.c-btn.red {
  background: #fef0f0;
  color: #f56c6c;
  border: 1px solid #fde2e2;
}
.c-btn.green {
  background: #f0f9eb;
  color: #67c23a;
  border: 1px solid #e1f3d8;
}
.c-btn.gray {
  background: #f0f2f5;
  color: #909399;
  border: 1px solid #dcdfe6;
  cursor: default;
}
.c-btn.blue {
  background: #ecf5ff;
  color: #409eff;
  border: 1px solid #d9ecff;
}

/* Right Panel */
.right-panel {
  width: 440px;
  background: #fff;
  border-left: 1px solid #e4e7ed;
  display: flex;
  flex-direction: column;
  box-shadow: -4px 0 16px rgba(0, 0, 0, 0.05);
  z-index: 30;
}
.panel-section {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.order-mgmt {
  border-bottom: 8px solid #f5f7fa;
  flex: default;
  height: 50%;
}
.fulfiller-mgmt {
  flex: default;
  height: 50%;
}

.sec-header {
  height: 48px;
  padding: 0 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid #f0f0f0;
}
.sec-header.no-border {
  border-bottom: none;
  height: 40px;
}
.sec-header .tit {
  font-weight: bold;
  font-size: 15px;
  color: #1f2f3d;
}

/* New Header Tabs Style */
.header-tabs-wrapper {
  display: flex;
  padding: 0 16px 8px;
  gap: 12px;
  border-bottom: 1px solid #f5f7fa;
}
.header-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 6px;
  transition: all 0.2s;
  min-width: 60px;
}
.header-tab:hover {
  background: #f5f7fa;
}
.header-tab.active {
  background: #ecf5ff;
}
.header-tab.active .lbl {
  color: #409eff;
  font-weight: bold;
}

.header-tab .num {
  font-size: 16px;
  font-weight: bold;
  line-height: 1.2;
}
.header-tab .lbl {
  font-size: 12px;
  color: #909399;
  margin-top: 2px;
}

.header-tab .num.danger {
  color: #f56c6c;
}
.header-tab .num.warning {
  color: #e6a23c;
}
.header-tab .num.primary {
  color: #409eff;
}
.header-tab .num.success {
  color: #67c23a;
}

.fulfiller-tabs .header-tab {
  flex-direction: row;
  gap: 4px;
  min-width: auto;
}
.fulfiller-tabs .header-tab .num {
  font-size: 14px;
}
.fulfiller-tabs .header-tab .lbl {
  margin-top: 0;
}

/* Header Right Tabs (Orders) */
.header-right-tabs {
  display: flex;
  gap: 4px;
}
.h-tab-item {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  position: relative;
  padding: 6px 12px;
  gap: 6px;
  border-radius: 4px;
  transition: all 0.2s;
  color: #606266;
}
.h-tab-item:hover {
  background: #f5f7fa;
}
.h-tab-item.active {
  background: #ecf5ff;
}
.h-tab-item.active .txt {
  color: #409eff;
  font-weight: bold;
}
.h-tab-item.active::after {
  display: none;
}

.h-tab-item .txt {
  font-size: 14px;
}
.h-tab-item .num {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 0;
}
.h-tab-item .num.danger {
  color: #f56c6c;
}
.h-tab-item .num.warning {
  color: #e6a23c;
}
.h-tab-item .num.primary {
  color: #409eff;
}

/* List */
.list-wrapper {
  flex: 1;
  overflow: hidden;
  padding: 8px 12px;
}
.empty-state {
  text-align: center;
  color: #909399;
  padding: 20px;
  font-size: 13px;
}

.list-card {
  background: #fff;
  border: 1px solid #ebeef5;
  border-radius: 8px;
  padding: 12px;
  margin-bottom: 10px;
  display: flex;
  align-items: stretch;
  gap: 12px;
  transition: all 0.2s;
  cursor: pointer;
}
.list-card:hover {
  border-color: #c6e2ff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.card-left {
  flex-shrink: 0;
  display: flex;
  align-items: center;
}
.order-card .type-tag {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: bold;
}
.type-tag.transport {
  background: #e6a23c;
}
.type-tag.feeding {
  background: #67c23a;
}
.type-tag.washing {
  background: #409eff;
}

.card-main {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
}
.row-1 {
  display: flex;
  align-items: center;
}
.o-type {
  font-weight: bold;
  font-size: 14px;
  color: #303133;
}
.row-2 {
  font-size: 12px;
  color: #606266;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.row-3 {
  font-size: 12px;
  color: #909399;
  display: flex;
  align-items: center;
  gap: 4px;
}

.card-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 8px;
  margin-left: 8px;
  flex-shrink: 0;
}
.card-right .actions {
  display: flex;
  align-items: center;
  gap: 4px;
}

.rider-card .card-left .dot {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid #fff;
}
.dot.online {
  background: #67c23a;
}
.dot.busy {
  background: #409eff;
}
.dot.offline {
  background: #909399;
}

.r-name {
  font-weight: bold;
  font-size: 14px;
  color: #303133;
  margin-right: 8px;
}
.r-station {
  font-size: 12px;
  color: #909399;
  background: #f4f4f5;
  padding: 1px 4px;
  border-radius: 2px;
}
.status-desc.online {
  color: #67c23a;
}
.status-desc.busy {
  color: #409eff;
}
.status-desc.offline {
  color: #909399;
}

.card-right-stats {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 6px;
}
.stat-box {
  font-size: 11px;
  color: #909399;
  display: flex;
  align-items: center;
  gap: 4px;
}
.stat-box .val {
  font-weight: bold;
  font-size: 13px;
}
.stat-box .val.danger {
  color: #f56c6c;
}
.stat-box .val.warning {
  color: #e6a23c;
}

.rider-summary {
  display: flex;
  align-items: center;
  gap: 24px;
  background: #fdfdfd;
  border: 1px solid #ebeef5;
  border-radius: 8px;
  padding: 20px;
  margin-bottom: 24px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
  flex-wrap: nowrap;
  overflow-x: auto;
}
.summary-item {
  display: flex;
  align-items: center;
  font-size: 14px;
  color: #606266;
  white-space: nowrap;
  flex-shrink: 0;
}
.summary-item .lbl {
  color: #909399;
  margin-right: 6px;
}
.summary-item .val {
  color: #303133;
  font-weight: 500;
}
.summary-item .val.bold {
  font-weight: bold;
  font-size: 16px;
  color: #303133;
}

.rider-orders-list {
  border: 1px solid #ebeef5;
  border-radius: 8px;
  overflow: hidden; /* Hide potential scrollbars from container */
}

/* Order Card New Layout */
.row-addr {
  font-size: 13px;
  color: #303133;
  display: flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.5;
}
.row-addr .tag {
  font-size: 11px;
  color: #fff;
  padding: 1px 4px;
  border-radius: 4px;
  flex-shrink: 0;
  transform: scale(0.9);
}
.tag.pick {
  background: #409eff;
}
.tag.drop {
  background: #e6a23c;
}
.tag.home {
  background: #67c23a;
}

.row-time {
  font-size: 12px;
  color: #909399;
  display: flex;
  align-items: center;
  gap: 4px;
}
.days-tag {
  color: #f56c6c;
  background: #fef0f0;
  padding: 0 4px;
  border-radius: 4px;
  font-size: 11px;
  border: 1px solid #fde2e2;
  transform: scale(0.95);
}

/* Updated Rider Card Layout */
.r-name {
  font-size: 14px;
  font-weight: bold;
  color: #303133;
}
.r-phone {
  font-size: 12px;
  color: #909399;
}
.categories-right {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  justify-content: flex-end;
  max-width: 100px;
}

.cat-tag {
  background: #f4f4f5;
  color: #909399;
  font-size: 10px;
  padding: 1px 4px;
  border-radius: 2px;
}
.cat-tag.cat-transport {
  background: #e6f7ff;
  color: #1890ff;
  border: 1px solid #91d5ff;
}
.cat-tag.cat-feeding {
  background: #f6ffed;
  color: #52c41a;
  border: 1px solid #b7eb8f;
}
.cat-tag.cat-washing {
  background: #fff0f6;
  color: #eb2f96;
  border: 1px solid #ffadd2;
}

.status-badge {
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 4px;
  display: inline-block;
  font-weight: bold;
}
.status-badge.online {
  background: #f0f9eb;
  color: #67c23a;
}
.status-badge.busy {
  background: #ecf5ff;
  color: #409eff;
}
.status-badge.offline {
  background: #f4f4f5;
  color: #909399;
}
.status-badge.disabled {
  background: #fef0f0;
  color: #f56c6c;
}

.last-time {
  font-size: 11px;
  color: #999;
}

/* Dispatch Dialog */
.dispatch-order-info {
  background: #f5f7fa;
  padding: 10px;
  border-radius: 4px;
  margin-bottom: 20px;
  border: 1px solid #e4e7ed;
}
.dispatch-rider-select .select-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}
.dispatch-rider-select .tit {
  font-weight: bold;
  font-size: 14px;
}

.rider-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  padding-right: 10px;
}
.rider-card.select-card {
  cursor: pointer;
  border: 1px solid #dcdfe6;
  position: relative;
  transition: all 0.2s;
  margin-bottom: 0; /* Override default list card margin */
}
.rider-card.select-card:hover {
  border-color: #409eff;
}
.rider-card.select-card.active {
  border-color: #409eff;
  background-color: #ecf5ff;
}
.selected-mark {
  position: absolute;
  top: 0;
  right: 0;
  background: #409eff;
  color: #fff;
  border-bottom-left-radius: 6px;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
}

.dispatch-footer {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid #ebeef5;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.dispatch-footer .fee-input {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
}
.empty-text {
  text-align: center;
  color: #909399;
  padding: 20px;
  width: 100%;
  grid-column: span 2;
}

.card-main {
  justify-content: flex-start;
} /* Override default center */
</style>
