<template>
  <ContentWrap>
    <div class="fixed-save-bar">
      <el-button type="warning" size="default" :loading="submitting" @click="handleSubmit">
        保存设置
      </el-button>
    </div>

    <el-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      label-width="120px"
      class="setting-form"
    >
      <el-row :gutter="20" class="main-row">
        <el-col :span="12" class="col-left">
          <div class="card card-top-left">
            <div class="card-header">
              <el-icon class="card-icon icon-blue"><Setting /></el-icon>
              <span class="card-title">基础设置</span>
              <div class="master-switch">
                <span class="switch-label">预约总开关</span>
                <el-switch
                  v-model="formData.appointmentEnabled"
                  active-text="开启"
                  inactive-text="关闭"
                />
              </div>
            </div>
            <div class="card-body">
              <el-form-item label="放号规则">
                <el-radio-group v-model="formData.ruleType" :disabled="isDisabled">
                  <el-radio :value="1">时间循环预约</el-radio>
                </el-radio-group>
              </el-form-item>

              <el-form-item v-show="false" label="开始预约日" prop="startDay">
                <el-select
                  v-model="formData.startDay"
                  placeholder="请选择"
                  style="width: 100%"
                  :disabled="isDisabled"
                >
                  <el-option label="当天" :value="0" />
                  <el-option label="未来1天" :value="1" />
                  <el-option label="未来2天" :value="2" />
                  <el-option label="未来3天" :value="3" />
                  <el-option label="未来4天" :value="4" />
                  <el-option label="未来5天" :value="5" />
                  <el-option label="未来6天" :value="6" />
                  <el-option label="未来7天" :value="7" />
                  <el-option label="未来8天" :value="8" />
                  <el-option label="未来9天" :value="9" />
                  <el-option label="未来10天" :value="10" />
                  <el-option label="未来11天" :value="11" />
                  <el-option label="未来12天" :value="12" />
                  <el-option label="未来13天" :value="13" />
                  <el-option label="未来14天" :value="14" />
                  <el-option label="未来15天" :value="15" />
                </el-select>
              </el-form-item>
              <el-form-item label="提前预约" prop="advanceDays">
                <el-input-number
                  v-model="formData.advanceDays"
                  :min="1"
                  :max="30"
                  style="width: 100%"
                  :disabled="isDisabled"
                >
                  <template #prefix>
                    <span>可提前</span>
                  </template>
                  <template #suffix>
                    <span>天预约</span>
                  </template>
                </el-input-number>
              </el-form-item>
            </div>
          </div>

          <div class="card card-bottom-left">
            <div class="card-header">
              <el-icon class="card-icon icon-green"><Calendar /></el-icon>
              <span class="card-title">预约组</span>
              <el-button
                type="primary"
                size="small"
                :disabled="isDisabled"
                @click="addAppointmentGroup"
              >
                <el-icon><Plus /></el-icon>
                添加预约组
              </el-button>
            </div>
            <div class="card-body card-body-groups">
              <div v-if="appointmentGroups.length === 0" class="empty-groups">
                <el-empty description="暂无预约组，点击右上角添加" :image-size="60" />
              </div>
              <div v-else class="group-list">
                <div
                  v-for="(group, groupIndex) in appointmentGroups"
                  :key="group.id"
                  class="group-card"
                >
                  <div class="group-header">
                    <span class="group-label">预约日期：</span>
                    <div class="cycle-buttons">
                      <el-button
                        :type="group.cycleType === 'daily' ? 'success' : 'default'"
                        size="small"
                        :disabled="isDisabled || group.enable == 0"
                        @click="setCycleType(group, 'daily')"
                      >
                        每天
                      </el-button>
                      <el-button
                        :type="group.cycleType === 'weekly' ? 'success' : 'default'"
                        size="small"
                        :disabled="isDisabled || group.enable == 0"
                        @click="openWeeklyDialog(group)"
                      >
                        每周
                      </el-button>
                      <el-button
                        :type="group.cycleType === 'monthly' ? 'success' : 'default'"
                        size="small"
                        :disabled="isDisabled || group.enable == 0"
                        @click="openMonthlyDialog(group)"
                      >
                        每月
                      </el-button>
                      <el-button
                        :type="group.cycleType === 'custom' ? 'success' : 'default'"
                        size="small"
                        :disabled="isDisabled || group.enable == 0"
                        @click="openCustomDialog(group)"
                      >
                        自定义
                      </el-button>
                    </div>
                    <el-switch
                      v-model="group.enable"
                      active-text="启用"
                      size="small"
                      :disabled="isDisabled"
                      :active-value="1"
                      :inactive-value="0"
                      style="margin-right: 1vw"
                      inactive-text="关闭"
                    />

                    <el-button
                      type="danger"
                      link
                      size="small"
                      :disabled="isDisabled || group.enable == 0"
                      @click="removeGroup(groupIndex)"
                    >
                      <el-icon><Delete /></el-icon>
                      删除组
                    </el-button>
                  </div>

                  <div class="group-dates">
                    <template v-if="group.cycleType === 'daily'">
                      <el-tag type="success" size="small">每天都可预约</el-tag>
                    </template>
                    <template v-else-if="group.cycleType === 'weekly'">
                      <span class="dates-label">每周可预约：</span>
                      <el-tag v-if="group.weeklyDays.length === 0" type="info" size="small"
                        >未设置</el-tag
                      >
                      <el-tag
                        v-for="day in group.weeklyDays"
                        :key="day"
                        type="success"
                        size="small"
                        class="date-tag"
                      >
                        {{ getWeekDayLabel(day) }}
                      </el-tag>
                    </template>
                    <template v-else-if="group.cycleType === 'monthly'">
                      <span class="dates-label">每月可预约：</span>
                      <el-tag v-if="group.monthlyDays.length === 0" type="info" size="small"
                        >未设置</el-tag
                      >
                      <el-tag
                        v-for="day in group.monthlyDays"
                        :key="day"
                        type="success"
                        size="small"
                        class="date-tag"
                      >
                        {{ day }}号
                      </el-tag>
                    </template>
                    <template v-else-if="group.cycleType === 'custom'">
                      <span class="dates-label">自定义日期：</span>
                      <el-tag v-if="group.customDates.length === 0" type="info" size="small"
                        >未设置</el-tag
                      >
                      <el-tag
                        v-for="date in group.customDates.slice(0, 5)"
                        :key="date"
                        type="success"
                        size="small"
                        class="date-tag"
                      >
                        {{ date }}
                      </el-tag>
                      <el-tooltip
                        v-if="group.customDates.length > 5"
                        :content="group.customDates.join('、')"
                        placement="top"
                      >
                        <el-tag type="info" size="small" class="date-tag">
                          +{{ group.customDates.length - 5 }}
                        </el-tag>
                      </el-tooltip>
                    </template>
                  </div>

                  <div class="group-items-section">
                    <div class="items-header">
                      <span class="items-title">预约项</span>
                      <span class="items-sub">（多项时间段不可重叠）</span>
                    </div>

                    <div v-if="group.items.length === 0" class="empty-items">
                      暂无预约项，点击下方按钮添加
                    </div>
                    <div v-else class="items-list">
                      <div v-for="(item, itemIndex) in group.items" :key="item.id" class="item-row">
                        <div
                          class="item-delete-btn"
                          :class="{ disabled: isDisabled || group.enable == 0 }"
                          @click="removeItem(group, itemIndex)"
                        >
                          <el-icon><Delete /></el-icon>
                        </div>
                        <div class="item-fields">
                          <div class="field-block">
                            <span class="field-label">时间段</span>
                            <el-time-picker
                              v-model="item.startTime"
                              format="HH:mm"
                              value-format="HH:mm"
                              placeholder="开始时间"
                              size="small"
                              style="width: 110px"
                              :disabled="isDisabled || group.enable == 0"
                              @change="checkTimeOverlap(group, itemIndex)"
                            />
                            <span class="time-sep">至</span>
                            <el-time-picker
                              v-model="item.endTime"
                              format="HH:mm"
                              value-format="HH:mm"
                              placeholder="结束时间"
                              size="small"
                              style="width: 110px"
                              :disabled="isDisabled || group.enable == 0"
                              @change="checkTimeOverlap(group, itemIndex)"
                            />
                          </div>
                          <div class="field-block">
                            <span class="field-label">限制人数</span>
                            <el-input-number
                              v-model="item.limitCount"
                              :min="1"
                              :max="9999"
                              size="small"
                              style="width: 110px"
                              :disabled="isDisabled || group.enable == 0"
                            />
                          </div>
                        </div>
                      </div>
                    </div>

                    <div class="add-item-row">
                      <el-button
                        type="success"
                        size="small"
                        :disabled="isDisabled || group.enable == 0"
                        @click="addItem(group)"
                      >
                        <el-icon><Plus /></el-icon>
                        添加预约项
                      </el-button>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </el-col>

        <el-col :span="12" class="col-right">
          <div class="card card-mid-right">
            <div class="card-header">
              <el-icon class="card-icon icon-green"><Tickets /></el-icon>
              <span class="card-title">放号时间段（每天可开始预约时间）</span>
            </div>
            <div class="card-body card-body-limit" style="padding: 40px 30px">
              <span class="field-label">放号开始时间：</span>
              <el-time-picker
                v-model="formData.startTime"
                format="HH:mm"
                value-format="HH:mm"
                placeholder="开始时间"
                style="width: 150px"
                :disabled="isDisabled"
              />

              <span class="field-label" style="margin-left: 3vw">放号结束时间：</span>
              <el-time-picker
                v-model="formData.endTime"
                format="HH:mm"
                value-format="HH:mm"
                placeholder="结束时间"
                style="width: 150px"
                :disabled="isDisabled"
              />
            </div>
          </div>

          <div class="card card-bottom-right">
            <div class="card-header">
              <el-icon class="card-icon icon-purple"><User /></el-icon>
              <span class="card-title">单人名额限制（按自然周和月）</span>
              <el-button
                type="primary"
                size="small"
                :disabled="isDisabled || personLimits.length >= 3"
                @click="openPersonLimitDialog"
              >
                <el-icon><Plus /></el-icon>
                添加
              </el-button>
            </div>
            <div class="card-body card-body-limit">
              <div v-if="personLimits.length === 0" class="empty-limits-inline">
                <el-empty description="暂无限制，点击右上角添加" :image-size="40" />
              </div>
              <div v-else class="limit-list-inline">
                <div v-for="(limit, index) in personLimits" :key="index" class="limit-item-inline">
                  <span class="limit-type-badge">{{ getLimitTypeLabel(limit.type) }}</span>
                  <span class="limit-count-num">{{ limit.count }} <em>次</em></span>
                  <el-button
                    type="danger"
                    link
                    size="small"
                    :disabled="isDisabled"
                    @click="removePersonLimit(index)"
                  >
                    <el-icon><Delete /></el-icon>
                  </el-button>
                </div>
              </div>
            </div>
          </div>
        </el-col>
      </el-row>
    </el-form>

    <el-dialog v-model="totalLimitDialogVisible" title="添加总名额限制" width="420px" align-center>
      <el-form :model="totalLimitForm" label-width="100px" style="margin-bottom: 20px">
        <el-form-item label="限制类型" required>
          <el-select v-model="totalLimitForm.type" placeholder="请选择" style="width: 100%">
            <el-option
              v-for="item in availableTotalTypes"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="限制次数" required>
          <el-input-number
            v-model="totalLimitForm.count"
            :min="1"
            :max="9999"
            style="width: 100%"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="totalLimitDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmTotalLimit">确定</el-button>
      </template>
    </el-dialog>

    <el-dialog
      v-model="personLimitDialogVisible"
      title="添加单人名额限制"
      width="420px"
      align-center
    >
      <el-form :model="personLimitForm" label-width="100px" style="margin-bottom: 20px">
        <el-form-item label="限制类型" required>
          <el-select v-model="personLimitForm.type" placeholder="请选择" style="width: 100%">
            <el-option
              v-for="item in availablePersonTypes"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="限制次数" required>
          <el-input-number
            v-model="personLimitForm.count"
            :min="1"
            :max="9999"
            style="width: 100%"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="personLimitDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmPersonLimit">确定</el-button>
      </template>
    </el-dialog>

    <el-dialog
      v-model="weeklyDialogVisible"
      title="选择每周可预约日期"
      width="480px"
      align-center
      class="date-selector-dialog"
      :append-to-body="false"
    >
      <div class="date-selector-body">
        <div class="selector-title">请选择每周可预约的日期</div>
        <div class="week-days-grid">
          <div
            v-for="day in weekDays"
            :key="day.value"
            class="day-cell"
            :class="{ active: weeklySelectedDays.includes(day.value) }"
            @click="toggleWeekDay(day.value)"
          >
            {{ day.label }}
          </div>
        </div>
      </div>
      <template #footer>
        <el-button @click="weeklyDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmWeekly">确定</el-button>
      </template>
    </el-dialog>

    <el-dialog
      v-model="monthlyDialogVisible"
      title="选择每月可预约日期"
      width="560px"
      align-center
      class="date-selector-dialog"
      :append-to-body="false"
    >
      <div class="date-selector-body">
        <div class="selector-title">请选择每月可预约的日期</div>
        <div class="month-days-grid">
          <div
            v-for="day in 31"
            :key="day"
            class="day-cell"
            :class="{ active: monthlySelectedDays.includes(day) }"
            @click="toggleMonthDay(day)"
          >
            {{ day }}
          </div>
        </div>
      </div>
      <template #footer>
        <el-button @click="monthlyDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmMonthly">确定</el-button>
      </template>
    </el-dialog>

    <el-dialog
      v-model="customDialogVisible"
      title="选择自定义日期"
      width="420px"
      align-center
      :append-to-body="false"
    >
      <div class="date-selector-body">
        <div class="selector-title">请选择可预约的日期</div>
        <el-date-picker
          v-model="customSelectedDates"
          type="dates"
          placeholder="选择日期"
          value-format="YYYY-MM-DD"
          style="width: 100%"
        />
      </div>
      <template #footer>
        <el-button @click="customDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmCustom">确定</el-button>
      </template>
    </el-dialog>
  </ContentWrap>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { Setting, Calendar, User, Plus, Delete, Tickets, Minus } from '@element-plus/icons-vue'
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessageBox } from 'element-plus'
import { useUserStore } from '@/store/modules/user'
import {
  appointmentConfigADD,
  appointmentConfigGetByTenant,
  appointmentConfigUpdate
} from '@/api/elderly/elder/outwardRegustration'

