<template>
  <el-drawer
    v-model="visible"
    title="预约问诊"
    direction="rtl"
    size="60%"
    :close-on-click-modal="false"
    :z-index="2000"
  >
    <div v-loading="loading">
      <el-alert
        v-if="todayHasBlockingAppointment"
        :type="isSelectingToday ? 'warning' : 'info'"
        :closable="false"
        show-icon
        class="today-block-alert"
        :title="todayBlockingAlertText"
      />
      <el-form :model="form" label-width="100px" class="appointment-form">
        <!-- 上次就诊 -->
        <el-form-item label="上次就诊:">
          <span class="text-gray-500">{{ lastVisit || '无就诊记录' }}</span>
        </el-form-item>

        <!-- 预约方式 -->
        <el-form-item label="预约方式:">
          <el-radio-group v-model="form.appointmentMethod" @change="handleMethodChange">
            <el-radio value="time">选择时段预约有专医生</el-radio>
            <!-- <el-radio value="doctor">选择医生预约有专时段</el-radio> -->
          </el-radio-group>
        </el-form-item>

        <!-- 预约类型 -->
        <el-form-item label="预约类型:">
          <el-radio-group v-model="form.appointmentType">
            <el-radio value="video">视频问诊</el-radio>
          </el-radio-group>
        </el-form-item>

        <!-- 选择患者 -->
        <el-form-item label="选择患者:">
          <el-radio-group v-model="form.patientId">
            <el-radio :value="patientInfo.id">{{ patientInfo.name }}</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="渠道来源:" required>
          <el-select
            v-model="form.channel_source"
            placeholder="请选择渠道来源"
            class="channel-source-select"
            @change="onChannelSourceChange"
          >
            <el-option
              v-for="item in channelOptions"
              :key="String(item.value)"
              :label="item.name"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item
          v-if="needsChannelSourceDetail"
          label="自媒体补充:"
          required
        >
          <el-input
            v-model="form.channel_source_detail"
            clearable
            maxlength="128"
            show-word-limit
            placeholder="请输入自媒体相关补充内容"
            class="channel-source-select"
          />
        </el-form-item>
        <!-- 预约医生 -->
        <el-form-item label="预约医生:">
          <div class="doctor-list">
            <el-radio-group v-model="selectedDoctorId" @change="handleDoctorChange">
              <el-radio
                v-for="doctor in doctorList"
                :key="doctor.id"
                :value="doctor.id"
                class="doctor-radio"
              >
                {{ doctor.name }}
                <!-- <el-tag
                  v-if="getDoctorAvailability(doctor.id)"
                  :type="getDoctorAvailability(doctor.id) > 0 ? 'success' : 'info'"
                  size="small"
                  class="ml-2"
                >
                  {{ getDoctorAvailability(doctor.id) > 0 ? getDoctorAvailability(doctor.id) : '无' }}
                </el-tag> -->
              </el-radio>
            </el-radio-group>
          </div>
        </el-form-item>

        <!-- 预约时间 -->
        <el-form-item label="预约时间:">
          <!-- 未选择医生提示 -->
          <el-empty 
            v-if="!selectedDoctorId" 
            description="请先选择医生" 
            :image-size="80" 
          />
          
          <!-- 医生无排班提示 -->
          <el-empty 
            v-else-if="selectedDoctorId && doctorRosterDates.length === 0" 
            description="该医生暂无排班" 
            :image-size="80" 
          />
          
          <!-- 有排班时显示日期和时间段 -->
          <div v-else class="appointment-time-container">
            <!-- 日期选择 -->
            <div class="date-selector">
              <el-button
                v-for="dateOption in dateOptions"
                :key="dateOption.date"
                :type="form.date === dateOption.date ? 'primary' : ''"
                @click="selectDate(dateOption.date)"
                class="date-button"
              >
                {{ dateOption.label }}
              </el-button>
            </div>

            <!-- 时间段区域 -->
            <div v-if="form.date" class="time-slots-container">
              <!-- 时间段标题和刷新按钮 -->
              <div class="time-slots-header">
                <span class="header-title">可预约时段</span>
                <el-button
                  text
                  type="primary"
                  size="small"
                  :loading="refreshing"
                  @click="handleRefreshSlots"
                >
                  <template #icon>
                    <Refresh />
                  </template>
                  刷新
                </el-button>
              </div>

              <!-- 时间段网格 -->
              <div class="time-slots-grid">
                <div
                  v-for="slot in filteredTimeSlots"
                  :key="slot.time"
                  class="time-slot-item"
                  :class="{
                    'available': slot.available,
                    'unavailable': !slot.available,
                    'selected': form.appointmentTime === slot.time
                  }"
                  @click="selectTimeSlot(slot)"
                >
                  <div class="slot-time">{{ slot.time }}</div>
                  <div class="slot-status" :class="{ 'status-available': slot.available }">
                    {{ slot.available ? '可约' : '已约' }}
                  </div>
                </div>
              </div>
            </div>
          </div>
        </el-form-item>

        <!-- 备注 -->
        <el-form-item label="备注:">
          <el-input
            v-model="form.remark"
            type="textarea"
            :rows="2"
            placeholder="请输入备注信息"
          />
        </el-form-item>
      </el-form>
    </div>

    <template #footer>
      <div class="drawer-footer">
        <el-button @click="visible = false">取消</el-button>
        <el-button
          type="primary"
          @click="handleConfirm"
          :loading="submitting"
          :disabled="!canSubmit"
        >
          确定
        </el-button>
      </div>
    </template>
  </el-drawer>
