import { ICustomFieldsOption } from '@/modules/customFields/customFields.interface';
import { CustomFields } from '@/modules/customFields/customFields.model';
import { Types } from 'mongoose';
import { ApiError } from './errors';
import { defaultStatus } from './responseCode/httpStatusAlias';
import { getObjectId } from './commonHelper';
import { CustomFormNames } from '@/modules/customFields/customFields.constant';

const typeValidators: Record<string, (val: string) => boolean> = {
  text: (v) => typeof v === 'string',
  textarea: (v) => typeof v === 'string',
  number: (v) => typeof v === 'number',
  email: (v) => typeof v === 'string' && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v),
  phone: (v) => typeof v === 'string' && /^\+?\d{6,15}$/.test(v),
  checkbox: (v) => Array.isArray(v),
  radio: (v) => typeof v === 'string',
  dropdown: (v) => typeof v === 'string',
  date: (v) => !isNaN(Date.parse(v)),
};

export const validateCustomFields = async ({
  customFields = {},
  companyId,
  formName,
  errorCode,
  section = '',
}: {
  customFields?: Record<string, unknown>;
  companyId: string | Types.ObjectId;
  formName: CustomFormNames;
  errorCode?: number;
  section?: string;
}): Promise<Record<string, unknown>> => {
  const sectionFilter = section
    ? { section: { $regex: new RegExp(`^${section}$`, 'i') } }
    : {};

  const fieldDefs = await CustomFields.find({
    companyId: companyId && getObjectId(companyId),
    formName,
    isDeleted: false,
    ...sectionFilter,
  });

  const validFields: Record<string, unknown> = {};
  const errors: string[] = [];

  for (const field of fieldDefs) {
    const { key, type, label, required, options } = field;
    const value = customFields?.[key];

    const isRequired = required ?? false;

    if (isRequired && (value === undefined || value === null || value === '')) {
      errors.push(`"${label}" is required.`);
      continue;
    }

    if (value === undefined || value === null || value === '') continue;

    const validator = typeValidators[type];
    if (validator && !validator(value as string)) {
      errors.push(`"${label}" must be a valid ${type}.`);
      continue;
    }

    // Option validation (for dropdown, radio, checkbox)
    if ((type === 'dropdown' || type === 'radio') && options?.length) {
      const allowedValues = options.map((o: ICustomFieldsOption) => o.value);
      if (!allowedValues.includes(value as string)) {
        errors.push(`"${label}" must be one of: ${allowedValues.join(', ')}`);
        continue;
      }
    }

    if (type === 'checkbox' && options?.length) {
      const allowedValues = options.map((o: ICustomFieldsOption) => o.value);
      const invalid = (value as string[]).filter(
        (v: string) => !allowedValues.includes(v),
      );
      if (invalid.length > 0) {
        errors.push(
          `"${label}" contains invalid values: ${invalid.join(', ')}`,
        );
        continue;
      }
    }

    validFields[key] = value;
  }

  if (errors.length > 0)
    throw new ApiError(
      defaultStatus.BAD_REQUEST,
      'Custom field validation failed',
      true,
      errors.join(', '),
      errorCode,
    );

  return validFields;
};
