<template>
  <div class="schedule-cycle-picker">
    <div class="text-caption text-medium-emphasis mb-2">开始执行周期</div>

    <v-row dense class="mb-2 align-center">
      <v-col cols="auto" class="cycle-type-col">
        <span v-if="singleShot" class="cycle-type-fixed text-body-2">当天</span>
        <v-select
          v-else
          :model-value="modelValue.type === 'custom' ? null : modelValue.type"
          :items="cycleTypeOptions"
          item-title="label"
          item-value="value"
          label="重复方式"
          variant="outlined"
          density="compact"
          hide-details
          class="cycle-type-select"
          @update:model-value="onTypeChange"
        />
      </v-col>

      <!-- 当天 / 每 N 天 / 每周 / 每月：时:分 -->
      <template v-if="showTimeOfDay">
        <v-col cols="auto" class="time-col">
          <v-text-field
            :model-value="modelValue.hour"
            label="时"
            type="number"
            min="0"
            max="23"
            variant="outlined"
            density="compact"
            hide-details
            @update:model-value="patch({ hour: toNum($event, 0, 23) })"
          />
        </v-col>
        <v-col cols="auto" class="time-col">
          <v-text-field
            :model-value="modelValue.minute"
            label="分"
            type="number"
            min="0"
            max="59"
            variant="outlined"
            density="compact"
            hide-details
            @update:model-value="patch({ minute: toNum($event, 0, 59) })"
          />
        </v-col>
      </template>

      <!-- 每小时 / 每 N 小时：第几分 -->
      <template v-if="!singleShot && (modelValue.type === 'hour' || modelValue.type === 'hour-n')">
        <v-col cols="auto" class="time-col-wide">
          <v-text-field
            :model-value="modelValue.minute"
            label="第几分"
            type="number"
            min="0"
            max="59"
            variant="outlined"
            density="compact"
            hide-details
            @update:model-value="patch({ minute: toNum($event, 0, 59) })"
          />
        </v-col>
      </template>
    </v-row>

    <div class="text-caption text-medium-emphasis mb-2">
      {{ cycleHint }}
    </div>

    <!-- 每 N 天 -->
    <v-text-field
      v-if="!singleShot && modelValue.type === 'day-n'"
      :model-value="modelValue.interval"
      label="天数 N"
      type="number"
      min="1"
      max="365"
      variant="outlined"
      density="compact"
      hint="从每月 1 日起每 N 天执行（与宝塔一致）"
      persistent-hint
      class="mb-2"
      @update:model-value="patch({ interval: toNum($event, 1, 365) })"
    />

    <!-- 每 N 小时 -->
    <v-text-field
      v-if="!singleShot && modelValue.type === 'hour-n'"
      :model-value="modelValue.interval"
      label="小时 N"
      type="number"
      min="1"
      max="23"
      variant="outlined"
      density="compact"
      class="mb-2"
      @update:model-value="patch({ interval: toNum($event, 1, 23) })"
    />

    <!-- 每 N 分钟 -->
    <v-text-field
      v-if="!singleShot && modelValue.type === 'minute-n'"
      :model-value="modelValue.interval"
      label="分钟 N"
      type="number"
      :min="SCHEDULE_MIN_INTERVAL_MINUTES"
      max="59"
      variant="outlined"
      density="compact"
      hint="从整点起每 N 分钟触发一次"
      persistent-hint
      class="mb-2"
      @update:model-value="patch({ interval: toNum($event, SCHEDULE_MIN_INTERVAL_MINUTES, 59) })"
    />

    <!-- 每周 -->
    <v-select
      v-if="!singleShot && modelValue.type === 'week'"
      :model-value="modelValue.week"
      :items="WEEKDAY_OPTIONS"
      item-title="label"
      item-value="value"
      label="星期"
      variant="outlined"
      density="compact"
      class="mb-2"
      @update:model-value="patch({ week: toNum($event, 0, 6) })"
    />

    <!-- 每月 -->
    <v-text-field
      v-if="!singleShot && modelValue.type === 'month'"
      :model-value="modelValue.monthDay"
      label="每月几号"
      type="number"
      min="1"
      max="31"
      variant="outlined"
      density="compact"
      class="mb-2"
      @update:model-value="patch({ monthDay: toNum($event, 1, 31) })"
    />

    <!-- 无法反解析的历史 Cron -->
    <template v-if="modelValue.type === 'custom'">
      <v-alert type="warning" density="compact" variant="tonal" class="mb-2 text-caption">
        当前 Cron 无法映射为可视化周期，可保留原表达式或改用上方周期类型重建。
      </v-alert>
      <v-text-field
        :model-value="modelValue.customCron"
        label="Cron 表达式（5 字段）"
        variant="outlined"
        density="compact"
        class="mb-2"
        @update:model-value="patch({ customCron: String($event ?? '') })"
      />
      <v-btn size="small" variant="tonal" color="primary" class="mb-2" @click="switchToVisual">
        改用可视化周期
      </v-btn>
    </template>

    <div v-if="previewLabel" class="text-caption text-medium-emphasis">
      预览：{{ previewLabel }}
      <span v-if="previewCron" class="ms-1">（{{ previewCron }}）</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, watch } from 'vue'
