import { FieldContext } from '@vinejs/vine/types';
import vine, { VineArray } from '@vinejs/vine';
import { SchemaTypes } from '@vinejs/vine/types';

type Options = {
    typeA: string;
    typeB: string;
};

/**
 * Custom rule to validate an array of titles contains at least one title
 * with type 'main' and one with type 'translated'.
 *
 * This rule expects the validated value to be an array of objects,
 * where each object has a "type" property.
 */
async function arrayContainsTypes(value: unknown, options: Options, field: FieldContext) {
    if (!Array.isArray(value)) {
        field.report(`The {{field}} must be an array of titles.`, 'array.titlesContainsMainAndTranslated', field);
        return false;
    }

    const typeAExpected = options.typeA.toLowerCase();
    const typeBExpected = options.typeB.toLowerCase();

    // const hasMain = value.some((title: any) => {
    //     return typeof title === 'object' && title !== null && String(title.type).toLowerCase() === 'main';
    // });

    // const hasTranslated = value.some((title: any) => {
    //     return typeof title === 'object' && title !== null && String(title.type).toLowerCase() === 'translated';
    // });
    const hasTypeA = value.some((item: any) => {
        return typeof item === 'object' && item !== null && String(item.type).toLowerCase() === typeAExpected;
    });

    const hasTypeB = value.some((item: any) => {
        return typeof item === 'object' && item !== null && String(item.type).toLowerCase() === typeBExpected;
    });
    if (!hasTypeA || !hasTypeB) {
        let errorMessage = `The ${field.getFieldPath()} array must have at least one '${options.typeA}' item and one '${options.typeB}' item.`;

        // Check for specific field names to produce a more readable message.
        if (field.getFieldPath() === 'titles') {
            // For titles we expect one main and minimum one translated title.
            if (!hasTypeA && !hasTypeB) {
                errorMessage = 'For titles, define one main title and minimum one translated title.';
            } else if (!hasTypeA) {
                errorMessage = 'For titles, define one main title.';
            } else if (!hasTypeB) {
                errorMessage = 'For titles, define minimum one translated title.';
            }
        } else if (field.getFieldPath() === 'descriptions') {
            // For descriptions we expect one abstracts description and minimum one translated description.
            if (!hasTypeA && !hasTypeB) {
                errorMessage = 'For descriptions, define one abstract description and minimum one translated description.';
            } else if (!hasTypeA) {
                errorMessage = 'For descriptions, define one abstract description.';
            } else if (!hasTypeB) {
                errorMessage = 'For descriptions, define minimum one translated description.';
            }
        }

        field.report(errorMessage, 'array.containsTypes', field, options);
        return false;
    }
    return true;
}

export const arrayContainsMainAndTranslatedRule = vine.createRule(arrayContainsTypes);

declare module '@vinejs/vine' {
    interface VineArray<Schema extends SchemaTypes> {
        arrayContainsTypes(options: Options): this;
    }
}

VineArray.macro('arrayContainsTypes', function <Schema extends SchemaTypes>(this: VineArray<Schema>, options: Options) {
    return this.use(arrayContainsMainAndTranslatedRule(options));
});
