<template>
  <view
    v-if="visible"
    class="outdoor-nav-panel"
    :class="{ collapsed: isCollapsed }"
    @touchstart.stop="handlePanelTouchStart"
    @touchmove.stop="handlePanelTouchMove"
    @touchend.stop="handlePanelTouchEnd"
    @mousedown.stop="handlePanelMouseStart"
    @mousemove.stop="handlePanelMouseMove"
    @mouseup.stop="handlePanelMouseEnd"
  >
    <view class="panel-handle" @tap.stop="toggleCollapsed"></view>

    <view v-if="isCollapsed" class="panel-collapsed" @tap="expandPanel">
      <view class="panel-collapsed-copy">
        <text class="panel-title">馆外导览</text>
        <text class="panel-summary">{{ collapsedSummary }}</text>
      </view>
      <view class="panel-expand">
        <text class="panel-expand-text">展开</text>
      </view>
    </view>

    <template v-else>
      <view class="panel-header">
        <view class="panel-title-group">
          <text class="panel-title">馆外导览</text>
          <text v-if="routeSummary" class="panel-summary">{{ routeSummary }}</text>
        </view>
        <view class="panel-actions">
          <view class="panel-light-action" @tap="handleBack">
            <text class="panel-light-action-text">返回</text>
          </view>
        </view>
      </view>

      <!-- 起点选择区域 -->
      <view class="start-point-section">
        <view class="section-label">
          <text class="section-label-text">起点</text>
        </view>
        <view class="start-point-buttons">
          <view
            class="start-btn gps-btn"
            :class="{ active: effectiveStartMode === 'gps' }"
            @tap="handleGpsStart"
          >
            <view class="start-btn-icon icon-gps">
              <view class="icon-gps-dot"></view>
            </view>
            <text class="start-btn-text">GPS定位</text>
          </view>
          <view
            class="start-btn manual-btn"
            :class="{ active: effectiveStartMode === 'manual' }"
            @tap="handleManualStart"
          >
            <view class="start-btn-icon icon-manual">
              <view class="icon-manual-line"></view>
            </view>
            <text class="start-btn-text">手动选择</text>
          </view>
        </view>
        <!-- 手动选择模式：显示搜索框 -->
        <view v-if="effectiveStartMode === 'manual'" class="start-search-container">
          <view class="start-search-input-wrapper">
            <input
              class="start-search-input"
              type="text"
              placeholder="输入起点地址或地名"
              v-model="startSearchQuery"
              @input="handleStartSearchInput"
            />
            <view v-if="isSearchingStart" class="start-search-loading">
              <text class="loading-text">搜索中...</text>
            </view>
          </view>
          <!-- 搜索结果列表 -->
          <view v-if="startSearchResults.length > 0" class="start-search-results">
            <view
              v-for="(result, index) in startSearchResults"
              :key="index"
              class="search-result-item"
              @tap="handleSelectSearchResult(result)"
            >
              <text class="result-title">{{ result.title }}</text>
              <text class="result-address">{{ result.address }}</text>
            </view>
          </view>
        </view>
        <view v-if="effectiveStartPoint" class="start-point-display">
          <view class="point-dot start"></view>
          <text class="point-name">{{ formatStartPointName() }}</text>
          <view class="point-change" @tap="handleManualStart">
            <text class="point-change-text">修改</text>
          </view>
        </view>
      </view>

      <!-- 出行方式选择 -->
      <view class="travel-mode-section">
        <text class="section-label-text">出行方式</text>
        <view class="travel-mode-list">
          <view
            v-for="mode in travelModes"
            :key="mode.type"
            class="travel-mode-item"
            :class="[{ active: selectedTravelMode === mode.type }, `mode-${mode.type}`]"
            @tap="handleTravelModeChange(mode.type)"
          >
            <view class="travel-mode-icon"></view>
            <text class="travel-mode-label">{{ mode.label }}</text>
          </view>
        </view>
      </view>

      <!-- 路线状态 -->
      <view v-if="loading" class="panel-status">
        <text class="panel-status-text">规划路线中...</text>
      </view>
      <view v-else-if="routeError" class="panel-status">
        <text class="panel-status-text error">{{ routeError }}</text>
      </view>

      <!-- 操作按钮 -->
      <view class="action-buttons">
        <view
          v-if="hasRoute"
          class="nav-btn secondary"
          @tap="handleClearRoute"
        >
          <text class="nav-btn-text">清除路线</text>
        </view>
        <view
          class="nav-btn primary"
          :class="{ disabled: !canNavigate }"
          @tap="handleStartNavigation"
        >
          <text class="nav-btn-text">{{ navigateButtonText }}</text>
        </view>
      </view>
    </template>
  </view>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { TRAVEL_MODE_CONFIG, type TravelMode } from '@/config/museum'