</template>

<script setup lang="ts">
import { ref, reactive, computed, nextTick } from 'vue'
import { Refresh } from '@element-plus/icons-vue'
import dayjs from 'dayjs'
import isoWeek from 'dayjs/plugin/isoWeek'
import { getDoctors } from '@/api/tcm'
import { getDictData } from '@/api/app'
import { getAvailableSlots, createAppointment, rosterLists, appointmentLists } from '@/api/doctor'
import feedback from '@/utils/feedback'

dayjs.extend(isoWeek)

interface TimeSlot {
  time: string
  available: boolean
  quota: number
}

interface DateOption {
  date: string
  label: string
}

const visible = ref(false)
const loading = ref(false)
const submitting = ref(false)
const refreshing = ref(false)
const doctorList = ref<any[]>([])
const timeSlots = ref<TimeSlot[]>([])
const lastVisit = ref('')
const selectedDoctorId = ref(0)
const doctorRosterDates = ref<string[]>([])  // 医生有排班的日期列表
const channelOptions = ref<{ name: string; value: string }[]>([])
/** 今日是否已有「已预约(1)/已过号(4)」挂号；仅在选择「今天」再预约时禁止提交，其他日期可正常挂 */
const todayHasBlockingAppointment = ref(false)

const patientInfo = reactive({
  id: 0,
  name: '',
  gender: '',
  age: 0
})

const form = reactive({
  appointmentMethod: 'time' as 'time' | 'doctor',
  appointmentType: 'video',
  patientId: 0,
  date: '',
  appointmentTime: '',
  remark: '',
  channel_source: '' as string,
  channel_source_detail: '' as string
})

/** 仅这些渠道字典 name 需填「自媒体补充」（与后台字典名称完全一致） */
const CHANNEL_NAMES_REQUIRING_SELF_MEDIA_DETAIL = new Set([
  '自媒体4H',
  '自媒体3Q',
  '自媒体3H',
  '自媒体2H',
  '自媒体2Q'
])

function channelNameRequiresSelfMediaDetail(name: string) {
  return CHANNEL_NAMES_REQUIRING_SELF_MEDIA_DETAIL.has(String(name ?? '').trim())
}

/** 当前选中渠道字典名称（用于判断是否需填「自媒体补充」） */
const selectedChannelDictName = computed(() => {
  const v = form.channel_source
  if (v === '' || v == null) return ''
  const row = channelOptions.value.find((item: any) => String(item.value) === String(v))
  return row ? String(row.name ?? '').trim() : ''
})

