import React, { useContext, useEffect } from 'react';
import type { SuitePlugin } from '@theorchard/suite-frontend';
import type { Label } from 'src/types';

const SESSION_STORAGE_SELECTED_LABEL = 'selected_label_uuid';
const SESSION_STORAGE_SONGS_TITLE_FILTER = 'songs_title_filter';
const SESSION_STORAGE_SONGS_SWS_FILTER = 'songs_song_writers_filter';
const SESSION_STORAGE_BRAND_FILTER = 'band_filter';
const SESSION_STORAGE_SW_SEARCH_FILTER = 'sw_search_filter';
const SESSION_STORAGE_PUBLISHERS_SEARCH_FILTER = 'publishers_search_filter';

interface PageFilters {
    songWritersPageSongwriterSearch?: string | null;
    publishersPagePublisherSearch?: string | null;
    songPageSongWriters?: string | null;
    songPageTitle?: string | null;
    brand?: string | null;
}

interface ApplicationContext {
    label: Label | null;
    setLabel: (label: Label | null) => void;
    labelAlt: Label | null; // alternative value, which is not store to sessionStorage
    setLabelAlt: (label: Label | null) => void; // alternative value, which is not store to sessionStorage
    pageFilters: PageFilters | null;
    updatePageFilters: (filters: PageFilters) => void;
}

const AppContext = React.createContext<ApplicationContext>({
    label: null,
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    setLabel: () => {},
    labelAlt: null,
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    setLabelAlt: () => {},
    pageFilters: null,
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    updatePageFilters: () => {},
});

const AppContextProvider: React.FC<React.PropsWithChildren> = ({
    children,
}) => {
    const [label, setLabel] = React.useState<Label | null>(null);
    const [labelAlt, setLabelAlt] = React.useState<Label | null>(null);
    const [pageFilters, setPageFilters] = React.useState<PageFilters>({
        songPageSongWriters: window.sessionStorage.getItem(
            SESSION_STORAGE_SONGS_SWS_FILTER
        ),
        brand: window.sessionStorage.getItem(SESSION_STORAGE_BRAND_FILTER),
        songWritersPageSongwriterSearch: window.sessionStorage.getItem(
            SESSION_STORAGE_SW_SEARCH_FILTER
        ),
        publishersPagePublisherSearch: window.sessionStorage.getItem(
            SESSION_STORAGE_PUBLISHERS_SEARCH_FILTER
        ),
        songPageTitle: window.sessionStorage.getItem(
            SESSION_STORAGE_SONGS_TITLE_FILTER
        ),
    });

    const updatePageFilters = (filters: PageFilters) => {
        setPageFilters(prevState => {
            let isUpdated = false;
            const updatedState = { ...prevState };

            if (filters.songPageTitle !== undefined) {
                updatedState.songPageTitle = filters.songPageTitle;
                isUpdated = true;
            }

            if (filters.songPageSongWriters !== undefined) {
                updatedState.songPageSongWriters = filters.songPageSongWriters;
                isUpdated = true;
            }

            if (filters.brand !== undefined) {
                updatedState.brand = filters.brand;
                isUpdated = true;
            }

            if (filters.songWritersPageSongwriterSearch !== undefined) {
                updatedState.songWritersPageSongwriterSearch =
                    filters.songWritersPageSongwriterSearch;
                isUpdated = true;
            }

            if (filters.publishersPagePublisherSearch !== undefined) {
                updatedState.publishersPagePublisherSearch =
                    filters.publishersPagePublisherSearch;
                isUpdated = true;
            }

            return isUpdated ? updatedState : prevState;
        });
    };

    useEffect(() => {
        try {
            const l = window.sessionStorage.getItem(
                SESSION_STORAGE_SELECTED_LABEL
            );

            if (l) {
                const parsed: Label = JSON.parse(l);
                setLabel(parsed);
            }
        } catch (e) {
            setLabel(null);
        }
    }, []);

    useEffect(() => {
        if (label)
            window.sessionStorage.setItem(
                SESSION_STORAGE_SELECTED_LABEL,
                JSON.stringify(label)
            );
    }, [label]);

    useEffect(() => {
        if (pageFilters.songPageTitle)
            window.sessionStorage.setItem(
                SESSION_STORAGE_SONGS_TITLE_FILTER,
                pageFilters.songPageTitle
            );
        else
            window.sessionStorage.removeItem(
                SESSION_STORAGE_SONGS_TITLE_FILTER
            );

        if (pageFilters.songPageSongWriters)
            window.sessionStorage.setItem(
                SESSION_STORAGE_SONGS_SWS_FILTER,
                pageFilters.songPageSongWriters
            );
        else window.sessionStorage.removeItem(SESSION_STORAGE_SONGS_SWS_FILTER);

        if (pageFilters.brand)
            window.sessionStorage.setItem(
                SESSION_STORAGE_BRAND_FILTER,
                pageFilters.brand
            );
        else window.sessionStorage.removeItem(SESSION_STORAGE_BRAND_FILTER);

        if (pageFilters.songWritersPageSongwriterSearch)
            window.sessionStorage.setItem(
                SESSION_STORAGE_SW_SEARCH_FILTER,
                pageFilters.songWritersPageSongwriterSearch
            );
        else window.sessionStorage.removeItem(SESSION_STORAGE_SW_SEARCH_FILTER);

        if (pageFilters.publishersPagePublisherSearch)
            window.sessionStorage.setItem(
                SESSION_STORAGE_PUBLISHERS_SEARCH_FILTER,
                pageFilters.publishersPagePublisherSearch
            );
        else
            window.sessionStorage.removeItem(
                SESSION_STORAGE_PUBLISHERS_SEARCH_FILTER
            );
    }, [pageFilters]);

    const value = {
        label,
        setLabel,
        labelAlt,
        setLabelAlt,
        pageFilters,
        updatePageFilters,
    };
    return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
};

const ApplicationContextProviderPlugin: SuitePlugin = {
    Wrapper: ({ children, loaded }) => {
        if (!loaded) return <>{children}</>;

        return <AppContextProvider>{children}</AppContextProvider>;
    },
};

export const useApplicationContext = () =>
    useContext<ApplicationContext>(AppContext);

export default ApplicationContextProviderPlugin;
