import React, {useContext, useEffect, useState} from 'react';
import CreateButton from "../../../UI/CreateButton/CreateButton";
import YearNavigator from "../../../UI/YearNavigator/YearNavigator";
import EditPeriodModal from "./Modals/EditPeriodModal";
import dayjs from "dayjs";
import locale from "dayjs/locale/el";
import UploadBox from "../../../UI/UploadBox/UploadBox";
import PageSubtitle from "../../../UI/Typography/PageSubtitle";
import './Deltia.scss'
import {MonthDeltio, UserDeltia, YearlyDeltia} from "../../../../models/HrSupport/PersonalFolder";
import {toastError, toastWarn} from "../../../../services/toaster";
import DeltioView from "../../../UI/UploadBox/DeltioView";
import useSetBreadCrumbs from "../../../../context/useSetBreadcrumbs";
import {
    editYear,
    getMyDeltia,
    getUserDeltia,
    initializeYear,
    lockDeltio,
    removeYear,
    uploadDeltio
} from "../../../../API/hr_support";
import useLoading from "../../../../hooks/useLoading";
import CalendarDeltio from "../../../SVG/CalendarDeltio";
import PdfPreviewModal from "../../../UI/Modal/PdfPreviewModal/PdfPreviewModal";
import useFile from "../../../HrSupport/z_hooks/useFile";
import EmployeeContext from "../employeeContext";

const now = dayjs().locale({
    ...locale,
});