/** 仅白名单内字典项需填写补充说明 */
const needsChannelSourceDetail = computed(() =>
  channelNameRequiresSelfMediaDetail(selectedChannelDictName.value)
)

const onChannelSourceChange = (val: string) => {
  const row = channelOptions.value.find((item: any) => String(item.value) === String(val))
  const name = row ? String(row.name ?? '').trim() : ''
  if (!channelNameRequiresSelfMediaDetail(name)) {
    form.channel_source_detail = ''
  }
}

// 生成未来7天的日期选项（只显示有排班的日期，且大于等于今天）
const dateOptions = computed<DateOption[]>(() => {
  if (!selectedDoctorId.value || doctorRosterDates.value.length === 0) {
    return []
  }
  
  const options: DateOption[] = []
  const weekDays = ['日', '一', '二', '三', '四', '五', '六']
  const today = dayjs().startOf('day')
  
  // 只显示有排班的日期，且日期大于等于今天
  for (const date of doctorRosterDates.value) {
    const dateObj = dayjs(date)
    
    // 过滤掉今天之前的日期
    if (dateObj.isBefore(today)) {
      continue
    }
    
    const label = `${dateObj.format('MM月DD日')} (${weekDays[dateObj.day()]})`
    options.push({
      date: date,
      label
    })
  }
  
  return options
})

// 过滤时间段：如果是今天，只显示当前时间之后的时间段
const filteredTimeSlots = computed(() => {
  if (!form.date || timeSlots.value.length === 0) {
    return []
  }
  
  const today = dayjs().format('YYYY-MM-DD')
  const isToday = form.date === today
  
  if (!isToday) {
    // 不是今天，显示所有时间段
    return timeSlots.value
  }
  
  // 是今天，只显示当前时间之后的时间段
  const now = dayjs()
  return timeSlots.value.map(slot => {
    const slotDateTime = dayjs(`${form.date} ${slot.time}`)
    const isPast = slotDateTime.isBefore(now) || slotDateTime.isSame(now, 'minute')
    
    // 如果时间已过，标记为不可用
    if (isPast) {
      return {
        ...slot,
        available: false
      }
    }
    return slot
  })
})

const todayYmd = () => dayjs().format('YYYY-MM-DD')

/** 当前选中的预约日是否为今天（与今日冲突检测联动） */
const isSelectingToday = computed(() => form.date === todayYmd())

/** 今日已有占用号时：选今天给警告文案，选他日给提示文案 */
const todayBlockingAlertText = computed(() => {
  if (!todayHasBlockingAppointment.value) return ''
  return isSelectingToday.value
    ? '该患者今日已有挂号（已预约或已过号），不能重复预约今天，请改选其他日期。'
    : '该患者今日已有挂号记录；可为患者预约其他日期的时段。'
})

/** 仅当「选今天 + 今日已有占用号」时禁止提交 */
const blockedByTodayDuplicate = computed(
  () => todayHasBlockingAppointment.value && isSelectingToday.value
)

// 是否可以提交
const canSubmit = computed(() => {
  return (
    !blockedByTodayDuplicate.value &&
    selectedDoctorId.value &&
    form.date &&
    form.appointmentTime &&
    !!form.channel_source &&
    (!needsChannelSourceDetail.value || form.channel_source_detail.trim() !== '')
  )
})

const emit = defineEmits(['success'])

// 打开弹窗
const open = async (patient: any) => {
  visible.value = true
  patientInfo.id = patient.patient_id || patient.id
  patientInfo.name = patient.patient_name || patient.name
  patientInfo.gender = patient.gender_desc || patient.gender
  patientInfo.age = patient.age || 0

  // 重置表单
  form.appointmentMethod = 'time'
  form.appointmentType = 'video'
  form.patientId = patientInfo.id
  selectedDoctorId.value = 0
  form.date = ''
  form.appointmentTime = ''
  form.remark = ''
  form.channel_source = ''
  form.channel_source_detail = ''
  timeSlots.value = []
  doctorRosterDates.value = []
  lastVisit.value = ''
  todayHasBlockingAppointment.value = false

  await loadChannelOptions()
  // 加载医生列表
  await loadDoctors()
  
  // 查询该患者的最近一次就诊记录
  await loadLastVisit()
  await loadTodayAppointmentBlock()
}

