import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator';
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import dayjs from 'dayjs';
import { TitleTypes, DescriptionTypes } from 'Contracts/enums';

export default class CreateDatasetValidator {
    constructor(protected ctx: HttpContextContract) {}

    /*
     * Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
     *
     * For example:
     * 1. The username must be of data type string. But then also, it should
     *    not contain special characters or numbers.
     *    ```
     *     schema.string({}, [ rules.alpha() ])
     *    ```
     *
     * 2. The email must be of data type string, formatted as a valid
     *    email. But also, not used by any other user.
     *    ```
     *     schema.string({}, [
     *       rules.email(),
     *       rules.unique({ table: 'users', column: 'email' }),
     *     ])
     *    ```
     */
    public schema = schema.create({
        // first step
        language: schema.string({ trim: true }, [
            rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
        ]),
        licenses: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one license for the new dataset
        rights: schema.string([rules.equalTo('true')]),
        // second step
        type: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
        creating_corporation: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
        titles: schema.array([rules.minLength(1)]).members(
            schema.object().members({
                value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
                type: schema.enum(Object.values(TitleTypes)),
                language: schema.string({ trim: true }, [
                    rules.minLength(2),
                    rules.maxLength(255),
                    rules.translatedLanguage('/language', 'type'),
                ]),
            }),
        ),
        descriptions: schema.array([rules.minLength(1)]).members(
            schema.object().members({
                value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
                type: schema.enum(Object.values(DescriptionTypes)),
                language: schema.string({ trim: true }, [
                    rules.minLength(2),
                    rules.maxLength(255),
                    rules.translatedLanguage('/language', 'type'),
                ]),
            }),
        ),
        authors: schema.array([rules.minLength(1)]).members(schema.object().members({ email: schema.string({ trim: true }) })),
        // third step
        project_id: schema.number.optional(),
        embargo_date: schema.date.optional({ format: 'yyyy-MM-dd' }, [rules.after(10, 'days')]),
        coverage: schema.object().members({
            x_min: schema.number(),
            x_max: schema.number(),
            y_min: schema.number(),
            y_max: schema.number(),
            elevation_absolut: schema.number.optional(),
            elevation_min: schema.number.optional([rules.requiredIfExists('elevation_max')]),
            elevation_max: schema.number.optional([rules.requiredIfExists('elevation_min')]),
            depth_absolut: schema.number.optional(),
            depth_min: schema.number.optional([rules.requiredIfExists('depth_max')]),
            depth_max: schema.number.optional([rules.requiredIfExists('depth_min')]),
        }),
        subjects: schema.array([rules.minLength(3), rules.uniqueArray('value')]).members(
            schema.object().members({
                value: schema.string({ trim: true }, [
                    rules.minLength(3),
                    rules.maxLength(255),
                    // rules.unique({ table: 'dataset_subjects', column: 'value' }),
                ]),
                // type: schema.enum(Object.values(TitleTypes)),
                language: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]),
            }),
        ),
        // file: schema.file({
        //     size: '100mb',
        //     extnames: ['jpg', 'gif', 'png'],
        // }),
        files: schema.array([rules.minLength(1)]).members(
            schema.file({
                size: '100mb',
                extnames: ['jpg', 'gif', 'png'],
            }),
        ),
        // upload: schema.object().members({
        //     label: schema.string({ trim: true }, [rules.maxLength(255)]),

        //     // label: schema.string({ trim: true }, [
        //     //     // rules.minLength(3),
        //     //     // rules.maxLength(255),
        //     // ]),
        // }),
    });

    /**
     * Custom messages for validation failures. You can make use of dot notation `(.)`
     * for targeting nested fields and array expressions `(*)` for targeting all
     * children of an array. For example:
     *
     * {
     *   'profile.username.required': 'Username is required',
     *   'scores.*.number': 'Define scores as valid numbers'
     * }
     *
     */
    public messages: CustomMessages = {
        'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
        'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long',
        'required': '{{ field }} is required',
        'unique': '{{ field }} must be unique, and this value is already taken',
        // 'confirmed': '{{ field }} is not correct',
        'licences.minLength': 'at least {{ options.minLength }} permission must be defined',
        'licences.*.number': 'Define roles as valid numbers',
        'rights.equalTo': 'you must agree to continue',

        'titles.0.value.minLength': 'Main Title  must be at least {{ options.minLength }} characters long',
        'titles.0.value.required': 'Main Title is required',
        'titles.*.value.required': 'Additional title is required, if defined',
        'titles.*.type.required': 'Additional title type is required',
        'titles.*.language.required': 'Additional title language is required',
        'titles.*.language.translatedLanguage': 'The language of the translated title must be different from the language of the dataset',

        'descriptions.0.value.minLength': 'Main Abstract  must be at least {{ options.minLength }} characters long',
        'descriptions.0.value.required': 'Main Abstract is required',
        'descriptions.*.value.required': 'Additional description is required, if defined',
        'descriptions.*.type.required': 'Additional description type is required',
        'descriptions.*.language.required': 'Additional description language is required',
        'descriptions.*.language.translatedLanguage':
            'The language of the translated description must be different from the language of the dataset',

        'authors.minLength': 'at least {{ options.minLength }} author must be defined',

        'after': `{{ field }} must be older than ${dayjs().add(10, 'day')}`,

        'subjects.minLength': 'at least {{ options.minLength }} keywords must be defined',
        'subjects.uniqueArray': 'The {{ options.array }} array must have unique values based on the {{ options.field }} attribute.',
        'subjects.*.value.required': 'keyword value is required',
        'subjects.*.value.minLength': 'keyword value  must be at least {{ options.minLength }} characters long',
        'subjects.*.type.required': 'keyword type is required',
        'subjects.*.language.required': 'language of keyword is required',

        'files.*.size': 'file size is to big',
        'files.extnames': 'file extension is not supported',
    };
}