type StartMode = 'gps' | 'manual'

const props = withDefaults(defineProps<{
  visible?: boolean
  loading?: boolean
  routeError?: string
  routeDistance?: number
  routeDuration?: number
  selectingManualStart?: boolean
  startPoint?: { latitude: number; longitude: number; name?: string } | null
  startMode?: 'gps' | 'manual'
}>(), {
  visible: false,
  loading: false,
  routeError: '',
  routeDistance: 0,
  routeDuration: 0,
  selectingManualStart: false,
  startPoint: null,
  startMode: 'gps'
})

const emit = defineEmits<{
  close: []
  gpsStart: []
  manualStartRequest: []
  manualStartConfirm: [location: { latitude: number; longitude: number }]
  manualStartCancel: []
  travelModeChange: [mode: TravelMode]
  startNavigation: []
  clearRoute: []
  back: []
}>()

const isCollapsed = ref(false)
const localStartMode = ref<StartMode>('gps')
const manualStartPoint = ref<{ latitude: number; longitude: number; name?: string } | null>(null)
const selectedTravelMode = ref<TravelMode>('walking')
const panelTouchStartY = ref(0)
const panelTouchCurrentY = ref(0)

// 起点搜索相关状态
const startSearchQuery = ref('')
const startSearchResults = ref<Array<{ title: string; address: string; latitude: number; longitude: number }>>([])
const isSearchingStart = ref(false)

const travelModes = Object.values(TRAVEL_MODE_CONFIG)

// 使用外部传入的 startPoint，兼容本地状态
const effectiveStartPoint = computed(() => {
  return props.startPoint ?? manualStartPoint.value
})

// 外部传入的 startMode 优先级更高
const effectiveStartMode = computed(() => {
  if (props.startPoint) return 'manual'
  return props.startMode ?? localStartMode.value
})

const hasRoute = computed(() => {
  return effectiveStartPoint.value !== null && !props.loading && !props.routeError
})

const canNavigate = computed(() => {
  if (props.loading) return false
  if (props.routeError) return false
  if (!effectiveStartPoint.value && effectiveStartMode.value !== 'gps') return false
  return true
})

const navigateButtonText = computed(() => {
  if (props.loading) return '规划中...'
  if (hasRoute.value) return '打开地图'
  return '规划路线'
})

const routeSummary = computed(() => {
  if (props.routeDistance > 0 && props.routeDuration > 0) {
    const distanceText = props.routeDistance >= 1000
      ? `${(props.routeDistance / 1000).toFixed(1)}公里`
      : `${Math.round(props.routeDistance)}米`
    const durationText = props.routeDuration >= 60
      ? `${Math.round(props.routeDuration / 60)}分钟`
      : `${Math.round(props.routeDuration)}秒`
    return `${distanceText} · 约${durationText}`
  }
  return ''
})

const collapsedSummary = computed(() => {
  if (effectiveStartPoint.value) {
    return formatStartPointName()
  }
  if (effectiveStartMode.value === 'gps') {
    return '使用 GPS 定位'
  }
  return '馆外导览到馆'
})

const formatStartPointName = () => {
  if (!effectiveStartPoint.value) return ''
  if (effectiveStartPoint.value.name) {
    return effectiveStartPoint.value.name
  }
  return `(${effectiveStartPoint.value.latitude.toFixed(5)}, ${effectiveStartPoint.value.longitude.toFixed(5)})`
}

watch(
  () => props.visible,
  (visible) => {
    if (visible) {
      isCollapsed.value = false
    } else {
      // 重置状态
      localStartMode.value = 'gps'
      manualStartPoint.value = null
      selectedTravelMode.value = 'walking'
    }
  }
)

const handleGpsStart = () => {
  localStartMode.value = 'gps'
  manualStartPoint.value = null
  emit('gpsStart')
}

