<template>
  <view
    v-if="visible"
    class="route-planner-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="summary" class="panel-summary">{{ summary }}</text>
        </view>
        <view class="panel-actions">
          <view class="panel-light-action" @tap="handleBack">
            <text class="panel-light-action-text">返回</text>
          </view>
          <view class="panel-light-action" @tap="collapsePanel">
            <text class="panel-light-action-text">收起</text>
          </view>
          <view class="panel-light-action" @tap="handleClear">
            <text class="panel-light-action-text">清除</text>
          </view>
        </view>
      </view>

      <view class="point-row">
        <view class="point-card" @tap="openPicker('start')">
          <view class="point-dot start"></view>
          <text class="point-label">起点</text>
          <text class="point-name" :class="{ placeholder: !startPoint }">
            {{ startPoint?.name || '选择起点' }}
          </text>
          <text v-if="startPoint" class="point-meta">{{ pointMeta(startPoint) }}</text>
        </view>

        <view class="swap-btn" @tap="handleSwap">
          <text class="swap-text">⇅</text>
        </view>

        <view class="point-card" @tap="openPicker('end')">
          <view class="point-dot end"></view>
          <text class="point-label">终点</text>
          <text class="point-name" :class="{ placeholder: !endPoint }">
            {{ endPoint?.name || '选择终点' }}
          </text>
          <text v-if="endPoint" class="point-meta">{{ pointMeta(endPoint) }}</text>
        </view>
      </view>

      <view v-if="startPoint && endPoint" class="route-options">
        <view class="route-options-header">
          <text class="route-options-title">{{ routeOptionsTitle }}</text>
          <text class="route-options-note">偏好选择</text>
        </view>
        <view class="route-option-list">
          <view
            v-for="option in routeOptions"
            :key="option.id"
            class="route-option"
            :class="{ active: option.active, disabled: option.disabled }"
          >
            <text class="route-option-title">{{ option.title }}</text>
            <text class="route-option-meta">{{ option.meta }}</text>
          </view>
        </view>
      </view>

      <view v-if="loading || error || summary" class="panel-status">
        <text v-if="loading" class="panel-status-text">{{ loadingText }}</text>
        <text v-else-if="error" class="panel-status-text error">{{ error }}</text>
        <text v-else class="panel-status-text">{{ summary }}</text>
      </view>

      <view
        class="view-route-btn"
        :class="{ disabled: !canPrimaryAction }"
        @tap="handlePrimaryAction"
      >
        <text class="view-route-text">{{ primaryActionText }}</text>
      </view>
    </template>

    <RoutePointPicker
      :visible="pickerMode !== ''"
      :title="pickerTitle"
      :placeholder="pickerPlaceholder"
      :options="pointOptions"
      :selected-poi-id="activeSelectedPoiId"
      :loading="pickerLoading"
      :error="pickerError"
      :empty-text="pickerEmptyText"
      close-text="返回"
      @close="closePicker"
      @select="handlePointSelect"
      @search="handlePickerSearch"
      @keyword-change="handlePickerKeywordChange"
    />
  </view>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import RoutePointPicker, {
  type RoutePointOption
} from '@/components/navigation/RoutePointPicker.vue'

type PickerMode = '' | 'start' | 'end'

const props = withDefaults(defineProps<{
  visible?: boolean
  startPoint?: RoutePointOption | null
  endPoint?: RoutePointOption | null
  pointOptions?: RoutePointOption[]
  hasRoutePreview?: boolean
  loading?: boolean
  error?: string
  summary?: string
  pickerLoading?: boolean
  pickerError?: string
  pickerEmptyText?: string
  routeReady?: boolean
}>(), {
  visible: true,
  startPoint: null,
  endPoint: null,
  pointOptions: () => [] as RoutePointOption[],
  hasRoutePreview: false,
  loading: false,
  error: '',
  summary: '',
  pickerLoading: false,
  pickerError: '',
  pickerEmptyText: '暂无匹配地点',
  routeReady: false
})

const emit = defineEmits<{
  'update:startPoint': [point: RoutePointOption | null]
  'update:endPoint': [point: RoutePointOption | null]
  startChange: [point: RoutePointOption]
  endChange: [point: RoutePointOption]
  pickerOpen: [mode: 'start' | 'end']
  pickerClose: []
  search: [payload: { mode: 'start' | 'end'; keyword: string }]
  swap: []
  clear: []
  viewRoute: [payload: { startPoint: RoutePointOption; endPoint: RoutePointOption }]
  simulateGuide: []
  back: []
}>()

