<template>
	<a-modal :title="title" :open="visible" :confirm-loading="isSaving" :footer="null" @cancel="handleCancel" width="700px">
		<a-form ref="formRef" :model="form" :rules="rules" :label-col="{ span: 5 }" :wrapper-col="{ span: 18 }">
			<!-- 任务名称 -->
			<a-form-item label="任务名称" name="name" required>
				<a-input v-model:value="form.name" placeholder="如：清理日志" allow-clear />
			</a-form-item>

			<!-- 任务类型 -->
			<a-form-item label="任务类型" name="type" required>
				<a-select v-model:value="form.type" placeholder="请选择任务类型">
					<a-select-option value="command">命令</a-select-option>
					<a-select-option value="job">任务</a-select-option>
					<a-select-option value="closure">闭包</a-select-option>
				</a-select>
			</a-form-item>

			<!-- 命令/类名 -->
			<a-form-item label="命令/类" name="command" required>
				<a-textarea v-if="form.type === 'command'" v-model:value="form.command" placeholder="如：php artisan schedule:run" :rows="3" />
				<a-input v-else v-model:value="form.command" placeholder="如：App\Jobs\SendEmailJob" allow-clear />
				<div class="form-tip">
					<span v-if="form.type === 'command'">Shell命令或Artisan命令</span>
					<span v-else-if="form.type === 'job'">任务类的完整命名空间</span>
					<span v-else>闭包函数的代码</span>
				</div>
			</a-form-item>

			<!-- Cron表达式 -->
			<a-form-item label="Cron表达式" name="expression" required>
				<a-input v-model:value="form.expression" placeholder="* * * * *" allow-clear />
				<div class="form-tip">
					分 时 日 月 周，如：0 0 * * * (每天0点执行)
					<a-link href="https://crontab.guru/" target="_blank" style="color: #1890ff">在线生成工具</a-link>
				</div>
			</a-form-item>

			<!-- 时区 -->
			<a-form-item label="时区" name="timezone">
				<a-select v-model:value="form.timezone" placeholder="请选择时区" show-search :filter-option="filterOption">
					<a-select-option value="Asia/Shanghai">Asia/Shanghai (中国)</a-select-option>
					<a-select-option value="UTC">UTC</a-select-option>
					<a-select-option value="America/New_York">America/New_York</a-select-option>
				</a-select>
			</a-form-item>

			<!-- 描述 -->
			<a-form-item label="任务描述" name="description">
				<a-textarea v-model:value="form.description" placeholder="请输入任务描述" :rows="3" maxlength="200" show-count />
			</a-form-item>

			<!-- 高级选项 -->
			<a-divider>高级选项</a-divider>

			<a-form-item label="后台运行" name="run_in_background">
				<a-switch v-model:checked="runInBackgroundChecked" />
				<div class="form-tip">命令类型任务是否在后台运行</div>
			</a-form-item>

			<a-form-item label="防止重叠" name="without_overlapping">
				<a-switch v-model:checked="withoutOverlappingChecked" />
				<div class="form-tip">防止任务重叠执行</div>
			</a-form-item>

			<a-form-item label="仅单例" name="only_one">
				<a-switch v-model:checked="onlyOneChecked" />
				<div class="form-tip">同一时间只运行一个实例</div>
			</a-form-item>

			<!-- 启用状态 -->
			<a-form-item label="启用状态" name="is_active">
				<sc-select v-model:value="form.is_active" source-type="dictionary" dictionary-code="yes_no" placeholder="请选择状态" allow-clear />
			</a-form-item>

			<!-- 排序 -->
			<a-form-item label="排序" name="sort">
				<a-input-number v-model:value="form.sort" :min="0" :max="10000" style="width: 100%" />
			</a-form-item>
		</a-form>
		<!-- 底部按钮 -->
		<div class="dialog-footer">
			<a-space>
				<a-button @click="handleCancel">取消</a-button>
				<a-button type="primary" :loading="isSaving" @click="handleSubmit">保存</a-button>
			</a-space>
		</div>
	</a-modal>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
import { message } from 'ant-design-vue'
import scSelect from '@/components/scSelect/index.vue'
import systemApi from '@/api/system'

const props = defineProps({
	visible: {
		type: Boolean,
		default: false,
	},
	record: {
		type: Object,
		default: null,
	},
})

const emit = defineEmits(['update:visible', 'success'])

const formRef = ref(null)
const isSaving = ref(false)
const isEdit = computed(() => !!props.record?.id)

const title = computed(() => {
	return isEdit.value ? '编辑定时任务' : '新增定时任务'
})

// 表单数据
const form = ref({
	id: '',
	name: '',
	command: '',
	type: 'command',
	expression: '* * * * *',
	timezone: 'Asia/Shanghai',
	description: '',
	is_active: null,
	run_in_background: false,
	without_overlapping: false,
	only_one: false,
	sort: 0,
})

// Cron 表达式验证函数
const validateCronExpression = (rule, value) => {
	if (!value || !value.trim()) {
		return Promise.reject('请输入Cron表达式')
	}

	const parts = value.trim().split(/\s+/)
	if (parts.length !== 5) {
		return Promise.reject('Cron表达式应由5部分组成：分 时 日 月 周')
	}

	const [minute, hour, day, month, weekday] = parts

	// 验证分钟 (0-59)
	if (!validateCronPart(minute, 0, 59)) {
		return Promise.reject('分钟部分格式不正确 (0-59)')
	}

	// 验证小时 (0-23)
	if (!validateCronPart(hour, 0, 23)) {
		return Promise.reject('小时部分格式不正确 (0-23)')
	}

	// 验证日 (1-31)
	if (!validateCronPart(day, 1, 31)) {
		return Promise.reject('日部分格式不正确 (1-31)')
	}

	// 验证月 (1-12)
	if (!validateCronPart(month, 1, 12)) {
		return Promise.reject('月部分格式不正确 (1-12)')
	}

	// 验证周 (0-6 或 SUN-SAT)
	if (!validateCronPart(weekday, 0, 6, true)) {
		return Promise.reject('周部分格式不正确 (0-6 或 SUN-SAT)')
	}

	return Promise.resolve()
}