/** 今日是否已有状态为已预约(1)或已过号(4)的挂号（仅禁止再挂「今天」，不禁止挂其他天） */
const loadTodayAppointmentBlock = async () => {
  todayHasBlockingAppointment.value = false
  const pid = patientInfo.id
  if (!pid) {
    return
  }
  const today = dayjs().format('YYYY-MM-DD')
  try {
    const res = await appointmentLists({
      patient_id: pid,
      start_date: today,
      end_date: today,
      page_no: 1,
      page_size: 50
    })
    const rows = res?.lists || []
    const blocking = rows.find((r: any) => {
      const s = Number(r.status)
      return s === 1 || s === 4
    })
    todayHasBlockingAppointment.value = !!blocking
  } catch (e) {
    console.error('检查今日挂号状态失败:', e)
  }
}

// 加载患者最近一次就诊记录（从预约表查询已完成的预约）
const loadLastVisit = async () => {
  try {
    const res = await appointmentLists({
      patient_id: patientInfo.id,
      status: 3,  // 只查询已完成的预约
      page_no: 1,
      page_size: 1
    })
    
    if (res?.lists && res.lists.length > 0) {
      const lastRecord = res.lists[0]
      // 格式化显示：日期 + 时间
      if (lastRecord.appointment_date && lastRecord.appointment_time) {
        lastVisit.value = `${lastRecord.appointment_date} ${lastRecord.appointment_time}`
      } else if (lastRecord.appointment_date) {
        lastVisit.value = lastRecord.appointment_date
      }
    }
  } catch (error) {
    console.error('加载就诊记录失败:', error)
  }
}

const loadChannelOptions = async () => {
  try {
    const data = await getDictData({ type: 'channels' })
    const rows = (data?.channels || []).filter((row: any) => row.status !== 0)
    rows.sort((a: any, b: any) => {
      const ds = Number(b?.sort ?? 0) - Number(a?.sort ?? 0)
      if (ds !== 0) return ds
      return Number(b?.id ?? 0) - Number(a?.id ?? 0)
    })
    // 统一为字符串，避免字典 value 为数字时 el-select 与表单校验不一致导致看似选了但实际未绑定
    channelOptions.value = rows.map((row: any) => ({
      ...row,
      value: row?.value != null && row.value !== '' ? String(row.value) : ''
    }))
  } catch (e) {
    console.error('加载渠道来源失败:', e)
    channelOptions.value = []
  }
}

// 加载医生列表
const loadDoctors = async () => {
  try {
    loading.value = true
    const res = await getDoctors()
    doctorList.value = res || []
  } catch (error) {
    console.error('加载医生列表失败:', error)
    feedback.msgError('加载医生列表失败')
  } finally {
    loading.value = false
  }
}

// 获取医生可用号源数
const getDoctorAvailability = (doctorId: number) => {
  // 这里应该从后端获取医生的可用号源数
  // 暂时返回模拟数据
  return Math.floor(Math.random() * 10)
}

// 预约方式改变
const handleMethodChange = () => {
  selectedDoctorId.value = 0
  form.date = ''
  form.appointmentTime = ''
  timeSlots.value = []
}

// 医生改变
const handleDoctorChange = async () => {
  form.appointmentTime = ''
  form.date = ''
  timeSlots.value = []
  doctorRosterDates.value = []
  
  if (selectedDoctorId.value) {
    await loadDoctorRoster()
  }
}

