<template>
  <!-- 添加或修改执行器抽屉 -->
  <el-drawer v-model="visibleProxy" :title="title" size="50%" append-to-body :close-on-click-modal="false" @closed="resetForm">
    <el-card shadow="always" class="box-card" style="padding-top: 10px">
      <el-form ref="executorFormRef" :model="form" :rules="rules" label-width="100px">
        <el-form-item label="AppName" prop="appname">
          <el-input v-model="form.appname" placeholder="请输入AppName" />
          <div class="form-tip">
            执行器AppName，每个执行器集群的唯一标识，用于分组管理多个执行器实例
          </div>
        </el-form-item>
        <el-form-item label="名称" prop="title">
          <el-input v-model="form.title" placeholder="请输入执行器名称" />
          <div class="form-tip">
            执行器名称，用于在管理界面中显示，便于识别不同的执行器
          </div>
        </el-form-item>
        <el-form-item label="注册方式" prop="addressType">
          <el-radio-group v-model="form.addressType">
            <el-radio :value="0">自动注册</el-radio>
            <el-radio :value="1">手动录入</el-radio>
          </el-radio-group>
          <div class="form-tip">
            自动注册：执行器启动时会自动注册到调度中心；手动录入：需要手动配置执行器地址
          </div>
        </el-form-item>
        <el-form-item label="机器地址" prop="addressList" v-if="form.addressType === 1">
          <el-input
            v-model="form.addressList"
            type="textarea"
            :rows="3"
            placeholder="请输入执行器机器地址，多个地址用逗号分隔，如：http://127.0.0.1:9999,http://192.168.1.100:9998"
          />
          <div class="form-tip">
            手动录入执行器地址时使用，格式：http://IP:PORT 或 https://IP:PORT，多个地址用英文逗号分隔
          </div>
        </el-form-item>
      </el-form>
    </el-card>
    <template #footer>
      <div class="dialog-footer">
        <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </template>
  </el-drawer>
</template>

<script setup lang="ts">
import { getJobGroup, addJobGroup, updateJobGroup } from '@/api/xxljob/executor';
import { JobGroupForm, JobGroupVO } from '@/api/xxljob/executor/types';

const props = defineProps({
  visible: {
    type: Boolean,
    default: false
  },
  editType: {
    type: String,
    default: 'add'
  },
  rowData: {
    type: Object as PropType<JobGroupVO | null>,
    default: null
  }
});

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

const { proxy } = getCurrentInstance() as ComponentInternalInstance;

// 可见性的双向绑定
const visibleProxy = computed({
  get: () => props.visible,
  set: (val) => emit('update:visible', val)
});

// 根据编辑类型决定标题
const title = computed(() => (props.editType === 'add' ? '添加执行器' : '修改执行器'));

// 按钮loading
const buttonLoading = ref(false);

// 表单ref
const executorFormRef = ref<ElFormInstance>();

// 初始化表单数据
const initFormData: JobGroupForm = {
  id: undefined,
  appname: '',
  title: '',
  addressType: 0,
  addressList: ''
};

// 表单数据
const form = ref<JobGroupForm>({ ...initFormData });

// HTTP URL 验证函数
const validateHttpUrl = (url: string): boolean => {
  try {
    const urlObj = new URL(url);

    // 检查协议
    if (!['http:', 'https:'].includes(urlObj.protocol)) {
      return false;
    }

    // 检查主机名
    if (!urlObj.hostname) {
      return false;
    }

    // 检查端口号（如果有的话）
    if (urlObj.port) {
      const port = parseInt(urlObj.port);
      if (isNaN(port) || port < 1 || port > 65535) {
        return false;
      }
    }

    // 检查IP地址格式或域名格式
    const hostname = urlObj.hostname;

    // IPv4 地址检查
    const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;

    // IPv6 地址检查（简化版）
    const ipv6Regex = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::1$|^::$/;

    // 域名检查
    const domainRegex = /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/;

    // localhost 特殊处理
    const isLocalhost = hostname === 'localhost';

    // 验证主机名格式
    const isValidHostname = isLocalhost || ipv4Regex.test(hostname) || ipv6Regex.test(hostname) || domainRegex.test(hostname);

    return isValidHostname;
  } catch (error) {
    return false;
  }
};

// 表单校验规则
const rules = ref({
  appname: [
    { required: true, message: 'AppName不能为空', trigger: 'blur' },
    {
      pattern: /^[a-zA-Z][a-zA-Z0-9_-]{3,63}$/,
      message: 'AppName必须以字母开头，只能包含字母、数字、下划线和连字符，长度4-64位',
      trigger: 'blur'
    }
  ],
  title: [{ required: true, message: '执行器名称不能为空', trigger: 'blur' }],
  addressType: [{ required: true, message: '注册方式不能为空', trigger: 'change' }],
  addressList: [
    {
      validator: (rule: any, value: string, callback: any) => {
        if (form.value.addressType === 1) {
          if (!value || value.trim() === '') {
            callback(new Error('手动录入时机器地址不能为空'));
            return;
          }

          // 分割地址并去除空白
          const addresses = value.split(',').map(addr => addr.trim()).filter(addr => addr);

          if (addresses.length === 0) {
            callback(new Error('请输入有效的机器地址'));
            return;
          }

          // 验证每个地址
          for (const addr of addresses) {
            if (!validateHttpUrl(addr)) {
              callback(new Error(`地址格式不正确: ${addr}，正确格式如：http://127.0.0.1:9999 或 https://example.com:8080`));
              return;
            }
          }

          // 检查是否有重复地址
          const uniqueAddresses = [...new Set(addresses)];
          if (uniqueAddresses.length !== addresses.length) {
            callback(new Error('存在重复的机器地址，请检查'));
            return;
          }

          // 地址数量限制
          if (addresses.length > 10) {
            callback(new Error('机器地址数量不能超过10个'));
            return;
          }
        }
        callback();
      },
      trigger: 'blur'
    }
  ]
});

/** 取消按钮 */
const cancel = () => {
  visibleProxy.value = false;
};

/** 表单重置 */
const resetForm = () => {
  form.value = { ...initFormData };
  executorFormRef.value?.resetFields();
};

/** 提交按钮 */
const submitForm = () => {
  executorFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      buttonLoading.value = true;
      try {
        // 处理地址列表格式
        if (form.value.addressType === 1 && form.value.addressList) {
          form.value.addressList = form.value.addressList
            .split(',')
            .map(addr => addr.trim())
            .filter(addr => addr)
            .join(',');
        } else if (form.value.addressType === 0) {
          form.value.addressList = '';
        }

        if (form.value.id) {
          await updateJobGroup(form.value);
        } else {
          await addJobGroup(form.value);
        }
        proxy?.$modal.msgSuccess('操作成功');
        emit('save');
        visibleProxy.value = false;
      } finally {
        buttonLoading.value = false;
      }
    }
  });
};

// 监听抽屉可见性、编辑类型和行数据变化
watch(
  [() => props.visible, () => props.editType, () => props.rowData],
  async ([visible, type, data]) => {
    if (visible) {
      resetForm();

      if (type === 'edit' && data) {
        // 修改操作
        const res = await getJobGroup(data.id);
        Object.assign(form.value, res.data);
      }
    }
  },
  { immediate: true }
);
</script>

<style scoped>
.form-tip {
  color: #909399;
  font-size: 12px;
  margin-top: 4px;
  line-height: 1.4;
}
</style>
