import { defineTrait } from '../define.js';

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

function parseRules(str) {
  if (!str) return [];
  return str.split(',').map((r) => r.trim()).filter(Boolean).map((rule) => {
    const [name, ...rest] = rule.split(':');
    return { name: name.trim(), param: rest.join(':').trim() };
  });
}

function validateValue(value, rules) {
  const errors = [];

  for (const rule of rules) {
    switch (rule.name) {
      case 'required':
        if (!value || value.trim().length === 0) {
          errors.push('This field is required');
        }
        break;

      case 'minlength': {
        const min = parseInt(rule.param, 10);
        if (value.length < min) {
          errors.push(`Minimum length is ${min}`);
        }
        break;
      }

      case 'maxlength': {
        const max = parseInt(rule.param, 10);
        if (value.length > max) {
          errors.push(`Maximum length is ${max}`);
        }
        break;
      }

      case 'pattern': {
        const re = new RegExp(rule.param);
        if (!re.test(value)) {
          errors.push(`Does not match required pattern`);
        }
        break;
      }

      case 'min': {
        const min = parseFloat(rule.param);
        if (parseFloat(value) < min) {
          errors.push(`Minimum value is ${min}`);
        }
        break;
      }

      case 'max': {
        const max = parseFloat(rule.param);
        if (parseFloat(value) > max) {
          errors.push(`Maximum value is ${max}`);
        }
        break;
      }

      case 'email':
        if (value && !EMAIL_RE.test(value)) {
          errors.push('Invalid email address');
        }
        break;
    }
  }

  return errors;
}

export const validation = defineTrait({
  name: 'validation',
  category: 'forms-data',
  description: 'Validation rules: required, minlength, pattern, email',
  attributes: ['data-validation-invalid', 'data-validation-valid', 'data-validation-message'],
  events: ['validated'],
  config: ['data-validate'],
  setup({ host }) {
    function validate() {
      const rulesStr = host.getAttribute('data-validate') || '';
      const rules = parseRules(rulesStr);
      const value = host.value ?? host.getAttribute('value') ?? '';
      const errors = validateValue(value, rules);
      const valid = errors.length === 0;

      if (valid) {
        host.setAttribute('data-validation-valid', '');
        host.removeAttribute('data-validation-invalid');
        host.removeAttribute('data-validation-message');
      } else {
        host.setAttribute('data-validation-invalid', '');
        host.setAttribute('data-validation-message', errors[0]);
        host.removeAttribute('data-validation-valid');
      }

      host.dispatchEvent(new CustomEvent('validated', {
        bubbles: true,
        detail: { valid, errors },
      }));
    }

    function onInput() { validate(); }
    function onChange() { validate(); }

    host.addEventListener('input', onInput);
    host.addEventListener('change', onChange);

    return () => {
      host.removeEventListener('input', onInput);
      host.removeEventListener('change', onChange);
      host.removeAttribute('data-validation-invalid');
      host.removeAttribute('data-validation-valid');
      host.removeAttribute('data-validation-message');
    };
  },
});
