import { ErrorPayload, useApi } from "@/api";
import { EGender, ESourceAuthorization, ICreateAuthorizePayload, ICreateAuthorizeResponse } from "@/api/resources/User";
import { useAuth } from "@/auth";
import { getClientTimezone } from "@/locales";
import { getDateAsString } from "@/services/date";
import { filterNullKeysOfObject } from "@/services/filter-object";
import metricService, { EGoals, EMetrics } from "@/services/metric/metricService";
import { actions, selectors } from "@/store";
import moment from "moment";
import { useCallback, useMemo, useState } from "react";
import { useTranslations } from "@/hooks/translations";
import { useDispatch, useSelector } from "react-redux";
import { Response } from "@/api/resources/Login";
import { useSession } from "@/hooks/session/useSession";



export const useAuthentication = () => {
    const api = useApi();
    const feature = useSelector(selectors.selectFeature)
    const { i18n } = useTranslations();
    const dispatch = useDispatch();
    const { updateSession } = useSession();
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [token, setToken] = useState<string | null>(null);
    const { user, signUp } = useAuth();
    const locale = i18n.language;
    const { username } = useSelector(selectors.selectUser)
    const { name: partnerName, birthDate: partnerBirthdateFromForm } = useSelector(selectors.selectRightUser)
    const {
        gender,
        birthdate: birthdateFromQuestionnaire,
        birthtime: birthtimeFromQuestionnaire,
        birthPlace,
        partnerGender,
        partnerBirthdate: partnerBirthdateFromQuestionnaire,
        partnerBirthPlace,
        partnerBirthtime,
    } = useSelector(selectors.selectQuestionnaire)
    const { checked, dateOfCheck } = useSelector(selectors.selectPrivacyPolicy)

    const birthdateFromForm = useSelector(selectors.selectBirthdate);
    const birthtimeFromForm = useSelector(selectors.selectBirthtime);

    const birthdate = useMemo(() => {
        if (birthdateFromQuestionnaire?.length) {
            return birthdateFromQuestionnaire;
        }
        if (birthdateFromForm?.length) {
            return birthdateFromForm;
        }
    }, [birthdateFromForm, birthdateFromQuestionnaire]);

    const birthtime = useMemo(() => {
        if (birthtimeFromQuestionnaire?.length) {
            return birthtimeFromQuestionnaire;
        }
        if (birthtimeFromForm?.length) {
            return birthtimeFromForm;
        }
    }, [birthtimeFromForm, birthtimeFromQuestionnaire]);

    const partnerBirthdate = useMemo(() => {
        const fromQuestionnaire = `${partnerBirthdateFromQuestionnaire} ${partnerBirthtime}`
        if (partnerBirthdateFromQuestionnaire?.length) {
            return fromQuestionnaire;
        }
        return getDateAsString(partnerBirthdateFromForm)
    }, [partnerBirthdateFromForm, partnerBirthdateFromQuestionnaire, partnerBirthtime])

    const formatDate = useCallback((date: string) => {
        const _date = moment(date, "YYYY-MM-DD HH:mm", true).format("YYYY-MM-DD HH:mm");
        if (_date === "Invalid date") {
            return null;
        }
        return _date;
    }, [])

    // Функция для получения всех куки браузера
    const getAllCookies = useCallback(() => {
        const cookies: Record<string, string> = {};
        document.cookie.split(';').forEach(cookie => {
            const [name, value] = cookie.trim().split('=');
            if (name && value) {
                cookies[name] = decodeURIComponent(value);
            }
        });
        return cookies;
    }, []);

    const getAuthorizationPayload = useCallback((email: string, source: ESourceAuthorization): ICreateAuthorizePayload => {
        const timezone = getClientTimezone();
        return filterNullKeysOfObject<ICreateAuthorizePayload>({
            timezone,
            locale,
            email,
            source,
            profile: {
                name: username || "",
                gender: EGender[gender as keyof typeof EGender] || null,
                birthdate: formatDate(`${birthdate} ${birthtime}`),
                birthplace: {
                    address: birthPlace,
                },
            },
            partner: {
                name: partnerName,
                gender: EGender[partnerGender as keyof typeof EGender] || null,
                birthdate: formatDate(partnerBirthdate),
                birthplace: {
                    address: partnerBirthPlace,
                },
            },
            sign: checked,
            signDate: dateOfCheck,
            feature: feature.includes("black") ? "ios" : feature
        })
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [
        birthPlace,
        birthdate,
        gender,
        locale,
        partnerBirthPlace,
        partnerBirthdate,
        partnerGender,
        partnerName,
        username,
        birthtime,
        checked,
        dateOfCheck
    ]);

    const authorizationWithPassword = useCallback(async (email: string, password: string) => {
        try {
            setIsLoading(true);
            setError(null)
            const payload = {
                email,
                locale,
                timezone: getClientTimezone(),
                password
            }
            const loginResult = await api.login(payload);
            const token = "token" in loginResult ? loginResult.token : null;
            const userId = "userId" in loginResult ? loginResult.userId : null;
            const status = "status" in loginResult ? loginResult.status : null;
            const message = "message" in loginResult ? loginResult.message : null;
            if (!token) {
                return {
                    status,
                    message
                }
            }
            metricService.reachGoal(EGoals.ENTERED_EMAIL, [EMetrics.YANDEX, EMetrics.KLAVIYO]);
            metricService.reachGoal(EGoals.LEAD, [EMetrics.FACEBOOK]);
            const { user } = await api.getUser({ token });
            const { user: userMe } = await api.getMe({ token });
            if (userId?.length) {
                metricService.userParams({
                    email: user?.email,
                    UserID: userId
                })
                metricService.setUserID(userId);
            }
            signUp(token, user, userMe);
            setToken(token);
            dispatch(actions.status.update("registred"));
        } catch (error: unknown) {
            const response = (error as ErrorPayload<Response>).responseData
            setError((!!response && "message" in response && response.message) || (error as Error).message);
            return response
        } finally {
            setIsLoading(false);
        }
    }, [api, dispatch, locale, signUp])

    const authorization = useCallback(async (email: string, source: ESourceAuthorization, isAnonymous = false) => {
        try {
            setIsLoading(true);
            setError(null)
            
            // Обновляем сессию с куки перед авторизацией
            try {
                const cookies = getAllCookies();
                await updateSession({ cookies }, source);
                console.log('Session updated with cookies before authorization:', cookies);
            } catch (sessionError) {
                console.warn('Failed to update session with cookies:', sessionError);
                // Продолжаем авторизацию даже если обновление сессии не удалось
            }
            
            const payload = getAuthorizationPayload(email, source);
            const { token, userId: userIdFromApi, generatingVideo, videoId, authCode } = isAnonymous ? await api.authorizationAnonymous(payload) : await api.authorization(payload);
            if (!!token && !isAnonymous) {
                metricService.reachGoal(EGoals.ENTERED_EMAIL, [EMetrics.YANDEX, EMetrics.KLAVIYO]);
                metricService.reachGoal(EGoals.LEAD, [EMetrics.FACEBOOK]);
            }
            const { user } = await api.getUser({ token });
            const { user: userMe } = await api.getMe({ token });
            const userId = userIdFromApi || userMe?._id;
            if (userId?.length) {
                dispatch(actions.userId.update({ userId }));
                metricService.userParams({
                    hasPersonalVideo: generatingVideo || false,
                    email: user?.email,
                    UserID: userId
                })
                metricService.setUserID(userId);
            }
            signUp(token, user, userMe, isAnonymous);
            setToken(token);
            dispatch(actions.userConfig.setAuthCode(authCode || ""));
            dispatch(actions.personalVideo.updateStatus({ generatingVideo: generatingVideo || false, videoId: videoId || "" }));
            if (generatingVideo) {
                metricService.reachGoal(EGoals.ROSE_VIDEO_CREATION_START, [EMetrics.YANDEX, EMetrics.KLAVIYO]);
            }
            dispatch(actions.status.update("registred"));
        } catch (error) {
            setError((error as Error).message);
        } finally {
            setIsLoading(false);
        }
    }, [api, dispatch, getAllCookies, getAuthorizationPayload, signUp, updateSession])

    const anonymousAuthorization = useCallback(async ({
        token,
        userId: userIdFromApi = "",
        generatingVideo = false,
        videoId = "",
        authCode = ""
    }: ICreateAuthorizeResponse) => {
        try {
            setIsLoading(true);
            setError(null)
            const { user } = await api.getUser({ token });
            const { user: userMe } = await api.getMe({ token });
            const userId = userIdFromApi || userMe?._id;
            if (userId?.length) {
                dispatch(actions.userId.update({ userId }));
                metricService.userParams({
                    hasPersonalVideo: generatingVideo || false,
                    email: user?.email,
                    UserID: userId
                })
                metricService.setUserID(userId);
            }
            signUp(token, user, userMe, true);
            setToken(token);
            dispatch(actions.userConfig.setAuthCode(authCode || ""));
            dispatch(actions.personalVideo.updateStatus({ generatingVideo: generatingVideo || false, videoId: videoId || "" }));
            if (generatingVideo) {
                metricService.reachGoal(EGoals.ROSE_VIDEO_CREATION_START, [EMetrics.YANDEX, EMetrics.KLAVIYO]);
            }
            dispatch(actions.status.update("registred"));
        } catch (error) {
            setError((error as Error).message);
        } finally {
            setIsLoading(false);
        }
    }, [api, dispatch, getAuthorizationPayload, signUp])

    return useMemo(
        () => ({
            isLoading,
            error,
            token,
            user,
            authorization,
            authorizationWithPassword,
            anonymousAuthorization
        }),
        [
            isLoading,
            error,
            token,
            user,
            authorization,
            authorizationWithPassword,
            anonymousAuthorization
        ]
    );
}