const userStore = useUserStore()
const message = useMessage()

const formRef = ref<FormInstance>()
const submitting = ref(false)
const tenantIds = ref<number[]>([])
let organizationId = 0
let groupIdCounter = 0
let itemIdCounter = 0
const configId = ref<number | undefined>(undefined)

type LimitItem = { type: number; count: number }

type CycleType = 'daily' | 'weekly' | 'monthly' | 'custom'

type AppointmentItem = {
  id: number
  // 后端返回的真实 id，新增的 item 没有此字段；提交时回传给后端，删除时进入 deleteIds
  serverId?: number
  startTime: string
  endTime: string
  limitCount: number
}

type AppointmentGroup = {
  id: number
  cycleType: CycleType
  enable: number
  weeklyDays: number[]
  monthlyDays: number[]
  customDates: string[]
  items: AppointmentItem[]
}

type AppointmentConfigDO = {
  id?: number
  advanceDays?: number
  beginBookDays?: number
  enable?: number
  personDailyLimit?: number
  personMonthlyLimit?: number
  personWeeklyLimit?: number
  tenantId?: number
  totalDailyLimit?: number
  totalMonthlyLimit?: number
  totalWeeklyLimit?: number
  [property: string]: any
}

type AppointmentGroupDO = {
  id?: number
  beginTime?: string
  customDates?: string
  dateType?: string
  endTime?: string
  enable?: number
  limitCount?: number
  monthDays?: string
  tenantId?: number
  weekDays?: string
}