const Deltia = () => {

    const [active, setActive] = useState('') //eg. '2022'
    const [hasModal, setHasModal] = useState('')
    const [userDeltia, setUserDeltia] = useState<UserDeltia>([])
    const {employee, canEdit, scope} = useContext(EmployeeContext)
    const [loading, setLoading] = useLoading(true)
    const {handleFileDownload, handleFileDelete} = useFile()

    useSetBreadCrumbs(3, 'Δελτία Κίνησης ' + employee.user.lastname + ' ' + employee.user.firstname)

    useEffect(() => {

        fetchDeltia()

    }, [])

    const fetchDeltia = async () => {

        setLoading(true, true)
        let res
        if (scope === 'hr_manager') {
            res = await getUserDeltia(employee.user.dua_code)
        } else if (scope === 'dua') {
            res = await getMyDeltia()
        } else {
            throw new Error('Unexpected scope value')
        }

        setUserDeltia(res.data)
        if (!activeYear && res.data.length > 0) {

            const fetos = dayjs().year().toString()
            // @ts-ignore
            if(res.data.some(year => year.year === fetos )){
                setActive(fetos)
            }
            else {
                setActive(res.data[0].year)
            }
        }
        setLoading(false)

    }

    const handleDeltioUpload = async (year: string, month: MonthDeltio, file: any) => {

        try {

            setLoading(true)
            const filename = `${month.month} ${year} - ${employee.user.firstname} ${employee.user.lastname}`;
            const formDataObject = new FormData();

            formDataObject.append('user_id', employee.user.id.toString());
            formDataObject.append('month', month.monthI.toString());
            formDataObject.append('year', year);
            formDataObject.append('file[]', file);
            formDataObject.append('filename[]', filename);
            const res = await uploadDeltio(formDataObject)
            await fetchDeltia()

        } catch (e: any) {

        } finally {
            setLoading(false)
        }

    }

    const handledDeltioDelete = async (year: string, monthI: number) => {

        const newD = JSON.parse(JSON.stringify(userDeltia))
        // @ts-ignore
        const newM = newD.find(d => d.year === year).deltia.find(d => d.monthI === monthI)
        const res = await handleFileDelete(newM.file_uuid, newM.file, '','')
        await fetchDeltia()

    }

    const handleFileLock = async (year: string, monthI: number) => {

        try {
            setLoading(true)
            const res = await lockDeltio(employee.user.dua_code, year, monthI)
            fetchDeltia()

        } catch (e: any) {
            if (e.response.data.message) {
                toastWarn(e.response.data.message)
            } else {
                toastError('Κάτι πήγε στραβά')
            }
        } finally {
            setLoading(false)
        }


    }

    const handleAddYear = async (year: { year: string, months: boolean[] }, mode: 'edit' | 'new') => {


        if (!/^2\d{3}$/.test(year.year)) {
            toastWarn('Παρακαλώ εισάγετε έγκυρο έτος.')
            return
        }

        /**
         * transform the array of boolean values to an array of the indexes of picked months
         */
        const monthsIndexes = year.months.reduce((arr, month, monthIndex) => {

            if (month) arr.push(monthIndex + 1)
            return arr
        }, [] as number[])


        if (monthsIndexes.length === 0) {
            toastWarn('Παρακαλώ επιλέξτε τουλάχιστον ενα μήνα.')
            return
        }

        if (mode === 'new' && userDeltia.find(d => d.year === year.year)) {
            toastWarn('Το έτος που εισάγατε έχει ήδη αρχικοποιηθεί.')
            return
        }

        if (mode === 'edit') {
            //test if any of the months have already deltio set
            const hasRemovedMonthWithFile = activeYear && activeYear.deltia.find(d => {
                return d.file && !monthsIndexes.find((m) => m === d.monthI)
            })

            if (hasRemovedMonthWithFile) {
                toastWarn('Δεν μπορείτε να αφαιρέσετε μήνα με αναβασμένο δελτίο. Σβήστε το και προσπαθήστε ξανά.')
                return
            }
        }

        setLoading(true)

        if (mode === 'edit') {

            try {
                const res = await editYear(employee.user.dua_code, year.year, monthsIndexes)
            } catch (e: any) {
                if (e.response.data.message) {
                    toastWarn(e.response.data.message)
                } else {
                    toastError('Κάτι πήγε στραβά')
                }
            }


        }

        if (mode === 'new') {

            try {
                const res = await initializeYear(employee.user.dua_code, year.year, monthsIndexes)
            } catch (e: any) {
                if (e.response.data.message) {
                    toastWarn(e.response.data.message)
                } else {
                    toastError('Κάτι πήγε στραβά')
                }
            }

        }

        setHasModal('')
        setLoading(false)
        fetchDeltia()


    }

    const handleRemoveYear = async (year: string) => {

        if (activeYear!.deltia.find(d => d.file)) {
            toastWarn('Δεν μπορείτε να αφαιρέσετε έτος με ανεβάσμένα δελτία')
            return
        }

        try {
            setLoading(true)
            await removeYear(employee.user.dua_code, year)
            setHasModal('')
            setActive('')
            fetchDeltia()

        } catch (e: any) {
            if (e.response.data.message) {
                toastWarn(e.response.data.message)
            } else {
                toastError('Κάτι πήγε στραβά')
            }
        } finally {
            setLoading(false)
        }
    }

    /**
     * formats year for the format modal needs
     * modal needs a 0 indexed array for the months
     */
    const prepareYear = (year: YearlyDeltia | null) => {

        const init = {
            project:'',
            year: '',
            months: new Array(12).fill(false)
        }

        if (year) {
            init.year = year.year

            year.deltia.forEach(year => {
                init.months[year.monthI - 1] = true
            })
        }

        return init

    }

    const activeYear = userDeltia.find(y => y.year === active)
    const [activeModal, setActiveModal] = useState<string | null>(null);
    const closeModal = () => {
        setActiveModal(null);
    };
    return (
        <div>

            <div className="row mb-6 gap-4">

                <div className="col">

                    <YearNavigator
                        years={userDeltia}
                        active={active}
                        isLocked={!canEdit || (activeYear && activeYear.deltia.length == 12 && activeYear?.deltia.every((m: any) => m.isLocked) || false)}
                        setActive={setActive}
                        onEdit={(year: string) => setHasModal(year)}
                    />
                </div>

                {
                    canEdit &&
                    <div className="col-auto">
                        <CreateButton onClick={() => {
                            setHasModal('new_year')
                        }}>
                            <CalendarDeltio/>
                            <p>ΠΡΟΣΘΗΚΗ ΧΡΟΝΙΑΣ</p>
                        </CreateButton>
                    </div>
                }


            </div>

            <div className={'mb-5'}>
                {activeYear && <PageSubtitle>Μηνιαία Δελτία {active}</PageSubtitle>}
            </div>

            <div className={'row g-4'}>
                {
                    activeYear && activeYear.deltia.map((m) => {

                            return (
                                <div key={activeYear.year.toString() + m.monthI.toString()}
                                     className={`col-6 col-md-4 col-xl-3 order-${m.monthI}`}>
                                    {
                                        activeModal === 'preview-pdf' && m.temp_url &&
                                        <PdfPreviewModal onClose={closeModal} pdfUrl={ m.temp_url}/>
                                    }
                                    <UploadBox
                                        text={activeYear.year + " " + m.month}
                                        hasFile={!!m.file}
                                        isLocked={m.isLocked}
                                        onChange={(f) => handleDeltioUpload(activeYear.year, m, f)}
                                        onDelete={() => handledDeltioDelete(activeYear.year, m.monthI)}
                                        onLock={() => handleFileLock(activeYear.year, m.monthI)}
                                        onPreview={() => setActiveModal('preview-pdf')}
                                        onDownload={() => {
                                            m.file && handleFileDownload(m.file, `${m.month} ${activeYear.year} - ${employee.user.firstname} ${employee.user.lastname}`,'','')
                                        }}
                                        canEdit={canEdit}
                                    >
                                        <DeltioView
                                            year={activeYear.year}
                                            month={m.month}
                                            updatedBy={m.updatedBy}
                                            isLocked={m.isLocked}
                                        />
                                    </UploadBox>
                                </div>
                            )
                        }
                    )
                }
            </div>


            {
                hasModal && <EditPeriodModal
                selectableProjects={[]}
                    selectableYears={[]}
                    mode={hasModal === 'new_year' ? 'new' : 'edit'}
                    init={prepareYear(hasModal === 'new_year' ? null : activeYear!)}
                    close={() => setHasModal('')}
                    onAddYear={(year, mode) => handleAddYear(year, mode)}
                    onRemoveYear={(year: string) => handleRemoveYear(year)}
                />
            }


        </div>
    );
}

export default Deltia;
