import type { FieldDataType } from '#/api/x/eln/fields';

export interface ControlConfigFormValues {
  controlDateFormat?: string;
  controlDefaultChecked?: boolean;
  controlDefaultDate?: string;
  controlDefaultOption?: string;
  controlDefaultValue?: string;
  controlOptionsText?: string;
  controlPlaceholder?: string;
}

export interface DropdownOption {
  display: string;
  value: string;
}

const MANAGED_KEYS = new Set(['dateFormat', 'defaultChecked', 'defaultValue', 'options', 'placeholder']);

export function controlConfigFormValues(config?: Record<string, unknown>): { extras: Record<string, unknown>; values: ControlConfigFormValues } {
  const source = config || {};
  const values: ControlConfigFormValues = {
    controlDateFormat: stringValue(source.dateFormat),
    controlDefaultChecked: Boolean(source.defaultChecked),
    controlDefaultDate: stringValue(source.defaultValue),
    controlDefaultOption: stringValue(source.defaultValue),
    controlDefaultValue: stringValue(source.defaultValue),
    controlOptionsText: formatDropdownOptions(source.options),
    controlPlaceholder: stringValue(source.placeholder),
  };
  const extras = Object.fromEntries(Object.entries(source).filter(([key]) => !MANAGED_KEYS.has(key)));
  return { extras, values };
}

export function buildControlConfig(
  dataType: FieldDataType,
  values: ControlConfigFormValues,
  extras: Record<string, unknown> = {},
): Record<string, unknown> | undefined {
  const config: Record<string, unknown> = { ...extras };
  if (dataType === 'CHECKBOX') {
    if (values.controlDefaultChecked) config.defaultChecked = true;
    return Object.keys(config).length ? config : undefined;
  }

  if (['DECIMAL', 'SELECT', 'TEXT', 'TEXTAREA'].includes(dataType)) {
    assignTrimmed(config, 'placeholder', values.controlPlaceholder);
  }
  if (dataType === 'SELECT') {
    const options = parseDropdownOptions(values.controlOptionsText || '');
    if (options.length) config.options = options;
    assignTrimmed(config, 'defaultValue', values.controlDefaultOption);
  } else if (dataType === 'DATE' || dataType === 'DATETIME') {
    assignTrimmed(config, 'dateFormat', values.controlDateFormat);
    assignTrimmed(config, 'defaultValue', values.controlDefaultDate);
  } else {
    assignTrimmed(config, 'defaultValue', values.controlDefaultValue);
  }
  return Object.keys(config).length ? config : undefined;
}

export function dropdownOptionsFromText(value?: string): DropdownOption[] {
  return parseDropdownOptions(value || '');
}

export function dropdownOptionsForSelect(value?: string): DropdownOption[] {
  try {
    return parseDropdownOptions(value || '');
  } catch {
    return [];
  }
}

export function validateDropdownOptions(value?: string): Promise<void> {
  try {
    const options = parseDropdownOptions(value || '');
    if (options.length < 2) throw new Error('请至少填写两个下拉选项');
    return Promise.resolve();
  } catch (error) {
    return Promise.reject(error);
  }
}

function assignTrimmed(config: Record<string, unknown>, key: string, value?: string) {
  const trimmed = value?.trim();
  if (trimmed) config[key] = trimmed;
}

function formatDropdownOptions(value: unknown): string {
  if (!Array.isArray(value)) return '';
  return value
    .filter((option): option is Record<string, unknown> => Boolean(option) && typeof option === 'object')
    .map((option) => `${stringValue(option.display)}｜${stringValue(option.value)}`)
    .join('\n');
}

function parseDropdownOptions(value: string): DropdownOption[] {
  const lines = value
    .split(/\r?\n/)
    .map((line) => line.trim())
    .filter(Boolean);
  const options = lines.map((line) => {
    const separator = line.indexOf('｜');
    if (separator < 1 || separator === line.length - 1) throw new Error('每个下拉选项均应填写“显示文本｜业务值”');
    const display = line.slice(0, separator).trim();
    const optionValue = line.slice(separator + 1).trim();
    if (!display || !optionValue) throw new Error('下拉选项的显示文本和业务值不能为空');
    return { display, value: optionValue };
  });
  if (new Set(options.map((option) => option.value)).size !== options.length) throw new Error('下拉选项的业务值不能重复');
  return options;
}

function stringValue(value: unknown): string {
  return typeof value === 'string' ? value : '';
}