const limitTypeOptions = [
  { label: '每天', value: 1 },
  { label: '每周', value: 2 },
  { label: '每月', value: 3 }
]

const weekDays = [
  { label: '周一', value: 1 },
  { label: '周二', value: 2 },
  { label: '周三', value: 3 },
  { label: '周四', value: 4 },
  { label: '周五', value: 5 },
  { label: '周六', value: 6 },
  { label: '周日', value: 7 }
]

const limitTypeToFieldMap: Record<number, { total: string; person: string }> = {
  1: { total: 'totalDailyLimit', person: 'personDailyLimit' },
  2: { total: 'totalWeeklyLimit', person: 'personWeeklyLimit' },
  3: { total: 'totalMonthlyLimit', person: 'personMonthlyLimit' }
}

const cycleTypeToDateType = (cycleType: CycleType): string => cycleType.toUpperCase()
const dateTypeToCycleType = (dateType: string): CycleType => {
  const map: Record<string, CycleType> = {
    DAILY: 'daily',
    WEEKLY: 'weekly',
    MONTHLY: 'monthly',
    CUSTOM: 'custom'
  }
  return map[dateType] || 'daily'
}

const totalLimits = ref<LimitItem[]>([])
const personLimits = ref<LimitItem[]>([])
const appointmentGroups = ref<AppointmentGroup[]>([])
// 被删除的旧 item 后端 id 列表，提交时一并传给后端做物理删除
const deleteIds = ref<number[]>([])