import {
  CYCLE_TYPE_OPTIONS,
  WEEKDAY_OPTIONS,
  buildCronFromCycle,
  defaultCycleConfig,
  formatCycleLabel,
  SCHEDULE_MIN_INTERVAL_MINUTES,
  type ScheduleCycleConfig,
  type ScheduleCycleType,
} from '@/utils/scheduleCycle'

const props = defineProps<{
  modelValue: ScheduleCycleConfig
  /** 单次执行：在下一匹配时刻跑一次 */
  singleShot?: boolean
}>()

const emit = defineEmits<{
  'update:modelValue': [value: ScheduleCycleConfig]
}>()

const cycleTypeOptions = CYCLE_TYPE_OPTIONS

const singleShot = computed(() => props.singleShot === true)

const showTimeOfDay = computed(() => {
  if (singleShot.value) return true
  return ['day', 'day-n', 'week', 'month'].includes(props.modelValue.type)
})

const cycleHint = computed(() => {
  const tz = '时间为北京时间（Asia/Shanghai）'
  if (singleShot.value) {
    return `单次：当天指定时:分，在下一匹配时刻执行一次（不含日期选择）。${tz}`
  }
  return `循环：按重复方式与时:分持续执行。${tz}`
})

/** 单次模式固定为「当天」时:分，不出现「重复方式」 */
watch(
  () => props.singleShot,
  (isOnce) => {
    if (!isOnce) return
    if (props.modelValue.type === 'custom') return
    if (props.modelValue.type === 'day') return
    emit('update:modelValue', { ...defaultCycleConfig(), ...props.modelValue, type: 'day' })
  },
  { immediate: true },
)

const previewLabel = computed(() => {
  try {
    return formatCycleLabel(props.modelValue)
  } catch {
    return ''
  }
})

const previewCron = computed(() => {
  try {
    if (props.modelValue.type === 'custom' && !props.modelValue.customCron.trim()) return ''
    return buildCronFromCycle(props.modelValue)
  } catch {
    return ''
  }
})

function toNum(raw: unknown, min: number, max: number): number {
  const n = Math.floor(Number(raw))
  if (Number.isNaN(n)) return min
  return Math.min(max, Math.max(min, n))
}

function patch(partial: Partial<ScheduleCycleConfig>) {
  emit('update:modelValue', { ...props.modelValue, ...partial })
}

function onTypeChange(type: ScheduleCycleType | null) {
  if (!type) return
  const next = { ...defaultCycleConfig(), ...props.modelValue, type }
  emit('update:modelValue', next)
}

function switchToVisual() {
  emit('update:modelValue', { ...defaultCycleConfig(), type: 'day' })
}
</script>

<style scoped>
.cycle-type-col {
  flex: 0 0 auto;
}
.cycle-type-select {
  width: 7.5rem;
  max-width: 7.5rem;
}
.cycle-type-fixed {
  display: inline-flex;
  align-items: center;
  height: 40px;
  padding: 0 4px;
  font-weight: 500;
  white-space: nowrap;
}
.time-col {
  flex: 0 0 auto;
  width: 4.5rem;
  max-width: 4.5rem;
}
.time-col-wide {
  flex: 0 0 auto;
  width: 5.5rem;
  max-width: 5.5rem;
}
</style>
