// ============================================================
// 校验函数 — 纯函数，与 UI 层解耦
// 每个校验器返回 string（错误信息）或 null（通过）
// ============================================================

type ValidateResult = string | null;

/** 用户名：3~64 位，仅允许字母、数字、-、_、. */
export function validateUsername(value: string): ValidateResult {
   if (!value || !value.trim()) return '请输入用户名';
   if (value.length < 3) return '用户名至少 3 位';
   if (value.length > 64) return '用户名最多 64 位';
   if (!/^[a-zA-Z0-9\-_.]+$/.test(value)) return '仅允许字母、数字、-、_、.';
   return null;
}

/** 密码：6~128 位 */
export function validatePassword(value: string): ValidateResult {
   if (!value) return '请输入密码';
   if (value.length < 6) return '密码至少 6 位';
   if (value.length > 128) return '密码最多 128 位';
   return null;
}

/** 确认密码：与密码一致 */
export function validateConfirmPassword(value: string, password: string): ValidateResult {
   if (!value) return '请再次输入密码';
   if (value !== password) return '两次输入的密码不一致';
   return null;
}

/** 手机号：5~32 位数字（可含 + 前缀） */
export function validatePhone(value: string): ValidateResult {
   if (!value) return '请输入手机号';
   if (value.length < 5) return '手机号至少 5 位';
   if (value.length > 32) return '手机号最多 32 位';
   if (!/^\+?[0-9]+$/.test(value)) return '手机号格式不正确';
   return null;
}

/** 短信验证码：4~8 位数字 */
export function validateSmsCode(value: string): ValidateResult {
   if (!value) return '请输入验证码';
   if (value.length < 4) return '验证码至少 4 位';
   if (value.length > 8) return '验证码最多 8 位';
   if (!/^[0-9]+$/.test(value)) return '验证码仅允许数字';
   return null;
}

/** 设备 ID：8~128 位 */
export function validateDeviceId(value: string): ValidateResult {
   if (!value) return '请输入设备标识';
   if (value.length < 8) return '设备标识至少 8 位';
   if (value.length > 128) return '设备标识最多 128 位';
   return null;
}

/** 可选字段：非空时不超过 maxLen */
export function optionalMaxLen(maxLen: number, label: string) {
   return (value: string): ValidateResult => {
      if (!value) return null;
      if (value.length > maxLen) return `${label}最多 ${maxLen} 位`;
      return null;
   };
}

/** 邀请码：可选，最多 32 位字母数字 */
export function validateReferralCode(value: string): ValidateResult {
   if (!value) return null;
   if (value.length > 32) return '邀请码最多 32 位';
   if (!/^[a-zA-Z0-9]+$/.test(value)) return '仅允许字母和数字';
   return null;
}

/**
 * 对一条字段配置执行所有规则校验
 * @returns 错误信息数组（空数组表示通过）
 */
export function validateField(value: string, rules: import('../model/types').FieldRule[]): string[] {
   const errors: string[] = [];
   for (const rule of rules) {
      // required
      if (rule.required && (!value || !value.trim())) {
         errors.push(rule.message || '此字段为必填');
         continue;
      }
      if (!value) continue; // 非必填且为空 → 跳过后续校验

      // minLen
      if (rule.minLen && value.length < rule.minLen) {
         errors.push(rule.message || `至少 ${rule.minLen} 位`);
      }
      // maxLen
      if (rule.maxLen && value.length > rule.maxLen) {
         errors.push(rule.message || `最多 ${rule.maxLen} 位`);
      }
      // pattern
      if (rule.pattern && !rule.pattern.test(value)) {
         errors.push(rule.message || '格式不正确');
      }
   }
   return errors;
}

/**
 * 逐字段运行校验器，有错误则设置并返回 true。
 *
 * 用法（在 handleSubmit 中）：
 *   if (runFieldChecks(setErrors,
 *     { field: 'phone',   error: validatePhone(phone) },
 *     { field: 'pwd',     error: validatePassword(pwd) },
 *     { field: 'confirm', error: validateConfirmPassword(confirm, pwd) },
 *   )) return;
 */
export function runFieldChecks(
   setErrors: (errors: Record<string, string>) => void,
   ...checks: Array<{ field: string; error: string | null }>
): boolean {
   const newErrors: Record<string, string> = {};
   for (const { field, error } of checks) {
      if (error) newErrors[field] = error;
   }
   if (Object.keys(newErrors).length > 0) {
      setErrors(newErrors);
      return true;
   }
   setErrors({});
   return false;
}

/**
 * 校验整个表单
 * @returns 错误映射 { fieldName: errorMsg[] }，空对象表示全部通过
 */
export function validateForm<T extends Record<string, string>>(
   values: T,
   fieldConfigs: import('../model/types').FieldConfig[],
   crossValidators?: Record<string, (value: string, allValues: T) => string | null>,
): Record<string, string[]> {
   const errors: Record<string, string[]> = {};

   for (const config of fieldConfigs) {
      const value = values[config.name] || '';
      const fieldErrors = validateField(value, config.rules);
      if (fieldErrors.length > 0) {
         errors[config.name] = fieldErrors;
      }
   }

   // 跨字段校验（如确认密码）
   if (crossValidators) {
      for (const [name, fn] of Object.entries(crossValidators)) {
         const value = values[name] || '';
         const err = fn(value, values);
         if (err) {
            errors[name] = [...(errors[name] || []), err];
         }
      }
   }

   return errors;
}