const totalLimitDialogVisible = ref(false)
const personLimitDialogVisible = ref(false)
const weeklyDialogVisible = ref(false)
const monthlyDialogVisible = ref(false)
const customDialogVisible = ref(false)

const totalLimitForm = reactive<LimitItem>({ type: 1, count: 1 })
const personLimitForm = reactive<LimitItem>({ type: 1, count: 1 })

const currentEditGroup = ref<AppointmentGroup | null>(null)
const weeklySelectedDays = ref<number[]>([])
const monthlySelectedDays = ref<number[]>([])
const customSelectedDates = ref<string[]>([])

const availableTotalTypes = computed(() => {
  const usedTypes = totalLimits.value.map((item) => item.type)
  return limitTypeOptions.filter((item) => !usedTypes.includes(item.value))
})

const availablePersonTypes = computed(() => {
  const usedTypes = personLimits.value.map((item) => item.type)
  return limitTypeOptions.filter((item) => !usedTypes.includes(item.value))
})

const isDisabled = computed(() => !formData.appointmentEnabled)

const getLimitTypeLabel = (type: number) => {
  const found = limitTypeOptions.find((item) => item.value === type)
  return found ? found.label : ''
}

const getWeekDayLabel = (day: number) => {
  const found = weekDays.find((item) => item.value === day)
  return found ? found.label : ''
}

const defaultFormData = () => ({
  ruleType: 1,
  startDay: 0,
  advanceDays: 6,
  startTime: '08:00',
  endTime: '17:30',
  appointmentEnabled: true
})

const formData = reactive(defaultFormData())

const timeToMinutes = (time: string): number => {
  if (!time) return -1
  const [h, m] = time.split(':').map(Number)
  return h * 60 + m
}

const isOverlap = (item1: AppointmentItem, item2: AppointmentItem): boolean => {
  if (!item1.startTime || !item1.endTime || !item2.startTime || !item2.endTime) return false
  const s1 = timeToMinutes(item1.startTime)
  const e1 = timeToMinutes(item1.endTime)
  const s2 = timeToMinutes(item2.startTime)
  const e2 = timeToMinutes(item2.endTime)
  if (s1 < 0 || e1 < 0 || s2 < 0 || e2 < 0) return false
  if (s1 >= e1 || s2 >= e2) return false
  return s1 < e2 && s2 < e1
}

const getDateDayOfMonth = (dateStr: string): number => {
  const parts = dateStr.split('-')
  if (parts.length !== 3) return -1
  return Number(parts[2])
}

const getDateWeekDay = (dateStr: string): number => {
  const parts = dateStr.split('-').map(Number)
  if (parts.length !== 3) return -1
  const date = new Date(parts[0], parts[1] - 1, parts[2])
  const day = date.getDay()
  return day === 0 ? 7 : day
}

const checkTimeOverlap = (group: AppointmentGroup, changedIndex: number) => {
  const changedItem = group.items[changedIndex]
  if (!changedItem.startTime || !changedItem.endTime) return
  if (timeToMinutes(changedItem.startTime) >= timeToMinutes(changedItem.endTime)) {
    message.warning('结束时间必须晚于开始时间')
    return
  }
  for (let i = 0; i < group.items.length; i++) {
    if (i === changedIndex) continue
    if (isOverlap(changedItem, group.items[i])) {
      message.warning('时间段与其他预约项重叠，请调整时间')
      return
    }
  }
}

const addAppointmentGroup = () => {
  groupIdCounter++
  itemIdCounter++
  appointmentGroups.value.push({
    id: groupIdCounter,
    cycleType: 'daily',
    enable: 1,
    weeklyDays: [],
    monthlyDays: [],
    customDates: [],
    items: [
      {
        id: itemIdCounter,
        startTime: '08:00',
        endTime: '09:00',
        limitCount: 20
      }
    ]
  })
}

const removeGroup = (index: number) => {
  const group = appointmentGroups.value[index]
  // 该组下所有带 serverId 的 item 都是后端旧数据，删除时记录 id 交给后端物理删除
  group.items.forEach((item) => {
    if (item.serverId) {
      deleteIds.value.push(item.serverId)
    }
  })
  appointmentGroups.value.splice(index, 1)
}

const addItem = (group: AppointmentGroup) => {
  let lastEnd = '08:00'
  if (group.items.length > 0) {
    const lastItem = group.items[group.items.length - 1]
    if (lastItem.endTime) {
      lastEnd = lastItem.endTime
    }
  }
  const lastEndMin = timeToMinutes(lastEnd)
  let newStart = lastEnd
  let newEnd = ''
  if (lastEndMin >= 0) {
    const newStartMin = Math.min(lastEndMin + 60, 23 * 60)
    const newEndMin = Math.min(newStartMin + 60, 24 * 60)
    const sh = Math.floor(newStartMin / 60)
      .toString()
      .padStart(2, '0')
    const sm = (newStartMin % 60).toString().padStart(2, '0')
    const eh = Math.floor(newEndMin / 60)
      .toString()
      .padStart(2, '0')
    const em = (newEndMin % 60).toString().padStart(2, '0')
    newStart = `${sh}:${sm}`
    newEnd = `${eh}:${em}`
  }
  itemIdCounter++
  group.items.push({
    id: itemIdCounter,
    startTime: newStart,
    endTime: newEnd,
    limitCount: 20
  })
}

