<script setup lang="ts">
import { ref, computed, watch, onMounted, useSlots } from 'vue'

const slots = useSlots()

// 合并所有属性
interface Props {
  // 表单字段属性
  df?: any
  record?: Record<string, any>
  canEdit?: boolean
  ctx?: any
  // Cron编辑器属性
  modelValue?: string
  name?: string
}

interface Emits {
  (e: 'update:modelValue', value: string): void
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: '* * * * *',
  name: 'trigger_time'
})

// Label布局：上下结构(vertical) 或 左右结构(horizontal)
const labelLayout = computed(() => props.df?.label_layout || 'vertical')

const emit = defineEmits<Emits>()

// 响应式数据
const selectedType = ref('')
const showParams = ref(false)
const showPreview = ref(false)
const isAdvancedMode = ref(false)
const copying = ref(false)

// 参数对象
const params = ref({
  nMinute: 5,
  nHour: 1,
  hour: 0,
  minute: 0,
  weekday: 0,
  day: 1
})

// Cron 表达式
const cronExpression = ref(props.modelValue || '* * * * *')

// 计算属性
const cronText = computed(() => {
  return cronToText(cronExpression.value)
})

const isValidCron = computed(() => {
  return /^\s*([0-9\*\/\-,]+\s+){4,6}[0-9\*\/\-,]+\s*$/.test(cronExpression.value)
})

// 方法
const cronToText = (expr: string): string => {
  if (expr === '* * * * *') return '每分钟'
  if (/^\*\/(\d+) \* \* \* \*$/.test(expr)) return `每${expr.match(/^\*\/(\d+)/)?.[1]}分钟`
  if (expr === '0 * * * *') return '每小时'
  if (/^0 \*\/(\d+) \* \* \*$/.test(expr)) return `每${expr.match(/^0 \*\/(\d+)/)?.[1]}小时`
  if (/^\d+ \d+ \* \* \*$/.test(expr)) {
    const [m, h] = expr.split(' ')
    return `每天 ${h}时${m}分`
  }
  if (/^\d+ \d+ \* \* \d+$/.test(expr)) {
    const [m, h, , , w] = expr.split(' ')
    const week = ['周日','周一','周二','周三','周四','周五','周六']
    return `每${week[parseInt(w)||0]} ${h}时${m}分`
  }
  if (/^\d+ \d+ \d+ \* \*$/.test(expr)) {
    const [m, h, d] = expr.split(' ')
    return `每月${d}日 ${h}时${m}分`
  }
  return ''
}

const updateCron = () => {
  let cron = ''
  
  switch (selectedType.value) {
    case 'every_minute':
      cron = '* * * * *'
      break
    case 'every_n_minute':
      cron = `*/${params.value.nMinute} * * * *`
      break
    case 'every_hour':
      cron = '0 * * * *'
      break
    case 'every_n_hour':
      cron = `0 */${params.value.nHour} * * *`
      break
    case 'every_day':
      cron = `${params.value.minute} ${params.value.hour} * * *`
      break
    case 'every_week':
      cron = `${params.value.minute} ${params.value.hour} * * ${params.value.weekday}`
      break
    case 'every_month':
      cron = `${params.value.minute} ${params.value.hour} ${params.value.day} * *`
      break
    default:
      cron = '* * * * *'
  }
  
  cronExpression.value = cron
  emit('update:modelValue', cron)
}

const onTypeChange = () => {
  if (selectedType.value) {
    showParams.value = true
    showPreview.value = true
    isAdvancedMode.value = false
    updateCron()
  } else {
    showParams.value = false
    if (cronExpression.value && cronExpression.value !== '* * * * *') {
      showPreview.value = true
    } else {
      showPreview.value = true
    }
  }
}

const toggleAdvancedMode = () => {
  isAdvancedMode.value = !isAdvancedMode.value
  if (isAdvancedMode.value) {
    showParams.value = false
  } else {
    showParams.value = true
  }
}

const onAdvancedInput = () => {
  emit('update:modelValue', cronExpression.value)
}

const copyCron = async () => {
  try {
    await navigator.clipboard.writeText(cronExpression.value)
    copying.value = true
    setTimeout(() => {
      copying.value = false
    }, 1200)
  } catch (err) {
    console.error('复制失败:', err)
  }
}