const pickerMode = ref<PickerMode>('')
const isCollapsed = ref(false)
const panelTouchStartY = ref(0)
const panelTouchCurrentY = ref(0)

const pickerTitle = computed(() => (
  pickerMode.value === 'start' ? '选择起点' : '选择终点'
))

const pickerPlaceholder = computed(() => (
  pickerMode.value === 'start' ? '搜索起点' : '搜索终点'
))

const activeSelectedPoiId = computed(() => (
  pickerMode.value === 'start'
    ? props.startPoint?.poiId || ''
    : props.endPoint?.poiId || ''
))

const canViewRoute = computed(() => Boolean(
  props.startPoint
  && props.endPoint
  && !props.loading
  && props.startPoint.poiId !== props.endPoint.poiId
))

const canPrimaryAction = computed(() => canViewRoute.value && !props.error)

const primaryActionText = computed(() => (
  props.hasRoutePreview
    ? '开始导览'
    : (props.routeReady ? '查看路线' : '查看位置关系')
))

const routeOptionsTitle = computed(() => '馆内导览')

const loadingText = computed(() => (
  props.routeReady ? '正在规划馆内导览路线' : '正在生成馆内位置关系'
))

const collapsedSummary = computed(() => {
  if (props.startPoint && props.endPoint) {
    return `${props.startPoint.name} → ${props.endPoint.name}`
  }

  return '手动选择起点和终点'
})

const routeOptions = computed(() => {
  const unavailable = Boolean(props.error)
  const summaryText = props.summary || (props.routeReady ? '选择后规划真实路线' : '选择后查看位置关系')
  return [
    {
      id: 'recommended',
      title: '推荐路线',
      meta: unavailable
        ? '当前暂不可用'
        : props.hasRoutePreview
          ? summaryText
          : props.routeReady
            ? '调用 SGS SDK 路线规划'
            : '查看起点终点位置关系',
      active: !unavailable,
      disabled: unavailable
    },
    {
      id: 'stairs',
      title: '少走楼梯',
      meta: props.routeReady ? '偏好能力待接入' : '偏好预览，待路线数据验证',
      active: false,
      disabled: true
    },
    {
      id: 'elevator',
      title: '电梯优先',
      meta: props.routeReady ? '偏好能力待接入' : '偏好预览，待路线数据验证',
      active: false,
      disabled: true
    }
  ]
})

watch(
  () => props.visible,
  (visible) => {
    if (visible) {
      isCollapsed.value = false
    } else {
      pickerMode.value = ''
    }
  }
)

const pointMeta = (point: RoutePointOption) => {
  return point.categoryLabel
    ? `${point.floorLabel} · ${point.categoryLabel}`
    : point.floorLabel
}

const openPicker = (mode: 'start' | 'end') => {
  pickerMode.value = mode
  emit('search', { mode, keyword: '' })
  emit('pickerOpen', mode)
}

const closePicker = () => {
  pickerMode.value = ''
  emit('pickerClose')
}

const handlePointSelect = (point: RoutePointOption) => {
  if (pickerMode.value === 'start') {
    emit('update:startPoint', point)
    emit('startChange', point)
  } else if (pickerMode.value === 'end') {
    emit('update:endPoint', point)
    emit('endChange', point)
  }

  closePicker()
}

const handlePickerSearch = (keyword: string) => {
  if (!pickerMode.value) return
  emit('search', { mode: pickerMode.value, keyword })
}

const handlePickerKeywordChange = (keyword: string) => {
  if (!pickerMode.value) return
  emit('search', { mode: pickerMode.value, keyword })
}

const handleSwap = () => {
  emit('swap')
}

const handleClear = () => {
  emit('clear')
}

const handleBack = () => {
  if (pickerMode.value) {
    closePicker()
    return
  }

  emit('back')
}

const collapsePanel = () => {
  isCollapsed.value = true
}

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) => {
  if (pickerMode.value) return
  const clientY = getGestureClientY(event)
  panelTouchStartY.value = clientY
  panelTouchCurrentY.value = clientY
}

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

const handlePanelTouchEnd = (event: TouchEvent) => {
  if (pickerMode.value) return
  panelTouchCurrentY.value = getGestureClientY(event)
  if (panelTouchCurrentY.value - panelTouchStartY.value > 48) {
    collapsePanel()
  }
}

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

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