const removeItem = (group: AppointmentGroup, index: number) => {
  const item = group.items[index]
  // 带 serverId 表示是后端旧数据，删除时记录 id 交给后端物理删除
  if (item.serverId) {
    deleteIds.value.push(item.serverId)
  }
  group.items.splice(index, 1)
}

const setCycleType = (group: AppointmentGroup, cycleType: CycleType) => {
  if (cycleType === 'daily') {
    group.cycleType = 'daily'
  }
}

const openWeeklyDialog = (group: AppointmentGroup) => {
  currentEditGroup.value = group
  weeklySelectedDays.value = [...group.weeklyDays]
  weeklyDialogVisible.value = true
}

const toggleWeekDay = (day: number) => {
  const idx = weeklySelectedDays.value.indexOf(day)
  if (idx > -1) {
    weeklySelectedDays.value.splice(idx, 1)
  } else {
    weeklySelectedDays.value.push(day)
    weeklySelectedDays.value.sort((a, b) => a - b)
  }
}

const confirmWeekly = () => {
  if (currentEditGroup.value) {
    currentEditGroup.value.weeklyDays = [...weeklySelectedDays.value]
    currentEditGroup.value.cycleType = 'weekly'
  }
  weeklyDialogVisible.value = false
  currentEditGroup.value = null
  weeklySelectedDays.value = []
}

const openMonthlyDialog = (group: AppointmentGroup) => {
  currentEditGroup.value = group
  monthlySelectedDays.value = [...group.monthlyDays]
  monthlyDialogVisible.value = true
}

const toggleMonthDay = (day: number) => {
  const idx = monthlySelectedDays.value.indexOf(day)
  if (idx > -1) {
    monthlySelectedDays.value.splice(idx, 1)
  } else {
    monthlySelectedDays.value.push(day)
    monthlySelectedDays.value.sort((a, b) => a - b)
  }
}

const confirmMonthly = () => {
  if (currentEditGroup.value) {
    currentEditGroup.value.monthlyDays = [...monthlySelectedDays.value]
    currentEditGroup.value.cycleType = 'monthly'
  }
  monthlyDialogVisible.value = false
  currentEditGroup.value = null
  monthlySelectedDays.value = []
}

const openCustomDialog = (group: AppointmentGroup) => {
  currentEditGroup.value = group
  customSelectedDates.value = [...group.customDates]
  customDialogVisible.value = true
}

const confirmCustom = () => {
  if (currentEditGroup.value) {
    currentEditGroup.value.customDates = [...customSelectedDates.value]
    currentEditGroup.value.cycleType = 'custom'
  }
  customDialogVisible.value = false
  currentEditGroup.value = null
  customSelectedDates.value = []
}

const openTotalLimitDialog = () => {
  if (availableTotalTypes.value.length === 0) return
  totalLimitForm.type = availableTotalTypes.value[0].value
  totalLimitForm.count = 1
  totalLimitDialogVisible.value = true
}

const confirmTotalLimit = () => {
  if (!totalLimitForm.type || !totalLimitForm.count) {
    message.warning('请填写完整信息')
    return
  }
  totalLimits.value.push({ type: totalLimitForm.type, count: totalLimitForm.count })
  totalLimitDialogVisible.value = false
}

const removeTotalLimit = (index: number) => {
  totalLimits.value.splice(index, 1)
}

const openPersonLimitDialog = () => {
  if (availablePersonTypes.value.length === 0) return
  personLimitForm.type = availablePersonTypes.value[0].value
  personLimitForm.count = 1
  personLimitDialogVisible.value = true
}

const confirmPersonLimit = () => {
  if (!personLimitForm.type || !personLimitForm.count) {
    message.warning('请填写完整信息')
    return
  }
  personLimits.value.push({ type: personLimitForm.type, count: personLimitForm.count })
  personLimitDialogVisible.value = false
}

const removePersonLimit = (index: number) => {
  personLimits.value.splice(index, 1)
}

const validatePersonLimits = (): string | null => {
  const daily = personLimits.value.find((item) => item.type === 1)
  const weekly = personLimits.value.find((item) => item.type === 2)
  const monthly = personLimits.value.find((item) => item.type === 3)

  if (daily && daily.count <= 0) {
    return '单人每日名额限制必须大于0'
  }
  if (weekly && weekly.count <= 0) {
    return '单人每周名额限制必须大于0'
  }
  if (monthly && monthly.count <= 0) {
    return '单人每月名额限制必须大于0'
  }
  if (monthly && weekly && monthly.count <= weekly.count) {
    return '单人每月名额限制必须大于每周名额限制'
  }
  if (weekly && daily && weekly.count <= daily.count) {
    return '单人每周名额限制必须大于每日名额限制'
  }

  return null
}

const validateAdvanceDays = (_rule: any, value: any, callback: any) => {
  if (!value || value < 1) {
    callback(new Error('提前预约天数最少为1'))
  } else {
    callback()
  }
}

const formRules: FormRules = reactive({
  ruleType: [{ required: true, message: '请选择放号规则', trigger: 'change' }],
  startDay: [{ required: true, message: '请选择开始预约日', trigger: 'change' }],
  advanceDays: [
    { required: true, message: '请输入提前预约天数', trigger: 'change' },
    { validator: validateAdvanceDays, trigger: 'change' }
  ]
})