// 加载医生排班信息
const loadDoctorRoster = async () => {
  if (!selectedDoctorId.value) {
    return
  }

  try {
    loading.value = true
    
    // 获取未来7天的日期范围
    const startDate = dayjs().format('YYYY-MM-DD')
    const endDate = dayjs().add(6, 'day').format('YYYY-MM-DD')
    
    // 查询医生在这个日期范围内的排班
    const res = await rosterLists({
      doctor_id: selectedDoctorId.value,
      start_date: startDate,
      end_date: endDate,
      status: 1  // 只查询出诊状态
    })
    
    // 提取有排班的日期
    if (res?.lists && res.lists.length > 0) {
      doctorRosterDates.value = [...new Set(res.lists.map((item: any) => item.date))] as string[]
      doctorRosterDates.value.sort()
      
      // 自动选择日期：优先选择今天，如果今天没有排班则选择第一个有排班的日期
      await nextTick()
      if (doctorRosterDates.value.length > 0) {
        const today = dayjs().format('YYYY-MM-DD')
        let defaultDate = doctorRosterDates.value.includes(today)
          ? today
          : doctorRosterDates.value[0]
        // 今日已有占用号时，默认不要落在「今天」，避免一进来确定按钮灰掉
        if (todayHasBlockingAppointment.value && defaultDate === today) {
          const later = doctorRosterDates.value.find((d) => d > today)
          defaultDate = later ?? doctorRosterDates.value.find((d) => d !== today) ?? defaultDate
        }
        selectDate(defaultDate)
      }
    } else {
      doctorRosterDates.value = []
      feedback.msgWarning('该医生暂无排班')
    }
  } catch (error) {
    console.error('加载医生排班失败:', error)
    feedback.msgError('加载医生排班失败')
    doctorRosterDates.value = []
  } finally {
    loading.value = false
  }
}

// 选择日期
const selectDate = (date: string) => {
  form.date = date
  form.appointmentTime = ''
  if (selectedDoctorId.value) {
    loadTimeSlots()
  }
}

// 加载时间段
const loadTimeSlots = async () => {
  if (!selectedDoctorId.value || !form.date) {
    return
  }

  try {
    loading.value = true
    
    // 加载全天时段（9:00-18:00，每15分钟一个）
    const response = await getAvailableSlots({
      doctor_id: selectedDoctorId.value,
      appointment_date: form.date,
      period: 'all'  // 获取全天时段
    })

    console.log('时间段数据:', response)

    timeSlots.value = (response?.slots || []).map((slot: any) => ({
      time: slot.time,
      available: slot.available,
      quota: slot.available ? 1 : 0  // 每个时间段只能预约1次
    }))
    
    console.log('处理后的时间段:', timeSlots.value)
  } catch (error) {
    console.error('加载时间段失败:', error)
    feedback.msgError('加载时间段失败')
    timeSlots.value = []
  } finally {
    loading.value = false
  }
}

// 选择时间段
const selectTimeSlot = (slot: TimeSlot) => {
  if (!slot.available) {
    feedback.msgWarning('该时间段不可预约')
    return
  }
  form.appointmentTime = slot.time
}

// 刷新时间段
const handleRefreshSlots = async () => {
  if (!selectedDoctorId.value || !form.date) {
    return
  }

  try {
    refreshing.value = true
    const previousSelection = form.appointmentTime
    form.appointmentTime = ''
    
    await loadTimeSlots()
    
    if (previousSelection) {
      const slot = timeSlots.value.find(s => s.time === previousSelection)
      if (slot && slot.available) {
        form.appointmentTime = previousSelection
      }
    }
    
    feedback.msgSuccess('刷新成功')
  } catch (error) {
    console.error('刷新失败:', error)
    feedback.msgError('刷新失败，请重试')
  } finally {
    refreshing.value = false
  }
}