const handlePanelMouseEnd = (event: MouseEvent) => {
  if (pickerMode.value) return
  panelTouchCurrentY.value = getGestureClientY(event)
  if (panelTouchCurrentY.value - panelTouchStartY.value > 48) {
    collapsePanel()
  }
}

const handleViewRoute = () => {
  if (!canViewRoute.value || !props.startPoint || !props.endPoint) return

  emit('viewRoute', {
    startPoint: props.startPoint,
    endPoint: props.endPoint
  })
}

const handlePrimaryAction = () => {
  if (!canViewRoute.value) return
  if (props.hasRoutePreview) {
    emit('simulateGuide')
    return
  }

  handleViewRoute()
}
</script>

<style scoped lang="scss">
.route-planner-panel {
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: calc(env(safe-area-inset-bottom) + 112px);
  padding: 10px 14px 14px;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  background: rgba(255, 255, 255, 0.97);
  border: 1px solid #e5e6de;
  border-radius: 8px;
  box-shadow: 0 10px 24px rgba(36, 49, 42, 0.12);
  z-index: 1003;
}

.route-planner-panel.collapsed {
  padding: 8px 10px 10px;
}

.panel-handle {
  width: 38px;
  height: 4px;
  margin: 0 auto 10px;
  background: #d8dbd2;
  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 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #151713;
  border-radius: 8px;
}

.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: 17px;
  line-height: 24px;
  font-weight: 700;
  color: #151713;
}

.panel-summary {
  font-size: 12px;
  line-height: 18px;
  color: #696962;
  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: #f5f7f2;
  border: 1px solid #e4e5df;
  border-radius: 8px;
}

.panel-light-action-text {
  font-size: 12px;
  line-height: 16px;
  font-weight: 500;
  color: #545861;
}

.point-row {
  position: relative;
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-right: 52px;
}

.point-card {
  position: relative;
  min-width: 0;
  min-height: 52px;
  padding: 8px 10px 8px 34px;
  display: grid;
  grid-template-columns: 42px minmax(0, 1fr);
  column-gap: 8px;
  align-items: center;
  box-sizing: border-box;
  background: #f6f7f4;
  border: 1px solid #e5e6de;
  border-radius: 8px;
}

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

.point-dot.start {
  background: #1fbf6b;
}

.point-dot.end {
  background: #ef5552;
}

.point-label {
  font-size: 11px;
  line-height: 15px;
  color: #8b8b84;
}

.point-name {
  margin-top: 0;
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
  color: #1f2329;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.point-name.placeholder {
  color: #545861;
}

.point-meta {
  grid-column: 2;
  margin-top: -2px;
  font-size: 11px;
  line-height: 15px;
  color: #696962;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.swap-btn {
  position: absolute;
  right: 0;
  top: 0;
  width: 42px;
  height: 112px;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  background: #ffffff;
  border: 1px solid #d7dad3;
  border-radius: 8px;
}

.swap-text {
  font-size: 22px;
  line-height: 24px;
  font-weight: 500;
  color: #151713;
}

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

.panel-status-text {
  font-size: 12px;
  line-height: 18px;
  color: #696962;
}

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

.view-route-btn {
  margin-top: 12px;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #151713;
  border-radius: 8px;
}

.view-route-btn.disabled {
  background: #d8dbd2;
}

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

.view-route-btn.disabled .view-route-text {
  color: #8b8b84;
}

.route-options {
  margin-top: 12px;
  padding: 10px;
  background: #f9fafb;
  border: 1px solid #ecede7;
  border-radius: 8px;
}

.route-options-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.route-options-title {
  font-size: 13px;
  line-height: 18px;
  font-weight: 700;
  color: #151713;
}

.route-options-note {
  font-size: 11px;
  line-height: 15px;
  color: #8b8b84;
}

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

.route-option {
  min-width: 0;
  min-height: 56px;
  padding: 8px 6px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
  box-sizing: border-box;
  background: #ffffff;
  border: 1px solid #e5e6de;
  border-radius: 8px;
}

.route-option.active {
  border-color: #151713;
  background: #ffffff;
}

.route-option.disabled {
  opacity: 0.68;
}

.route-option-title {
  font-size: 12px;
  line-height: 16px;
  font-weight: 700;
  color: #151713;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.route-option-meta {
  font-size: 10px;
  line-height: 14px;
  color: #696962;
  text-align: center;
  display: -webkit-box;
  overflow: hidden;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
</style>