const changeTen = (i: any[]) => {
  if (i.length > 1) {
    message.error('只能选择一个机构!')
    if (i[0].length > 1) {
      tenantIds.value = [i[0][1]]
    } else {
      tenantIds.value = []
    }
  }
  if (tenantIds.value.length > 0) {
    organizationId = tenantIds.value[0]
    getSetting()
  }
}

const parseGroups = (groups: AppointmentGroupDO[]): AppointmentGroup[] => {
  const map = new Map<string, AppointmentGroup>()
  groups.forEach((g) => {
    const cycleType = dateTypeToCycleType(g.dateType || 'DAILY')
    const weekDays = g.weekDays || ''
    const monthDays = g.monthDays || ''
    const customDates = g.customDates || ''
    const enable = g.enable ?? 1
    const key = `${cycleType}_${weekDays}_${monthDays}_${customDates}`
    if (!map.has(key)) {
      groupIdCounter++
      map.set(key, {
        id: groupIdCounter,
        cycleType,
        enable,
        weeklyDays: weekDays ? weekDays.split(',').map(Number) : [],
        monthlyDays: monthDays ? monthDays.split(',').map(Number) : [],
        customDates: customDates ? customDates.split(',') : [],
        items: []
      })
    }
    const group = map.get(key)!
    itemIdCounter++
    group.items.push({
      id: itemIdCounter,
      // 保留后端真实 id，用于更新时回传和删除时入 deleteIds
      serverId: g.id,
      startTime: g.beginTime || '',
      endTime: g.endTime || '',
      limitCount: g.limitCount || 100
    })
  })
  return Array.from(map.values())
}

const getSetting = async () => {
  try {
    const res = await appointmentConfigGetByTenant({ tenantId: organizationId })
    if (res && res.config) {
      const config = res.config
      configId.value = config.id
      let startTime = defaultFormData().startTime
      let endTime = defaultFormData().endTime
      if (config.openTimeSlot && typeof config.openTimeSlot === 'string') {
        const [s, e] = config.openTimeSlot.split('-')
        if (s && e) {
          startTime = s
          endTime = e
        }
      }
      Object.assign(formData, {
        ruleType: 1,
        startDay: config.beginBookDays ?? 0,
        advanceDays: config.advanceDays ?? 0,
        appointmentEnabled: config.enabled === 1,
        startTime,
        endTime
      })
      totalLimits.value = []
      personLimits.value = []
      ;[1, 2, 3].forEach((type) => {
        const field = limitTypeToFieldMap[type]
        const totalVal = config[field.total]
        if (totalVal !== undefined && totalVal !== null && totalVal > 0) {
          totalLimits.value.push({ type, count: totalVal })
        }
        const personVal = config[field.person]
        if (personVal !== undefined && personVal !== null && personVal > 0) {
          personLimits.value.push({ type, count: personVal })
        }
      })
      groupIdCounter = 0
      itemIdCounter = 0
      // 重新拉取配置后，本地 deleteIds 已无意义，清空避免脏数据
      deleteIds.value = []
      appointmentGroups.value = parseGroups(res.group || [])
      if (appointmentGroups.value.length > 0) {
        groupIdCounter = Math.max(...appointmentGroups.value.map((g) => g.id))
        let maxItemId = 0
        appointmentGroups.value.forEach((g) => {
          if (g.items && g.items.length > 0) {
            maxItemId = Math.max(maxItemId, ...g.items.map((it) => it.id))
          }
        })
        itemIdCounter = maxItemId
      }
    } else {
      configId.value = undefined
      Object.assign(formData, defaultFormData())
      totalLimits.value = []
      personLimits.value = []
      appointmentGroups.value = []
    }
  } catch (e) {
    console.log('获取设置失败', e)
  }
}

const validateGroups = (): string | null => {
  if (appointmentGroups.value.length === 0) {
    return '请至少添加一个预约组'
  }

  const dailyGroups = appointmentGroups.value.filter((g) => g.cycleType === 'daily')
  if (dailyGroups.length > 0 && appointmentGroups.value.length > 1) {
    return '选择每天时，只能有一个预约组'
  }

  const weeklyGroups = appointmentGroups.value.filter((g) => g.cycleType === 'weekly')
  const monthlyGroups = appointmentGroups.value.filter((g) => g.cycleType === 'monthly')

  if (weeklyGroups.length > 0 && monthlyGroups.length > 0) {
    return '每周和每月预约组不能同时存在'
  }

  if (weeklyGroups.length > 1) {
    const usedDays = new Set<number>()
    for (const group of weeklyGroups) {
      for (const day of group.weeklyDays) {
        if (usedDays.has(day)) {
          return '不同每周预约组存在重复的星期'
        }
        usedDays.add(day)
      }
    }
  }

  if (monthlyGroups.length > 1) {
    const usedDays = new Set<number>()
    for (const group of monthlyGroups) {
      for (const day of group.monthlyDays) {
        if (usedDays.has(day)) {
          return '不同每月预约组存在重复的日期'
        }
        usedDays.add(day)
      }
    }
  }

  const customGroups = appointmentGroups.value.filter((g) => g.cycleType === 'custom')
  if (customGroups.length > 1) {
    const usedDates = new Set<string>()
    for (const group of customGroups) {
      for (const date of group.customDates) {
        if (usedDates.has(date)) {
          return '不同自定义预约组存在重复的日期'
        }
        usedDates.add(date)
      }
    }
  }

  if (monthlyGroups.length > 0 && customGroups.length > 0) {
    const usedDays = new Set<number>()
    for (const group of monthlyGroups) {
      for (const day of group.monthlyDays) {
        usedDays.add(day)
      }
    }
    for (const group of customGroups) {
      for (const date of group.customDates) {
        const day = getDateDayOfMonth(date)
        if (day > 0 && usedDays.has(day)) {
          return `自定义日期 ${date} 与每月预约的 ${day}号冲突`
        }
      }
    }
  }

  if (weeklyGroups.length > 0 && customGroups.length > 0) {
    const usedDays = new Set<number>()
    for (const group of weeklyGroups) {
      for (const day of group.weeklyDays) {
        usedDays.add(day)
      }
    }
    for (const group of customGroups) {
      for (const date of group.customDates) {
        const day = getDateWeekDay(date)
        if (day > 0 && usedDays.has(day)) {
          return `自定义日期 ${date} 与每周预约冲突`
        }
      }
    }
  }

  for (const group of appointmentGroups.value) {
    if (group.cycleType === 'weekly' && group.weeklyDays.length === 0) {
      return '存在未设置每周可预约日期的预约组'
    }
    if (group.cycleType === 'monthly' && group.monthlyDays.length === 0) {
      return '存在未设置每月可预约日期的预约组'
    }
    if (group.cycleType === 'custom' && group.customDates.length === 0) {
      return '存在未设置自定义日期的预约组'
    }
  }

  return null
}