// 验证 Cron 单个部分
const validateCronPart = (part, min, max, allowDayNames = false) => {
	// 支持 * (所有值)
	if (part === '*') return true

	// 支持逗号分隔的列表
	const listItems = part.split(',')
	for (const item of listItems) {
		// 支持步长 (step)，如 */5 或 0-10/2
		if (item.includes('/')) {
			const [range, step] = item.split('/')
			if (!range || !step) return false
			if (!validateCronRange(range, min, max, allowDayNames)) return false
			if (!/^\d+$/.test(step)) return false
			continue
		}

		// 支持范围，如 1-5
		if (item.includes('-')) {
			if (!validateCronRange(item, min, max, allowDayNames)) return false
			continue
		}

		// 支持星期名称
		if (allowDayNames) {
			const dayNames = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']
			const dayNamesLower = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']
			if (dayNames.includes(item) || dayNamesLower.includes(item)) {
				continue
			}
		}

		// 检查是否为有效数字
		if (!/^\d+$/.test(item)) return false
		const num = parseInt(item, 10)
		if (num < min || num > max) return false
	}

	return true
}

// 验证 Cron 范围
const validateCronRange = (range, min, max, allowDayNames = false) => {
	// 处理 * 范围
	if (range === '*') return true

	const parts = range.split('-')
	if (parts.length !== 2) return false

	const [start, end] = parts

	// 支持星期名称范围
	if (allowDayNames) {
		const dayNames = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']
		const startIdx = dayNames.indexOf(start)
		const endIdx = dayNames.indexOf(end)
		if (startIdx !== -1 && endIdx !== -1) {
			return startIdx <= endIdx
		}
	}

	// 数字范围验证
	if (!/^\d+$/.test(start) || !/^\d+$/.test(end)) return false
	const startNum = parseInt(start, 10)
	const endNum = parseInt(end, 10)

	return startNum >= min && startNum <= max && endNum >= min && endNum <= max && startNum <= endNum
}

// 验证规则
const rules = {
	name: [
		{ required: true, message: '请输入任务名称', trigger: 'blur' },
		{
			min: 2,
			max: 100,
			message: '长度在 2 到 100 个字符',
			trigger: 'blur',
		},
	],
	type: [{ required: true, message: '请选择任务类型', trigger: 'change' }],
	command: [{ required: true, message: '请输入命令或类名', trigger: 'blur' }],
	expression: [
		{ required: true, message: '请输入Cron表达式', trigger: 'blur' },
		{ validator: validateCronExpression, trigger: 'blur' },
	],
}

// 下拉筛选
const filterOption = (input, option) => {
	return option.value.toLowerCase().includes(input.toLowerCase())
}

// 重置表单
const resetForm = () => {
	form.value = {
		id: '',
		name: '',
		command: '',
		type: 'command',
		expression: '* * * * *',
		timezone: 'Asia/Shanghai',
		description: '',
		is_active: null,
		run_in_background: false,
		without_overlapping: false,
		only_one: false,
		sort: 0,
	}
	formRef.value?.clearValidate()
}

// 设置数据
const setData = (data) => {
	if (data) {
		form.value = {
			id: data.id || '',
			name: data.name || '',
			command: data.command || '',
			type: data.type || 'command',
			expression: data.expression || '* * * * *',
			timezone: data.timezone || 'Asia/Shanghai',
			description: data.description || '',
			is_active: data.is_active !== undefined ? data.is_active : null,
			run_in_background: data.run_in_background || false,
			without_overlapping: data.without_overlapping || false,
			only_one: data.only_one || false,
			sort: data.sort !== undefined ? data.sort : 0,
		}
	}
}

// 提交表单
const handleSubmit = async () => {
	try {
		await formRef.value.validate()

		isSaving.value = true

		const submitData = { ...form.value }

		let res = {}
		if (isEdit.value) {
			res = await systemApi.task.edit.put(form.value.id, submitData)
		} else {
			res = await systemApi.task.add.post(submitData)
		}

		if (res.code === 200) {
			message.success(isEdit.value ? '编辑成功' : '新增成功')
			emit('success')
			handleCancel()
		} else {
			message.error(res.message || '操作失败')
		}
	} catch (error) {
		if (error.errorFields) {
			console.log('表单验证失败:', error)
		} else {
			console.error('提交失败:', error)
			message.error('操作失败')
		}
	} finally {
		isSaving.value = false
	}
}

// 取消
const handleCancel = () => {
	resetForm()
	emit('update:visible', false)
}

// 监听 visible 变化
watch(
	() => props.visible,
	(newVal) => {
		if (newVal) {
			if (props.record) {
				setData(props.record)
			} else {
				resetForm()
			}
		}
	},
	{ immediate: true },
)
</script>

<style scoped lang="scss">
.form-tip {
	font-size: 12px;
	color: #8c8c8c;
	margin-top: 4px;
	line-height: 1.5;
}

.dialog-footer {
	display: flex;
	justify-content: flex-end;
	padding-top: 16px;
	border-top: 1px solid #f0f0f0;
	margin-top: 16px;
}

:deep(.ant-modal-body) {
	max-height: 60vh;
	overflow-y: auto;
}
</style>
