// plugins/validation.ts
// @ts-ignore
import {defineNuxtPlugin} from '#app'

export default defineNuxtPlugin(() => {
    const validate = (field: any, rules: string[], label = '') => {
        const errors: string[] = []

        // Helpers
        const getRule = (name: string) => rules.find(r => r.startsWith(name))
        const hasRule = (name: string) => Boolean(getRule(name))
        const getValue = (rule: string | undefined) =>
            rule?.split(':')[1] ?? null

        // Main validation handlers
        const handlers: Record<string, () => void> = {
            required: () => {
                const empty =
                    field === '' ||
                    field === null ||
                    field === undefined ||
                    (Array.isArray(field) && field.length === 0)

                if (empty) errors.push(`وارد کردن ${label} الزامی است.`)
            },

            min: () => {
                const min = Number(getValue(getRule('min')))
                if (String(field).length < min)
                    errors.push(`${label} باید حداقل ${min} کاراکتر باشد.`)
            },

            max: () => {
                const max = Number(getValue(getRule('max')))
                if (String(field).length > max)
                    errors.push(`${label} نباید بیشتر از ${max} کاراکتر باشد.`)
            },

            exact: () => {
                const exact = Number(getValue(getRule('exact')))
                if (String(field).length !== exact)
                    errors.push(`${label} باید ${exact} کاراکتر باشد.`)
            },

            email: () => {
                const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
                if (!emailRegex.test(field))
                    errors.push(`${label} باید یک ایمیل معتبر باشد.`)
            },

            phone: () => {
                const phoneRegex = /^(09)\d{9}$/
                if (!phoneRegex.test(field))
                    errors.push(`${label} باید یک شماره موبایل معتبر باشد.`)
            },

            melicode: () => {
                if (!isValidMelicode(field))
                    errors.push(`${label} معتبر نیست.`)
            },

            numeric: () => {
                if (!/^[0-9]+$/.test(field))
                    errors.push(`${label} فقط باید شامل اعداد باشد.`)
            },

            starts_with: () => {
                const start = getValue(getRule('starts_with'))
                if (!String(field).startsWith(start ?? ''))
                    errors.push(`${label} باید با ${start} شروع شود.`)
            },

            date: () => {
                if (!isValidPersianDate(field))
                    errors.push(`${label} معتبر نیست.`)
            }
        }

        // Execute matched handlers
        rules.forEach(rule => {
            const name = rule.split(':')[0]
            // @ts-ignore
            if (handlers[name]) handlers[name]()
        })

        return errors
    }

    // -------------------------
    // Helpers
    // -------------------------

    function isValidMelicode(value: string): boolean {
        if (!/^\d{10}$/.test(value)) return false
        if ([...Array(10)].some(i => value === String(i).repeat(10))) return false

        const check = Number(value[9])
        // @ts-ignore
        const sum = [...value.substring(0, 9)]
            .reduce((acc, num, i) => acc + Number(num) * (10 - i), 0)
        const remainder = sum % 11

        return (remainder < 2 && check === remainder) ||
            (remainder >= 2 && check === (11 - remainder))
    }

    function isValidPersianDate(value: string): boolean {
        const regex = /^1[34]\d{2}\/(0[1-9]|1[0-2])\/(0[1-9]|[12][0-9]|3[01])$/
        if (!regex.test(value)) return false

        const [year, month, day] = value.split('/').map(Number)

        // @ts-ignore
        if (month < 1 || month > 12) return false
        // @ts-ignore
        if (day < 1) return false
        // @ts-ignore
        if (month <= 6 && day > 31) return false
        // @ts-ignore
        if (month >= 7 && month <= 11 && day > 30) return false
        // @ts-ignore
        if (month === 12 && day > 30) return false


        return true
    }

    return {
        provide: {
            validation: {validate}
        },
    }
})