const handleSubmit = async () => {
  if (!formRef.value) return
  if (!organizationId) {
    await ElMessageBox.alert('请选择机构!', '警告', { type: 'warning' })
    return
  }
  if (!formData.advanceDays || formData.advanceDays < 1) {
    await ElMessageBox.alert('提前预约天数最少为1', '警告', { type: 'warning' })
    return
  }
  if (
    formData.startTime &&
    formData.endTime &&
    timeToMinutes(formData.startTime) >= timeToMinutes(formData.endTime)
  ) {
    await ElMessageBox.alert('放号开始时间不能晚于或等于结束时间', '警告', { type: 'warning' })
    return
  }
  const groupError = validateGroups()
  if (groupError) {
    await ElMessageBox.alert(groupError, '警告', { type: 'warning' })
    return
  }
  const personLimitError = validatePersonLimits()
  if (personLimitError) {
    await ElMessageBox.alert(personLimitError, '警告', { type: 'warning' })
    return
  }
  for (const group of appointmentGroups.value) {
    for (let i = 0; i < group.items.length; i++) {
      const item = group.items[i]
      if (!item.limitCount || item.limitCount <= 0) {
        await ElMessageBox.alert('限制人数必须大于0', '警告', { type: 'warning' })
        return
      }
      if (
        item.startTime &&
        item.endTime &&
        timeToMinutes(item.startTime) >= timeToMinutes(item.endTime)
      ) {
        await ElMessageBox.alert('存在开始时间晚于或等于结束时间的预约项，请检查', '警告', {
          type: 'warning'
        })
        return
      }
      for (let j = i + 1; j < group.items.length; j++) {
        if (isOverlap(item, group.items[j])) {
          await ElMessageBox.alert('同一预约组内存在时间段重叠的预约项，请检查', '警告', {
            type: 'warning'
          })
          return
        }
      }
    }
  }
  try {
    await formRef.value.validate()
    submitting.value = true
    const config: AppointmentConfigDO = {
      id: configId.value,
      tenantId: organizationId,
      advanceDays: formData.advanceDays,
      beginBookDays: formData.startDay,
      enabled: formData.appointmentEnabled ? 1 : 0,
      openTimeSlot:
        formData.startTime && formData.endTime
          ? `${formData.startTime}-${formData.endTime}`
          : undefined
    }
    totalLimits.value.forEach((limit) => {
      const field = limitTypeToFieldMap[limit.type]
      if (field) {
        config[field.total] = limit.count
      }
    })
    // 单人名额：未设置或删除时传 -1（后端表示无限制）
    ;[1, 2, 3].forEach((type) => {
      const field = limitTypeToFieldMap[type]
      if (field) {
        const limit = personLimits.value.find((item) => item.type === type)
        config[field.person] = limit ? limit.count : -1
      }
    })
    const group: AppointmentGroupDO[] = []
    appointmentGroups.value.forEach((g) => {
      const dateType = cycleTypeToDateType(g.cycleType)
      const weekDays = g.weeklyDays.join(',') || undefined
      const monthDays = g.monthlyDays.join(',') || undefined
      const customDates = g.customDates.join(',') || undefined
      const enable = g.enable || 0
      g.items.forEach((item) => {
        group.push({
          // 旧数据带回后端 id 用于更新；新增数据不带 id，后端按新增处理
          ...(item.serverId ? { id: item.serverId } : {}),
          dateType,
          weekDays,
          monthDays,
          customDates,
          beginTime: item.startTime,
          enable: enable,
          endTime: item.endTime,
          limitCount: item.limitCount,
          tenantId: organizationId
        })
      })
    })
    const params = { config, group, deleteIds: deleteIds.value }
    const res = configId.value
      ? await appointmentConfigUpdate(params)
      : await appointmentConfigADD(params)
    if (res) {
      message.success('设置成功!')
      await getSetting()
    }
  } catch (error: any) {
    if (error?.message) {
      await ElMessageBox.alert(error.message, '警告', { type: 'warning' })
    }
  } finally {
    submitting.value = false
  }
}

onMounted(() => {
  if (userStore.orgTenantId.length > 0) {
    tenantIds.value = [userStore.orgTenantId[0]] as number[]
    organizationId = tenantIds.value[0]
    getSetting()
  }
})
</script>

