/**
 * debouncing is used to delay the execution of a function for {timeout}
 * if we call the function again within the {timeout} the previous calls will be cancelled
 * e.g. -> user types fast on the search box, we dont want to spam the server for every letter the user types,
 * so we schedule the execution for later and only send a request when the user has stoped typed for {timeout} s
 */
import React from "react";
import {toastError, toastSuccess} from "../services/toaster";
import dayjs from "dayjs";
// import {getPetitionPdf} from "../API/dynamic-forms";
// import {PDFDocument} from "pdf-lib";
// import fontkit from "@pdf-lib/fontkit";


export function debounce(func: any, timeout = 300) {

    let timer: any;

    function debounced(...args: any) {
        clearTimeout(timer);
        timer = setTimeout(() => {
                // @ts-ignore
                func(...args)

            }
            , timeout);
    };

    function cancel() {
        timer && clearTimeout(timer);
    }

    debounced.cancel = cancel
    return debounced
}

/**
 * throttling (the reverse of debnoucing) is used to prevent execution of the same function for {timeout} ms
 * if we call the function again within the {timeout} it will be ignored
 */
// function throttle(func: any, timeout = 300) {
//
//     let timer: any;
//     return (...args: any) => {
//         if (timer) return;
//         func(...args);
//         timer = setTimeout(() => {
//                 timer = null;
//             }
//             , timeout);
//     };
// }

export function getRate(data: number[]) {

    const from = data[0]
    const to = data[data.length - 1]
    if (from === 0 && to === 0) return '0'
    return ((to - from) / from).toFixed(2)

}

export function arraySum(array: number[]) {
    if (array.length > 0) {  // Check if the array is not empty
    return array.reduce((sum, current) => {
            return sum + current;
        });  // Provide 0 as the initial value
    } else {
        return -1;  // Return -1 for empty arrays
    }
}

export function normaliseGreek(text: string) {

    text = text.replace(/Ά|ά/g, 'α')
        .replace(/Έ|έ/g, 'ε')
        .replace(/Ή|ή/g, 'η')
        .replace(/Ί|ί/g, 'ι')
        .replace(/Ϊ́|ΐ/g, 'ϊ')
        .replace(/Ύ|ύ/g, 'υ')
        .replace(/Ό|ό/g, 'ο')
        .replace(/Ϋ́|ΰ/g, 'ϋ')
        .replace(/Ώ|ώ/g, 'ω')
        .replace(/ς/g, 'σ');

    return text;
}

export function oldNormaliseGreek(text: string) {

    text = text.replace(/Ά|Α|ά/g, 'α')
        .replace(/Έ|Ε|έ/g, 'ε')
        .replace(/Ή|Η|ή/g, 'η')
        .replace(/Ί|Ϊ|Ι|ί|ΐ|ϊ/g, 'ι')
        .replace(/Ό|Ο|ό/g, 'ο')
        .replace(/Ύ|Ϋ|Υ|ύ|ΰ|ϋ/g, 'υ')
        .replace(/Ώ|Ω|ώ/g, 'ω')
        .replace(/Σ|ς/g, 'σ');

    return text;
}

/**
 * ALLOWS ONLY GREEK ALPHABET, NUMBERS AND PARENTHESIS "-" , "/" , " "
 */
export function forceUppercaseGreek(text: string) {
    if (!text) return "";
    return normaliseGreek(text)
        .toUpperCase()
        .replace(/[^Α-ΩA-Z0-9()\- /]/gi, '')  // keep digits and parentheses
        .replace(/\s+/g, ' ')                  // collapse repeated spaces
        .replace(/-+/g, '-')                   // collapse repeated dashes
        .trim();
}

export function forceUppercaseEnglish(text: string) {
    // eslint-disable-next-line no-useless-escape
    return text.toUpperCase().replace(/[^A-Z\-]/gi, '')
}

export function forceUppercase(text: string) {
    return normaliseGreek(text).toUpperCase()
}

// validation for afm activation form (2nd step)
export function validateForm(data: any) {
    const newErrors = []
    if (data.afm.length !== 9) newErrors.push('afm')
    if (!data.firstname || data.firstname.length < 3) newErrors.push('firstname')
    if (!data.lastname || data.lastname.length < 3) newErrors.push('lastname')
    if (!data.father_name || data.father_name.length < 3) newErrors.push('father_name')
    if (!data.firstname_en || data.firstname_en.length < 3) newErrors.push('firstname_en')
    if (!data.lastname_en || data.lastname_en.length < 3) newErrors.push('lastname_en')
    if (!data.father_name_en || data.father_name_en.length < 3) newErrors.push('father_name_en')
    if (!data.social_sec_number || data.social_sec_number.length !== 11) newErrors.push('social_sec_number')
    if (!data.work_relation_id) newErrors.push('work_relation_id')
    if (!data.education_category_id) newErrors.push('education_category_id')
    if (!data.staff_category_id) newErrors.push('staff_category_id')
    if (!data.specialization_id) newErrors.push('specialization_id')
    if (data.mobile.length !== 0 && data.mobile.length !== 10) newErrors.push('mobile')
    return newErrors
}


// Helper function to extract plain text from a child element
export const extractPlainTextFromChild = (child: React.ReactNode): string => {
    if (typeof child === 'string') {
        return child;
    }
    if (Array.isArray(child)) {
        return child.map(extractPlainTextFromChild).join(' ');
    }
    if (React.isValidElement(child) && child.props.children) {
        return extractPlainTextFromChild(child.props.children);
    }
    return '';
};

export const handleCopyContent = async (text: string) => {

    try {
        await navigator.clipboard.writeText(text);
        toastSuccess("Το περιεχόμενο αντιγράφηκε!");
    } catch (error) {
        toastError('Κάτι πήγε στραβά, το περιεχόμενο δεν αντιγράφηκε.');
    }
};

export const stripHtmlTags = (string: string) => {
    return string.replace(/<[^>]+>/g, '');
}
export const clearInput = (setState: (state: any) => void, property: string) => {
    setState((prevState: any) => ({
        ...prevState,
        [property]: '',
    }));
};

export const formatDate = (date: string) => {
    if (!date) return "--"
    return dayjs(date).format('DD.MM.YYYY');
}

export const isValidMail = (email: string) => {
    // eslint-disable-next-line no-useless-escape
    const emailRegex = /^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i;
    return emailRegex.test(email)
}

export function downloadFileFromBlob(blob:Blob, name:string = 'file'){
    const myLink = document.createElement('a');
    myLink.href = window.URL.createObjectURL(blob);
    myLink.download = name;
    myLink.click();
}

export  function shortenLongWords(
    input: string,
    longWordThreshold: number = 7,
    shortWordLength: number = 6
): string {
    const separators = ['/', '\\', '-', '_', '+'];

    return input
        .split(' ')
        .map(part =>
            part
                .split(/([\/\\\-_+])/g) // regex captures all separators
                .map(word =>
                    separators.includes(word)
                        ? word
                        : word.length > longWordThreshold
                            ? word.slice(0, shortWordLength) + '.'
                            : word
                )
                .join('')
        )
        .join(' ');
}


export const toArr = <T, >(v: T[] | Record<string, T> | undefined): T[] =>
    Array.isArray(v) ? v : Object.values(v ?? {});


export    const normalizeNullStringToNull = (v: any) => (v === "null" ? null : v);