const parseCronExpression = (expr: string) => {
  if (!expr || expr === '* * * * *') return
  
  // 解析每N分钟
  const nMinuteMatch = expr.match(/^\*\/(\d+) \* \* \* \*$/)
  if (nMinuteMatch) {
    selectedType.value = 'every_n_minute'
    params.value.nMinute = parseInt(nMinuteMatch[1])
    return
  }
  
  // 解析每N小时
  const nHourMatch = expr.match(/^0 \*\/(\d+) \* \* \*$/)
  if (nHourMatch) {
    selectedType.value = 'every_n_hour'
    params.value.nHour = parseInt(nHourMatch[1])
    return
  }
  
  // 解析每天
  const dailyMatch = expr.match(/^(\d+) (\d+) \* \* \*$/)
  if (dailyMatch) {
    selectedType.value = 'every_day'
    params.value.minute = parseInt(dailyMatch[1])
    params.value.hour = parseInt(dailyMatch[2])
    return
  }
  
  // 解析每周
  const weeklyMatch = expr.match(/^(\d+) (\d+) \* \* (\d+)$/)
  if (weeklyMatch) {
    selectedType.value = 'every_week'
    params.value.minute = parseInt(weeklyMatch[1])
    params.value.hour = parseInt(weeklyMatch[2])
    params.value.weekday = parseInt(weeklyMatch[3])
    return
  }
  
  // 解析每月
  const monthlyMatch = expr.match(/^(\d+) (\d+) (\d+) \* \*$/)
  if (monthlyMatch) {
    selectedType.value = 'every_month'
    params.value.minute = parseInt(monthlyMatch[1])
    params.value.hour = parseInt(monthlyMatch[2])
    params.value.day = parseInt(monthlyMatch[3])
    return
  }
  
  // 默认情况，进入高级模式
  isAdvancedMode.value = true
}

// 监听外部值变化
watch(() => props.modelValue, (newValue) => {
  if (newValue && newValue !== cronExpression.value) {
    cronExpression.value = newValue
    parseCronExpression(newValue)
    if (newValue && newValue !== '* * * * *') {
      showPreview.value = true
    }
  }
})

// 初始化
onMounted(() => {
  cronExpression.value = props.modelValue || '* * * * *'
  if (props.modelValue && props.modelValue !== '* * * * *') {
    parseCronExpression(props.modelValue)
    showPreview.value = true
  } else {
    showPreview.value = true
  }
})
</script>

<template>
  <div :class="['field-wrapper', `layout-${labelLayout}`, { 'form-builder-control': slots.label }]">
    <!-- FormBuilder 模式: 使用 slot 渲染 label -->
    <div v-if="slots.label" class="field-controls">
      <slot name="label" />
      <slot name="actions" />
    </div>
    <!-- default_single.vue 模式: 自己渲染 label -->
    <label v-else-if="props.df" class="field-label">
      {{ props.ctx?.t(props.df?.label || props.df?.fieldname) }}
      <span v-if="props.df?.reqd" class="required">*</span>
    </label>
    <div class="cron-editor-modern">
      <!-- 触发时间选择器 -->
      <div class="cron-type-container">
        <select 
          v-model="selectedType" 
          class="cron-type"
          @change="onTypeChange"
        >
          <option value="" disabled hidden>触发时间</option>
          <option value="every_minute">每分钟</option>
          <option value="every_n_minute">每N分钟</option>
          <option value="every_hour">每小时</option>
          <option value="every_n_hour">每N小时</option>
          <option value="every_day">每天</option>
          <option value="every_week">每周</option>
          <option value="every_month">每月</option>
        </select>
      </div>

      <!-- 参数设置区域 -->
      <div v-if="showParams" class="cron-params">
        <!-- 每N分钟 -->
        <div v-if="selectedType === 'every_n_minute'" class="param-group">
          每 
          <input 
            type="number" 
            v-model="params.nMinute" 
            min="1" 
            max="59" 
            class="param-input"
            @input="updateCron"
          /> 
          分钟
        </div>

        <!-- 每N小时 -->
        <div v-if="selectedType === 'every_n_hour'" class="param-group">
          每 
          <input 
            type="number" 
            v-model="params.nHour" 
            min="1" 
            max="23" 
            class="param-input"
            @input="updateCron"
          /> 
          小时
        </div>

        <!-- 每天 -->
        <div v-if="selectedType === 'every_day'" class="param-group">
          每天 
          <input 
            type="number" 
            v-model="params.hour" 
            min="0" 
            max="23" 
            class="param-input"
            @input="updateCron"
          /> 
          时 
          <input 
            type="number" 
            v-model="params.minute" 
            min="0" 
            max="59" 
            class="param-input"
            @input="updateCron"
          /> 
          分
        </div>

        <!-- 每周 -->
        <div v-if="selectedType === 'every_week'" class="param-group">
          每周 
          <select v-model="params.weekday" class="param-select" @change="updateCron">
            <option value="0">周日</option>
            <option value="1">周一</option>
            <option value="2">周二</option>
            <option value="3">周三</option>
            <option value="4">周四</option>
            <option value="5">周五</option>
            <option value="6">周六</option>
          </select>
          <input 
            type="number" 
            v-model="params.hour" 
            min="0" 
            max="23" 
            class="param-input"
            @input="updateCron"
          /> 
          时 
          <input 
            type="number" 
            v-model="params.minute" 
            min="0" 
            max="59" 
            class="param-input"
            @input="updateCron"
          /> 
          分
        </div>

        <!-- 每月 -->
        <div v-if="selectedType === 'every_month'" class="param-group">
          每月 
          <input 
            type="number" 
            v-model="params.day" 
            min="1" 
            max="31" 
            class="param-input"
            @input="updateCron"
          /> 
          日 
          <input 
            type="number" 
            v-model="params.hour" 
            min="0" 
            max="23" 
            class="param-input"
            @input="updateCron"
          /> 
          时 
          <input 
            type="number" 
            v-model="params.minute" 
            min="0" 
            max="59" 
            class="param-input"
            @input="updateCron"
          /> 
          分
        </div>
      </div>

      <!-- Cron 表达式预览 -->
      <div v-if="showPreview" class="cron-preview">
        <strong>Cron 表达式：</strong>
        <code>{{ cronExpression }}</code>
        <span v-if="cronText" class="cron-text">({{ cronText }})</span>
        <button 
          type="button" 
          class="copy-btn"
          @click="copyCron"
          :disabled="copying"
        >
          {{ copying ? '已复制!' : '复制' }}
        </button>
      </div>

      <!-- 高级模式切换 -->
      <div class="cron-toggle-container">
        <button 
          type="button" 
          class="cron-toggle-mode"
          @click="toggleAdvancedMode"
        >
          {{ isAdvancedMode ? '可视化设置' : 'Cron表达式' }}
        </button>
      </div>

      <!-- 高级模式 - 直接编辑 Cron 表达式 -->
      <div v-if="isAdvancedMode" class="cron-advanced">
        <input 
          type="text" 
          v-model="cronExpression" 
          class="cron-input"
          placeholder="如：*/5 * * * *"
          @input="onAdvancedInput"
          :class="{ 'error': !isValidCron }"
        />
      </div>

      <!-- 隐藏的输入框用于表单提交 -->
      <input 
        type="hidden" 
        :name="props.name" 
        :value="cronExpression"
      />
    </div>
  </div>
