import type {
  ControlType,
  DropdownOption,
  RawTypeConfig,
  TypeConfigValidationField,
  ValidatedDropdownConfig,
  ValidatedTypeConfig,
  ValidationResult,
} from './types';

const SUPPORTED_CONTROL_TYPES = ['text', 'dropdown', 'checkbox', 'date', 'multiline'] as const satisfies readonly ControlType[];

export const CONTROL_TYPES: readonly ControlType[] = Object.freeze([...SUPPORTED_CONTROL_TYPES]);

function isControlType(value: unknown): value is ControlType {
  return SUPPORTED_CONTROL_TYPES.some((controlType) => controlType === value);
}

export function normalizeControlType(value: unknown): ControlType {
  return isControlType(value) ? value : 'text';
}

function isStrictDate(value: string): boolean {
  const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);

  if (!match) {
    return false;
  }

  const year = Number(match[1]);
  const month = Number(match[2]);
  const day = Number(match[3]);
  const date = new Date(0);

  if (year < 1) {
    return false;
  }

  date.setUTCHours(0, 0, 0, 0);
  date.setUTCFullYear(year, month - 1, day);

  return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
}

function validateDropdown(raw: RawTypeConfig, placeholder: string): ValidationResult<ValidatedDropdownConfig, TypeConfigValidationField> {
  const options: DropdownOption[] = (raw.options ?? []).map((item) => ({
    display: String(item.display || '').trim(),
    value: String(item.value || '').trim(),
  }));

  if (options.length < 2 || options.some((item) => !item.display || !item.value)) {
    return {
      ok: false,
      field: 'dropdown-options',
      message: '下拉框至少需要两个完整选项',
    };
  }

  const values = options.map((item) => item.value);
  const hasDuplicate = values.some((value, index) => values.indexOf(value) !== index);

  if (hasDuplicate) {
    return {
      ok: false,
      field: 'dropdown-options',
      message: '下拉选项业务值不能重复',
    };
  }

  const defaultValue = String(raw.defaultOptionValue || '').trim();
  const selectedIndex = defaultValue ? values.indexOf(defaultValue) : -1;

  if (defaultValue && selectedIndex === -1) {
    return {
      ok: false,
      field: 'dropdown-default',
      message: '默认项必须来自下拉选项',
    };
  }

  return {
    ok: true,
    value: {
      controlType: 'dropdown',
      placeholder,
      options,
      selectedIndex,
    },
  };
}

export function validateTypeConfig(raw: RawTypeConfig | null | undefined): ValidationResult<ValidatedTypeConfig, TypeConfigValidationField> {
  if (!raw) {
    return {
      ok: false,
      field: 'control-type',
      message: '请选择有效的字段类型',
    };
  }

  const type = raw.controlType;

  if (!isControlType(type)) {
    return {
      ok: false,
      field: 'control-type',
      message: '请选择有效的字段类型',
    };
  }

  const placeholder = String(raw.placeholder || '').trim();
  const defaultValue = String(raw.defaultValue || '');

  if (type === 'dropdown') {
    return validateDropdown(raw, placeholder);
  }

  if (type === 'text' && /[\r\n]/.test(defaultValue)) {
    return {
      ok: false,
      field: 'text-default',
      message: '单行文本默认值不能换行',
    };
  }

  if (type === 'date' && defaultValue && !isStrictDate(defaultValue)) {
    return {
      ok: false,
      field: 'date-default',
      message: '请输入有效的日期',
    };
  }

  return {
    ok: true,
    value: {
      controlType: type,
      placeholder,
      defaultValue,
      defaultChecked: Boolean(raw.defaultChecked),
    },
  };
}

function hasExactTag(control: unknown, tag: string): boolean {
  return typeof control === 'object' && control !== null && 'Tag' in control && control.Tag === tag;
}

export function countTag(controls: unknown, tag: string): number {
  if (!Array.isArray(controls)) {
    return 0;
  }

  return (controls as readonly unknown[]).filter((control) => hasExactTag(control, tag)).length;
}
