'use client';

import React, { useCallback, useEffect, useState } from 'react';
import { Button, Collapse, List } from 'antd';
import type { CollapseProps } from 'antd';
import { useSearchParams } from 'next/navigation';
import { useRouter } from '../../navigation';
import { Filter } from '../../types/experts';
import { Languages, SearchData, Tag } from '../../types/tags';
import { getObjectByFilter, getObjectByAdditionalFilter, getSearchParamsString } from '../../utils/filter';
import { CustomSwitch } from '../view/CustomSwitch';
import { CustomSlider } from '../view/CustomSlider';
import { CustomInput } from '../view/CustomInput';
import { i18nText } from '../../i18nKeys';

type ExpertsFilterProps = {
    searchData?: SearchData;
    languages?: Languages;
    basePath: string;
    priceTitle: string;
    durationTitle: string;
    locale: string;
};

export const ExpertsFilter = ({
    searchData,
    languages,
    basePath,
    priceTitle,
    durationTitle,
    locale
}: ExpertsFilterProps) => {
    const searchParams = useSearchParams();
    const router = useRouter();
    const [filter, setFilter] = useState<Filter | undefined>(getObjectByFilter(searchParams));
    const [openedTabs, setOpenedTabs] = useState<string[]>([]);
    const [filteredTags, setFilteredTags] = useState<Tag[]>([]);
    const [searchLang, setSearchLang] = useState<string>();
    const [searchTags, setSearchTags] = useState<string>();

    useEffect(() => {
        const tags = searchData?.themesGroups
            ? searchData.themesGroups.reduce<Tag[]>((acc, item) => {
                if (item?.tags) {
                    return [
                        ...acc,
                        ...item.tags.map((tag) => ({ ...tag, group: item.name }))
                    ]
                }

                return acc;
            }, [])
            : [];

        setFilteredTags(tags);
    }, [searchData?.themesGroups]);

    const onChangeFilterArr = useCallback((field: string, id: number | string, checked: boolean) => {
        let arr = (filter && filter[field]) || [];

        if (checked && !arr?.includes(id)) {
            arr.push(id);
        }

        if (!checked && arr?.includes(id)) {
            arr = arr.filter((tId) => tId != id);
        }

        setFilter({
            ...(filter || {}),
            [field]: arr
        });
    }, [filter, searchParams, searchData]);

    const onChangePrice = useCallback(([min, max]: number[]) => {
        const newFilter: Filter = {
            ...filter,
            priceFrom: min,
            priceTo: max
        };

        if (newFilter.priceFrom === searchData?.sessionCostMin) {
            delete newFilter.priceFrom;
        }

        if (newFilter.priceTo === searchData?.sessionCostMax) {
            delete newFilter.priceTo;
        }

        setFilter(newFilter);
    }, [filter, searchParams, searchData]);

    const onChangeDuration = useCallback(([min, max]: number[]) => {
        const newFilter: Filter = {
            ...filter,
            durationFrom: min,
            durationTo: max
        };

        if (newFilter.durationFrom === searchData?.sessionDurationMin) {
            delete newFilter.durationFrom;
        }

        if (newFilter.durationTo === searchData?.sessionDurationMax) {
            delete newFilter.durationTo;
        }

        setFilter(newFilter);
    }, [filter, searchParams, searchData]);

    const goToFilterPage = useCallback(() => {
        const newFilter = {
            ...filter,
            ...getObjectByAdditionalFilter(searchParams)
        };
        const search = getSearchParamsString(newFilter);

        router.push(search ? `${basePath}?${search}#filter` : `${basePath}#filter`);

        // router.push({
        //     pathname: basePath as any,
        //     query: {
        //         ...filter,
        //         ...getObjectByAdditionalFilter(searchParams)
        //     }
        // })
    }, [filter, searchParams, searchData]);

    const getSelectedLanguage = useCallback((): string => {
        const cur = languages ? languages.filter(({ code }) => filter?.userLanguages ? filter.userLanguages.includes(code) : false) : [];

        return cur ? cur.map(({ nativeSpelling }) => nativeSpelling).join(', ') : '';
    }, [filter, languages]);

    const getSelectedTags = useCallback((): string => {
        const cur = filteredTags.filter(({ id }) => filter?.themesTagIds ? filter.themesTagIds.includes(id) : false);

        return cur ? cur.map(({ name }) => name).join(', ') : '';
    }, [filter, filteredTags]);

    const getList = useCallback((fieldName: string, data: { id: number | string, name: string }[]) => (
        <div className="b-filter__inner">
            <List
                itemLayout="vertical"
                size="small"
                dataSource={data}
                split={false}
                style={{ width: '100%' }}
                renderItem={({ id, name }) => (
                    <List.Item key={id} style={{ padding: 0 }}>
                        <div className="b-filter__item">
                            <div className="b-filter__title">{name}</div>
                            <CustomSwitch
                                defaultChecked={(filter && filter[fieldName]?.includes(id)) || false}
                                onChange={(checked: boolean) => onChangeFilterArr(fieldName, id, checked)}
                            />
                        </div>
                    </List.Item>
                )}
            />
        </div>
    ), [filter, searchParams, searchData]);

    const getLangList = () => {
        const reg = searchLang ? new RegExp(searchLang, 'ig') : '';
        const langList = reg ? (languages || []).filter(({ code, nativeSpelling }) => reg.test(code) || reg.test(nativeSpelling)) : languages;
        return langList?.length
            ? getList('userLanguages', langList.map(({ code, nativeSpelling }) => ({ id: code, name: nativeSpelling })))
            : null;
    };

    const getTagsList = () => {
        const reg = searchTags ? new RegExp(searchTags, 'ig') : '';

        if (reg) {
            const tagsList = filteredTags.filter(({ name, group }) => reg.test(name) || reg.test(group));
            return getList('themesTagIds', tagsList);
        }

        return searchData?.themesGroups?.length ? searchData.themesGroups.map(({ id, name, tags }) => (
            <div key={id}>
                <h3 className="title-h5">{name}</h3>
                {getList('themesTagIds', tags)}
            </div>
        )) : null;
    };

    const getCollapsedPanels: CollapseProps['items'] = [
        {
            key: 'userLanguages',
            label: (
                <>
                    <div className="b-filter__collapsed__title">{i18nText('sessionLang', locale)}</div>
                    {!openedTabs.includes('userLanguages') && filter?.userLanguages?.length > 0 && (
                        <div className="b-filter__collapsed__desc">{getSelectedLanguage()}</div>
                    )}
                </>
            ),
            children: (
                <>
                    <CustomInput
                        placeholder={i18nText('search', locale)}
                        value={searchLang}
                        onChange={(e) => setSearchLang(e.target?.value)}
                        allowClear
                    />
                    <div className="b-filter__content">
                        {getLangList()}
                    </div>
                </>
            ),
        },
        {
            key: 'themesTagIds',
            label: (
                <>
                    <div className="b-filter__collapsed__title">Direction</div>
                    {!openedTabs.includes('themesTagIds') && filter?.themesTagIds?.length > 0 && (
                        <div className="b-filter__collapsed__desc">{getSelectedTags()}</div>
                    )}
                </>
            ),
            children: (
                <>
                    <CustomInput
                        placeholder={i18nText('search', locale)}
                        value={searchTags}
                        onChange={(e) => setSearchTags(e.target?.value)}
                        allowClear
                    />
                    <div className="b-filter__content">{getTagsList()}</div>
                </>
            ),
        }
    ];

    const onChangeTab = (keys: (string | string[])) => {
        if (Array.isArray(keys)) {
            setOpenedTabs(keys);
            if (!keys.includes('userLanguages') && searchLang) setSearchLang('');
            if (!keys.includes('themesTagIds') && searchTags) setSearchTags('');
        }
    };

    return (
        <div className="b-filter">
            <Collapse
                ghost
                items={getCollapsedPanels}
                expandIconPosition="end"
                onChange={onChangeTab}
            />
            <div className="b-filter__block">
                <h3 className="title-h3">{i18nText('price', locale)}</h3>
                <div className="b-filter__slider">
                    <CustomSlider
                        range
                        step={1}
                        defaultValue={[filter?.priceFrom || searchData?.sessionCostMin || 0, filter?.priceTo || searchData?.sessionCostMax || 0]}
                        min={searchData?.sessionCostMin || 0}
                        max={searchData?.sessionCostMax || 0}
                        onChange={onChangePrice}
                    />
                </div>
                <div className="b-filter__description">{priceTitle}</div>
            </div>
            <div className="b-filter__block">
                <h3 className="title-h3">{i18nText('duration', locale)}</h3>
                <div className="b-filter__slider">
                    <CustomSlider
                        range
                        step={1}
                        defaultValue={[filter?.durationFrom || searchData?.sessionDurationMin || 0, filter?.durationTo || searchData?.sessionDurationMax || 0]}
                        min={searchData?.sessionDurationMin || 0}
                        max={searchData?.sessionDurationMax || 0}
                        onChange={onChangeDuration}
                    />
                </div>
                <div className="b-filter__description">{durationTitle}</div>
            </div>
            <Button
                className="btn-apply"
                onClick={goToFilterPage}
            >
                {i18nText('apply', locale)}
            </Button>
        </div>
    );
};