<style scoped lang="scss">
.setting-form {
  padding-top: 16px;

  .main-row {
    display: flex;
    align-items: stretch;
  }

  .col-left,
  .col-right {
    display: flex;
    flex-direction: column;
    gap: 20px;
  }

  .card {
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
    display: flex;
    flex-direction: column;
    overflow: hidden;

    &-top-left,
    &-mid-right {
      flex: 0 0 auto;
    }

    &-bottom-left,
    &-bottom-right {
      flex: 1 1 auto;
      min-height: 0;
    }
  }

  .card-header {
    display: flex;
    align-items: center;
    padding: 16px 20px;
    border-bottom: 1px solid #f0f0f0;
    background: linear-gradient(90deg, #fafbfc 0%, #ffffff 100%);

    .card-icon {
      width: 28px;
      height: 28px;
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 6px;
      margin-right: 10px;
      color: #fff;
      font-size: 16px;

      &.icon-blue {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      }
      &.icon-green {
        background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
      }
      &.icon-orange {
        background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
      }
      &.icon-purple {
        background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
      }
    }

    .card-title {
      font-size: 16px;
      font-weight: 600;
      color: #303133;
      flex: 1;
    }

    .master-switch {
      display: flex;
      align-items: center;
      gap: 8px;

      .switch-label {
        font-size: 14px;
        color: #606266;
      }
    }
  }

  .card-body {
    padding: 20px;
    flex: 1;
  }

  .empty-groups {
    padding: 30px 0;
  }

  .card-body-groups {
    padding: 16px 20px;
    max-height: 560px;
    overflow-y: auto;
  }

  .group-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
  }

  .group-card {
    background-color: #fff;
    border: 1px solid #e4e7ed;
    border-radius: 8px;
    padding: 16px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
  }

  .group-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
    flex-wrap: wrap;

    .group-label {
      font-size: 14px;
      font-weight: 600;
      color: #303133;
    }

    .cycle-buttons {
      display: flex;
      gap: 6px;
      flex: 1;
      flex-wrap: wrap;
    }
  }

  .group-dates {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    padding: 12px 0;
    border-top: 1px dashed #ebeef5;
    border-bottom: 1px dashed #ebeef5;

    .dates-label {
      font-size: 13px;
      color: #606266;
      margin-right: 4px;
    }

    .date-tag {
      margin: 2px 0;
    }
  }

  .group-items-section {
    margin-top: 14px;
  }

  .items-header {
    display: flex;
    align-items: center;
    margin-bottom: 10px;

    .items-title {
      font-size: 14px;
      font-weight: 600;
      color: #303133;
    }

    .items-sub {
      font-size: 12px;
      color: #909399;
      margin-left: 8px;
    }
  }

  .empty-items {
    text-align: center;
    padding: 20px 0;
    font-size: 13px;
    color: #c0c4cc;
    background-color: #fafafa;
    border-radius: 6px;
    border: 1px dashed #dcdfe6;
  }

  .items-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 12px;
  }

  .item-row {
    display: flex;
    align-items: center;
    gap: 10px;
    background-color: #f8f9fa;
    border: 1px solid #e9ecef;
    border-radius: 6px;
    padding: 10px 12px;
  }

  .item-delete-btn {
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 4px;
    color: #f56c6c;
    cursor: pointer;
    transition: all 0.2s;
    flex-shrink: 0;
    margin-top: 6px;

    &:hover {
      background-color: #fef0f0;
    }

    &.disabled {
      pointer-events: none;
      opacity: 0.4;
      cursor: not-allowed;
    }
  }

  .item-fields {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
  }

  .field-block {
    display: flex;
    align-items: center;
    gap: 6px;

    .field-label {
      font-size: 13px;
      color: #606266;
      white-space: nowrap;
    }

    .time-sep {
      font-size: 13px;
      color: #909399;
    }
  }

  .add-item-row {
    display: flex;
    justify-content: center;
  }
}

.fixed-save-bar {
  width: 100%;
  display: flex;
  justify-content: flex-end;
}

:deep(.el-form-item) {
  margin-bottom: 18px;

  &:last-child {
    margin-bottom: 0;
  }
}

:deep(.el-form-item__content) {
  display: flex;
  align-items: center;
}

:deep(.date-selector-dialog) {
  .date-selector-body {
    padding: 6px 0;

    .selector-title {
      font-size: 14px;
      color: #606266;
      margin-bottom: 16px;
    }

    .week-days-grid {
      display: grid;
      grid-template-columns: repeat(7, 1fr);
      gap: 10px;
    }

    .month-days-grid {
      display: grid;
      grid-template-columns: repeat(7, 1fr);
      gap: 8px;
    }

    .day-cell {
      height: 42px;
      display: flex;
      align-items: center;
      justify-content: center;
      border: 2px solid #e4e7ed;
      border-radius: 8px;
      cursor: pointer;
      font-size: 14px;
      color: #606266;
      background-color: #fff;
      transition: all 0.2s ease;
      user-select: none;

      &:hover {
        border-color: #67c23a;
        color: #67c23a;
        background-color: #f0f9eb;
      }

      &.active {
        border-color: #67c23a;
        background-color: #67c23a;
        color: #fff;
        font-weight: 500;
        box-shadow: 0 2px 6px rgba(103, 194, 58, 0.3);
      }
    }
  }
}

.limit-list-inline {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.limit-item-inline {
  display: flex;
  align-items: center;
  padding: 10px 14px;
  background-color: #f8f9fa;
  border-radius: 6px;
  border: 1px solid #e9ecef;

  .limit-type-badge {
    font-size: 12px;
    font-weight: 600;
    color: #fff;
    padding: 3px 10px;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border-radius: 4px;
    margin-right: 16px;
  }

  .limit-count-num {
    flex: 1;
    font-size: 16px;
    font-weight: 600;
    color: #f56c6c;

    em {
      font-style: normal;
      font-size: 13px;
      font-weight: 400;
      color: #909399;
      margin-left: 2px;
    }
  }
}
</style>