// 搜索起点地址
const searchStartAddress = async (query: string) => {
  if (!query.trim()) {
    startSearchResults.value = []
    return
  }

  isSearchingStart.value = true
  try {
    const { searchPoi } = await import('@/services/tencent/TencentMapService')
    const result = await searchPoi(query, '深圳市', 1, 5)
    if (result.status === 0 && result.data) {
      startSearchResults.value = result.data.map(poi => ({
        title: poi.title,
        address: poi.address,
        latitude: poi.location.lat,
        longitude: poi.location.lng
      }))
    } else {
      startSearchResults.value = []
    }
  } catch (error) {
    console.error('搜索起点失败:', error)
    startSearchResults.value = []
  } finally {
    isSearchingStart.value = false
  }
}

// 处理搜索输入
const handleStartSearchInput = () => {
  const query = startSearchQuery.value
  if (query.length >= 2) {
    void searchStartAddress(query)
  } else {
    startSearchResults.value = []
  }
}

// 选择搜索结果作为起点
const handleSelectSearchResult = (result: { title: string; address: string; latitude: number; longitude: number }) => {
  manualStartPoint.value = {
    latitude: result.latitude,
    longitude: result.longitude,
    name: result.title
  }
  startSearchQuery.value = ''
  startSearchResults.value = []
  emit('manualStartConfirm', { latitude: result.latitude, longitude: result.longitude })
}

// 切换到手动选择模式
const handleManualStart = () => {
  localStartMode.value = 'manual'
  startSearchQuery.value = ''
  startSearchResults.value = []
  emit('manualStartRequest')
}

const handleTravelModeChange = (mode: TravelMode) => {
  selectedTravelMode.value = mode
  emit('travelModeChange', mode)
}

const handleStartNavigation = () => {
  if (!canNavigate.value) return
  emit('startNavigation')
}

const handleClearRoute = () => {
  manualStartPoint.value = null
  localStartMode.value = 'gps'
  emit('clearRoute')
}

const handleBack = () => {
  emit('back')
}

const expandPanel = () => {
  isCollapsed.value = false
}

const toggleCollapsed = () => {
  isCollapsed.value = !isCollapsed.value
}

const getGestureClientY = (event: TouchEvent | MouseEvent) => {
  if ('changedTouches' in event) {
    return event.changedTouches?.[0]?.clientY
      ?? event.touches?.[0]?.clientY
      ?? 0
  }
  return event.clientY
}

const handlePanelTouchStart = (event: TouchEvent) => {
  const clientY = getGestureClientY(event)
  panelTouchStartY.value = clientY
  panelTouchCurrentY.value = clientY
}

const handlePanelTouchMove = (event: TouchEvent) => {
  panelTouchCurrentY.value = getGestureClientY(event)
}

const handlePanelTouchEnd = (event: TouchEvent) => {
  panelTouchCurrentY.value = getGestureClientY(event)
  if (panelTouchCurrentY.value - panelTouchStartY.value > 48) {
    emit('close')
  }
}

const handlePanelMouseStart = (event: MouseEvent) => {
  const clientY = getGestureClientY(event)
  panelTouchStartY.value = clientY
  panelTouchCurrentY.value = clientY
}

const handlePanelMouseMove = (event: MouseEvent) => {
  panelTouchCurrentY.value = getGestureClientY(event)
}

const handlePanelMouseEnd = (event: MouseEvent) => {
  panelTouchCurrentY.value = getGestureClientY(event)
  if (panelTouchCurrentY.value - panelTouchStartY.value > 48) {
    emit('close')
  }
}
</script>

<style scoped lang="scss">
.outdoor-nav-panel {
  position: absolute;
  left: 15px;
  right: 15px;
  bottom: calc(env(safe-area-inset-bottom) + 106px);
  padding: 12px 15px 15px;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  background: var(--museum-bg-surface);
  border: 1px solid #d9d9d9;
  border-radius: var(--radius-card);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
  z-index: 1003;
}

.outdoor-nav-panel.collapsed {
  padding: 10px 12px 12px;
}

.panel-handle {
  width: 38px;
  height: 4px;
  margin: 0 auto 12px;
  background: #d9d9d9;
  border-radius: 999px;
}