</template>

<style scoped>
.field-wrapper :deep(.cron-editor-modern) {
  flex: 1;
}

.cron-editor-modern {
  border: 1px solid #e1e5e9;
  border-radius: 12px;
  padding: 20px;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
  max-width: 480px;
  margin: 0 auto;
}

.cron-type-container {
  margin-bottom: 16px;
}

.cron-type {
  width: 100%;
  padding: 10px 14px;
  border: 1.5px solid #1fc76f;
  border-radius: 8px;
  font-size: 15px;
  background: #f3f3f3 url('data:image/svg+xml;utf8,<svg fill="%231fc76f" height="20" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg"><path d="M7 10l5 5 5-5z"/></svg>') no-repeat right 16px center/18px 18px;
  padding-right: 40px;
  outline: none;
  transition: border-color 0.2s;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
}

.cron-type:focus {
  border-color: #1fc76f;
}

.cron-params {
  margin-bottom: 16px;
  padding: 14px;
  background: #f3f3f3;
  border-radius: 8px;
  border: 1.5px solid #e3e7ed;
}

.param-group {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.param-input {
  width: 60px;
  padding: 6px 8px;
  border: 1.5px solid #bfc8d6;
  border-radius: 4px;
  font-size: 14px;
  text-align: center;
  outline: none;
  transition: border-color 0.2s;
  background: #fff;
}

.param-input:focus {
  border-color: #1fc76f;
}

.param-select {
  padding: 6px 8px;
  border: 1px solid #d1d5db;
  border-radius: 4px;
  font-size: 14px;
  outline: none;
  transition: border-color 0.2s;
}

.param-select:focus {
  border-color: #1fc76f;
}

.cron-preview {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: #f3f3f3;
  border-radius: 6px;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 14px;
  color: #333;
  margin-bottom: 16px;
  border-left: 4px solid #1fc76f;
  flex-wrap: wrap;
}

.cron-text {
  color: #888;
  margin-left: 10px;
}

.copy-btn {
  background: #e3e7ed;
  color: #1fc76f;
  border: none;
  padding: 4px 10px;
  border-radius: 4px;
  font-size: 13px;
  cursor: pointer;
  margin-left: 8px;
  transition: background 0.2s;
}

.copy-btn:hover {
  background: #d1d5db;
}

.copy-btn:disabled {
  background: #1fc76f;
  color: white;
}

.cron-toggle-container {
  margin-bottom: 16px;
}

.cron-toggle-mode {
  background: #1fc76f;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 8px;
  font-size: 15px;
  cursor: pointer;
  transition: background-color 0.2s;
  outline: none;
}

.cron-toggle-mode:hover {
  background: #1ab85a;
}

.cron-advanced {
  margin-bottom: 16px;
}

.cron-input {
  width: 100%;
  padding: 10px 14px;
  border: 1.5px solid #bfc8d6;
  border-radius: 8px;
  font-size: 15px;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  outline: none;
  transition: border-color 0.2s;
  background: #f3f3f3;
}

.cron-input:focus {
  border-color: #1fc76f;
}

.cron-input.error {
  border-color: #e74c3c;
  background: #fff6f6;
}
</style>
