// import { ValidationError } from '../errors/validation_error.js';
import { errors } from '@vinejs/vine';
import type { ErrorReporterContract, FieldContext } from '@vinejs/vine/types';
import string from '@poppinss/utils/string';

/**
 * Shape of the Vanilla error node
 */
export type VanillaErrorNode = {
    [field: string]: string[];
};
export interface MessagesBagContract {
    get(pointer: string, rule: string, message: string, arrayExpressionPointer?: string, args?: any): string;
}
/**
 * Message bag exposes the API to pull the most appropriate message for a
 * given validation failure.
 */
export class MessagesBag implements MessagesBagContract {
    messages: Message;
    wildCardCallback;
    constructor(messages: string[]) {
        this.messages = messages;
        this.wildCardCallback = typeof this.messages['*'] === 'function' ? this.messages['*'] : undefined;
    }
    /**
     * Transform message by replace placeholders with runtime values
     */
    transform(message: any, rule: string, pointer: string, args: any) {
        /**
         * No interpolation required
         */
        if (!message.includes('{{')) {
            return message;
        }
        return string.interpolate(message, { rule, field: pointer, options: args || {} });
    }
    /**
     * Returns the most appropriate message for the validation failure.
     */
    get(pointer: string, rule: string, message: string, arrayExpressionPointer: string, args: any) {
        let validationMessage = this.messages[`${pointer}.${rule}`];
        /**
         * Fetch message for the array expression pointer if it exists
         */
        if (!validationMessage && arrayExpressionPointer) {
            validationMessage = this.messages[`${arrayExpressionPointer}.${rule}`];
        }
        /**
         * Fallback to the message for the rule
         */
        if (!validationMessage) {
            validationMessage = this.messages[rule];
        }
        /**
         * Transform and return message. The wildcard callback is invoked when custom message
         * is not defined
         */
        return validationMessage
            ? this.transform(validationMessage, rule, pointer, args)
            : this.wildCardCallback
              ? this.wildCardCallback(pointer, rule, arrayExpressionPointer, args)
              : message;
    }
}
/**
 * Shape of the error message collected by the SimpleErrorReporter
 */
type SimpleError = {
    message: string;
    field: string;
    rule: string;
    index?: number;
    meta?: Record<string, any>;
};
export interface Message {
    [key: string]: any;
}
/**
 * Simple error reporter collects error messages as an array of object.
 * Each object has following properties.
 *
 * - message: string
 * - field: string
 * - rule: string
 * - index?: number (in case of an array member)
 * - args?: Record<string, any>
 */
export class VanillaErrorReporter implements ErrorReporterContract {
    // private messages;
    // private bail;
    /**
     * Boolean to know one or more errors have been reported
     */
    hasErrors: boolean = false;
    /**
     * Collection of errors
     */
    // errors: SimpleError[] = [];
    errors: Message = {};
    /**
     * Report an error.
     */

    // constructor(messages: MessagesBagContract) {
    //     this.messages = messages;
    // }

    report(message: string, rule: string, field: FieldContext, meta?: Record<string, any> | undefined): void {
        // const error: SimpleError = {
        //     message,
        //     rule,
        //     field: field.getFieldPath()
        //   };
        //   if (meta) {
        //     error.meta = meta;
        //   }
        //   if (field.isArrayMember) {
        //     error.index = field.name as number;
        //   }
        //   this.errors.push(error);
        this.hasErrors = true;
        // if (this.errors[field.getFieldPath()]) {
        //     this.errors[field.getFieldPath()]?.push(message);
        // } else {
        //     this.errors[field.getFieldPath()] = [message];
        // }
        const error: SimpleError = {
            message,
            rule,
            field: field.getFieldPath(), // ?field.wildCardPath.split('.')[0]  : field.getFieldPath(),
        };
        //   field: 'titles.0.value'
        //   message: 'Main Title is required'
        //   rule: 'required' "required"

        if (meta) {
            error.meta = meta;
        }
        //   if (field.isArrayMember) {
        //     error.index = field.name;
        //   }
        this.hasErrors = true;

        // var test = field.getFieldPath();

        //   this.errors.push(error);
        // if (this.errors[error.field]) {
        //     this.errors[error.field]?.push(message);
        // }
        if (field.isArrayMember) {
            // Check if the field has wildCardPath and if the error field already exists
            if (this.errors[error.field]) {
                // Do nothing, as we don't want to push further messages
            } else {
                // If the error field already exists, push the message
                if (this.errors[error.field]) {
                    this.errors[error.field].push(message);
                } else {
                    this.errors[error.field] = [message];
                }
            }
        } else {
            if (this.errors[error.field]) {
                this.errors[error.field]?.push(message);
            } else {
                this.errors[error.field] = [message];
            }
        }

         // } else {
        //     // normal field
        //     this.errors[field.field] = [message];
        // }

        /**
         * Collecting errors as per the JSONAPI spec
         */
        // this.errors.push({
        //     code: rule,
        //     detail: message,
        //     source: {
        //         pointer: field.wildCardPath,
        //     },
        //     ...(meta ? { meta } : {}),
        // });

        //   let pointer: string = field.wildCardPath as string; //'display_name'
        // //   if (field.isArrayMember) {
        // //     this.errors[pointer] = field.name;
        // //   }
        //   this.errors[pointer] = this.errors[pointer] || [];
        // //   this.errors[pointer].push(message);
        //   this.errors[pointer].push(this.messages.get(pointer, rule, message, arrayExpressionPointer, args));
    }
    /**
     * Returns an instance of the validation error
     */
    createError() {
        return new errors.E_VALIDATION_ERROR(this.errors);
    }
}
export {};