.panel-collapsed {
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.panel-collapsed-copy {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.panel-expand {
  flex: 0 0 auto;
  height: 30px;
  padding: 0 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000000;
  border-radius: var(--radius-button);
}

.panel-expand-text {
  font-size: 12px;
  line-height: 16px;
  font-weight: 500;
  color: var(--museum-accent);
}

.panel-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.panel-title-group {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.panel-title {
  font-size: 18px;
  line-height: 25px;
  font-weight: 500;
  color: var(--museum-text-primary);
}

.panel-summary {
  font-size: 12px;
  line-height: 18px;
  color: var(--museum-text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.panel-actions {
  flex: 0 0 auto;
  display: flex;
  gap: 6px;
}

.panel-light-action {
  flex: 0 0 auto;
  height: 28px;
  padding: 0 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  background: var(--museum-bg-surface);
  border: 1px solid #d9d9d9;
  border-radius: var(--radius-button);
}

.panel-light-action-text {
  font-size: 12px;
  line-height: 16px;
  font-weight: 500;
  color: var(--museum-text-secondary);
}

.start-point-section {
  margin-top: 16px;
}

.section-label {
  margin-bottom: 8px;
}

.section-label-text {
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--museum-text-secondary);
}

.start-point-buttons {
  display: flex;
  gap: 10px;
}

.start-btn {
  flex: 1;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  box-sizing: border-box;
  background: var(--museum-bg-surface);
  border: 1px solid #d9d9d9;
  border-radius: var(--radius-button);
  transition: all 0.2s;
}

.start-btn.active {
  background: #000000;
  border-color: #000000;
}

.start-btn-icon {
  position: relative;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--museum-text-primary);
  box-sizing: border-box;
}

.start-btn.active .start-btn-icon {
  color: var(--museum-accent);
}

.icon-gps {
  border: 1.8px solid currentColor;
  border-radius: 50%;
}

.icon-gps::before,
.icon-gps::after {
  content: '';
  position: absolute;
  background: currentColor;
}

.icon-gps::before {
  left: 8px;
  top: -4px;
  width: 1.8px;
  height: 24px;
}

.icon-gps::after {
  left: -4px;
  top: 8px;
  width: 24px;
  height: 1.8px;
}

.icon-gps-dot {
  position: absolute;
  left: 5px;
  top: 5px;
  width: 6px;
  height: 6px;
  background: currentColor;
  border-radius: 50%;
}

.icon-manual {
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
}

.icon-manual::before {
  content: '';
  position: absolute;
  right: 0;
  bottom: -2px;
  width: 7px;
  height: 7px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
}

.icon-manual-line {
  position: absolute;
  left: 3px;
  bottom: 5px;
  width: 15px;
  height: 2px;
  background: currentColor;
}

.start-btn-text {
  font-size: 14px;
  line-height: 20px;
  font-weight: 500;
  color: var(--museum-text-primary);
}

.start-btn.active .start-btn-text {
  color: var(--museum-accent);
}

.start-hint {
  margin-top: 8px;
  padding: 10px 12px;
  background: var(--museum-bg-light);
  border: 1px solid var(--museum-border-light);
  border-radius: var(--radius-button);
}

.start-hint-text {
  font-size: 12px;
  line-height: 17px;
  color: var(--museum-text-disabled);
}

.start-search-container {
  margin-top: 10px;
}

.start-search-input-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

.start-search-input {
  width: 100%;
  height: 40px;
  padding: 0 12px;
  font-size: 14px;
  color: var(--museum-text-primary);
  background: var(--museum-bg-cream);
  border: 1px solid #adb0b4;
  border-radius: var(--radius-button);
  box-sizing: border-box;
}

.start-search-loading {
  position: absolute;
  right: 12px;
  display: flex;
  align-items: center;
  pointer-events: none;
}

.loading-text {
  font-size: 12px;
  color: var(--museum-text-disabled);
}

.start-search-results {
  margin-top: 8px;
  background: var(--museum-bg-surface);
  border: 1px solid #d9d9d9;
  border-radius: var(--radius-button);
  overflow: hidden;
}

.search-result-item {
  padding: 12px;
  border-bottom: 1px solid #d9d9d9;
  cursor: pointer;
}

.search-result-item:last-child {
  border-bottom: none;
}

.result-title {
  display: block;
  font-size: 14px;
  font-weight: 500;
  color: var(--museum-text-primary);
  margin-bottom: 4px;
}

.result-address {
  display: block;
  font-size: 12px;
  color: var(--museum-text-disabled);
}

.start-point-display {
  position: relative;
  margin-top: 8px;
  padding: 10px 10px 10px 30px;
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--museum-bg-light);
  border: 1px solid #d9d9d9;
  border-radius: var(--radius-button);
}

.point-dot {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.point-dot.start {
  background: #2c854f;
}

.point-name {
  flex: 1;
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
  color: var(--museum-text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.point-change {
  flex: 0 0 auto;
  height: 26px;
  padding: 0 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--museum-bg-surface);
  border: 1px solid #d9d9d9;
  border-radius: var(--radius-button);
}

.point-change-text {
  font-size: 12px;
  line-height: 16px;
  font-weight: 500;
  color: var(--museum-text-secondary);
}

.travel-mode-section {
  margin-top: 16px;
}

.travel-mode-list {
  margin-top: 8px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}

.travel-mode-item {
  height: 52px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  box-sizing: border-box;
  background: var(--museum-bg-surface);
  border: 1px solid #d9d9d9;
  border-radius: var(--radius-button);
  transition: all 0.2s;
}

.travel-mode-item.active {
  background: #000000;
  border-color: #000000;
}

.travel-mode-icon {
  position: relative;
  width: 22px;
  height: 18px;
  color: var(--museum-text-primary);
  box-sizing: border-box;
}

.travel-mode-item.active .travel-mode-icon {
  color: var(--museum-accent);
}

.mode-walking .travel-mode-icon::before {
  content: '';
  position: absolute;
  left: 8px;
  top: 0;
  width: 6px;
  height: 6px;
  background: currentColor;
  border-radius: 50%;
}

.mode-walking .travel-mode-icon::after {
  content: '';
  position: absolute;
  left: 6px;
  top: 7px;
  width: 10px;
  height: 10px;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: skewX(-18deg);
}

.mode-driving .travel-mode-icon {
  border: 2px solid currentColor;
  border-radius: 4px 4px 3px 3px;
}

.mode-driving .travel-mode-icon::before,
.mode-driving .travel-mode-icon::after {
  content: '';
  position: absolute;
  bottom: -5px;
  width: 5px;
  height: 5px;
  background: currentColor;
  border-radius: 50%;
}

.mode-driving .travel-mode-icon::before {
  left: 2px;
}

.mode-driving .travel-mode-icon::after {
  right: 2px;
}

.mode-transit .travel-mode-icon {
  border: 2px solid currentColor;
  border-radius: 3px;
}

.mode-transit .travel-mode-icon::before {
  content: '';
  position: absolute;
  left: 4px;
  right: 4px;
  top: 4px;
  height: 5px;
  border-top: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
}

.travel-mode-label {
  font-size: 12px;
  line-height: 16px;
  font-weight: 500;
  color: var(--museum-text-primary);
}

.travel-mode-item.active .travel-mode-label {
  color: var(--museum-accent);
}

.panel-status {
  margin-top: 10px;
  min-height: 20px;
}

.panel-status-text {
  font-size: 12px;
  line-height: 18px;
  color: var(--museum-text-tertiary);
}

.panel-status-text.error {
  color: #e73333;
}

.action-buttons {
  margin-top: 14px;
  display: flex;
  gap: 10px;
}

.nav-btn {
  flex: 1;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-button);
  transition: all 0.2s;
}

.nav-btn.primary {
  flex: 2;
  background: #000000;
}

.nav-btn.secondary {
  flex: 1;
  background: var(--museum-bg-surface);
  border: 1px solid #000000;
}

.nav-btn.disabled {
  background: #000000;
  border-color: #000000;
  opacity: 0.45;
}

.nav-btn-text {
  font-size: 14px;
  line-height: 19px;
  font-weight: 500;
  color: var(--museum-accent);
}

.nav-btn.secondary .nav-btn-text {
  color: var(--museum-text-primary);
}

.nav-btn.disabled .nav-btn-text {
  color: var(--museum-accent);
}

.manual-select-hint {
  margin-top: 12px;
  padding: 12px 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: #fff9e6;
  border: 1px solid #ffe58a;
  border-radius: 8px;
}

.manual-select-hint-text {
  font-size: 13px;
  line-height: 18px;
  color: #7a6108;
}

.manual-select-cancel {
  flex: 0 0 auto;
  height: 26px;
  padding: 0 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #ffffff;
  border: 1px solid #d7dad3;
  border-radius: 6px;
}

.manual-select-cancel-text {
  font-size: 12px;
  line-height: 16px;
  font-weight: 500;
  color: #545861;
}
</style>