// 确认挂号
const handleConfirm = async () => {
  if (!selectedDoctorId.value) {
    feedback.msgWarning('请选择医生')
    return
  }
  if (!form.date) {
    feedback.msgWarning('请选择日期')
    return
  }
  if (!form.appointmentTime) {
    feedback.msgWarning('请选择预约时间')
    return
  }
  if (!form.channel_source) {
    feedback.msgWarning('请选择渠道来源')
    return
  }
  if (needsChannelSourceDetail.value && !form.channel_source_detail.trim()) {
    feedback.msgWarning('请填写自媒体渠道补充信息')
    return
  }
  if (blockedByTodayDuplicate.value) {
    feedback.msgWarning(
      '该患者今日已有挂号（已预约或已过号），不能重复预约今天，请改选其他日期。'
    )
    return
  }

  try {
    submitting.value = true
    
    // 构建请求参数
    const params = {
      patient_id: patientInfo.id,
      doctor_id: selectedDoctorId.value,
      appointment_date: form.date,
      period: 'all',  // 全天时段
      appointment_time: form.appointmentTime,
      appointment_type: form.appointmentType,
      remark: form.remark,
      channel_source: String(form.channel_source ?? ''),
      channel_source_detail: form.channel_source_detail.trim()
    }
    
    console.log('提交预约参数:', params)
    
    await createAppointment(params)

    feedback.msgSuccess('预约成功')
    visible.value = false
    emit('success')
  } catch (error) {
    console.error('预约失败:', error)
    feedback.msgError('预约失败')
  } finally {
    submitting.value = false
  }
}

defineExpose({ open })
</script>

<style scoped lang="scss">
.today-block-alert {
  margin-bottom: 16px;
}

.appointment-form {
  :deep(.el-form-item__label) {
    font-weight: 500;
  }

  .channel-source-select {
    width: 100%;
    max-width: 360px;
  }
}

.doctor-list {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;

  .doctor-radio {
    margin-right: 0;
    
    :deep(.el-radio__label) {
      display: flex;
      align-items: center;
    }
  }
}

.appointment-time-container {
  width: 100%;
}

.date-selector {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 20px;

  .date-button {
    min-width: 130px;
    height: 40px;
    font-size: 14px;
    border-radius: 8px;
    transition: all 0.2s;
    
    &:hover {
      transform: translateY(-2px);
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    }
  }
}

.time-slots-container {
  background-color: #f8f9fa;
  border-radius: 8px;
  padding: 16px;
}

.time-slots-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  
  .header-title {
    font-size: 15px;
    font-weight: 600;
    color: #303133;
  }
}

.time-slots-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 10px;
  max-height: 450px;
  overflow-y: auto;
  padding: 2px;

  &::-webkit-scrollbar {
    width: 6px;
  }

  &::-webkit-scrollbar-thumb {
    background-color: #dcdfe6;
    border-radius: 3px;
    
    &:hover {
      background-color: #c0c4cc;
    }
  }

  .time-slot-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 0px 8px;
    border: 2px solid #e4e7ed;
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.2s;
    background-color: #fff;
    min-height: 70px;

    .slot-time {
      font-size: 15px;
      font-weight: 600;
      color: #303133;
      margin-bottom: 6px;
    }

    .slot-status {
      font-size: 12px;
      color: #909399;
      padding: 0px 8px;
      border-radius: 4px;
      background-color: #f4f4f5;
      
      &.status-available {
        color: #67c23a;
        background-color: #f0f9ff;
      }
    }

    &.available {
      border-color: #e4e7ed;
      
      &:hover {
        border-color: #409eff;
        background-color: #ecf5ff;
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
      }
    }

    &.unavailable {
      background-color: #f5f7fa;
      border-color: #e4e7ed;
      cursor: not-allowed;
      opacity: 0.6;
      
      .slot-time {
        color: #c0c4cc;
      }
      
      .slot-status {
        color: #c0c4cc;
        background-color: #f5f7fa;
      }
      
      &:hover {
        transform: none;
        box-shadow: none;
      }
    }

    &.selected {
      border-color: #409eff;
      background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
      box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);

      .slot-time {
        color: #fff;
      }

      .slot-status {
        color: #fff;
        background-color: rgba(255, 255, 255, 0.2);
      }
    }
  }
}

:deep(.el-radio-group) {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

:deep(.el-radio) {
  margin-right: 0;
}

.drawer-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  padding: 12px 0;
}
</style>
