import { fetchCountryUserData, usePostSetSlowMutation } from '@api/countries';
import { usePostSetDareRegionMutation } from '@api/myDARE';
import {
  usePostAddVisitMutation,
  usePostGetSingleRegionMutation,
  usePostSetNotVisitedMutation
} from '@api/myRegions';
import React, { createContext, useContext, useState, useCallback } from 'react';
import { DareRegion, NmRegion, SlowData } from 'src/screens/InAppScreens/TravelsScreen/utils/types';
import { StoreType, storage } from 'src/storage';

const RegionContext = createContext<any>(null);

export const useRegion = () => useContext(RegionContext);

export const RegionProvider = ({ children }: { children: React.ReactNode }) => {
  const [userData, setUserData] = useState({});
  const [nmRegions, setNmRegions] = useState<NmRegion[]>([]);
  const [dareRegions, setDareRegions] = useState<DareRegion[] | null>([]);
  const [slow, setSlow] = useState<SlowData[]>([]);
  const token = storage.get('token', StoreType.STRING) as string;
  const { mutate: updateDARE } = usePostSetDareRegionMutation();
  const { mutate: updateSlow } = usePostSetSlowMutation();
  const { mutateAsync: mutateCountriesData } = fetchCountryUserData();
  const { mutateAsync: unvisitRegion } = usePostSetNotVisitedMutation();
  const { mutateAsync: addVisit } = usePostAddVisitMutation();
  const { mutateAsync: getRegion } = usePostGetSingleRegionMutation();

  const handleUpdateNM = useCallback(
    (region: number, first: number, last: number, visits: number, quality: number) => {
      const updatedNM = {
        ...userData,
        first_visit_year: first,
        last_visit_year: last,
        best_visit_quality: quality,
        no_of_visits: visits,
        visited: visits > 0 ? true : false
      };

      if (visits === 0) {
        unvisitRegion(
          { token, region },
          {
            onSuccess: (res) => {
              updatedNM && setUserData(updatedNM);
            },
            onError: (err) => {
              console.log('err', err);
            }
          }
        );

        return;
      }

      const currentYear = new Date().getFullYear();
      const currentMonth = new Date().getMonth() + 1;
      updatedNM.first_visit_year = undefined;
      updatedNM.last_visit_year = undefined;
      updatedNM.best_visit_quality = 3;

      const updatedNMData = {
        token,
        region,
        quality: 3,
        year_from: undefined,
        month_from: undefined,
        day_from: undefined,
        year_to: undefined,
        month_to: undefined,
        day_to: undefined,
        hidden: 0
      };

      addVisit(updatedNMData as never, {
        onError: (error) => {
          console.log('addVisit error', error);
        }
      });

      updatedNM && setUserData(updatedNM);
    },
    [userData, token]
  );

  const handleUpdateDare = useCallback(
    (region: number, visits: 0 | 1) => {
      const updatedDARE = { ...userData, visited: visits > 0 ? true : false };

      const updatedDareData = {
        token,
        region,
        visits
      };

      updateDARE(updatedDareData);
      updatedDARE && setUserData(updatedDARE);
    },
    [userData, token]
  );

  const handleUpdateSlow = useCallback(
    async (id: number, v?: boolean, s11?: boolean, s31?: boolean, s101?: boolean) => {
      const updatedSlow: any = {
        ...userData,
        type: 'countries',
        visited: true
      };

      if (v !== undefined) {
        updatedSlow.visited = v;
      }
      if (s11 !== undefined) {
        const visitedValue = v !== undefined ? v : true;
        updatedSlow.slow11 = !visitedValue ? 0 : (Number(s11) as 0 | 1);
      }
      if (s31 !== undefined) {
        const visitedValue = v !== undefined ? v : true;
        updatedSlow.slow31 = !visitedValue ? 0 : (Number(s31) as 0 | 1);
      }
      if (s101 !== undefined) {
        const visitedValue = v !== undefined ? v : true;
        updatedSlow.slow101 = !visitedValue ? 0 : (Number(s101) as 0 | 1);
      }

      const updatedSlowData: any = {
        token,
        id
      };

      if (v !== undefined) {
        updatedSlowData.v = v;
      }
      if (s11 !== undefined) {
        const visitedValue = v !== undefined ? v : true;
        updatedSlowData.s11 = !visitedValue ? false : s11;
      }
      if (s31 !== undefined) {
        const visitedValue = v !== undefined ? v : true;
        updatedSlowData.s31 = !visitedValue ? false : s31;
      }
      if (s101 !== undefined) {
        const visitedValue = v !== undefined ? v : true;
        updatedSlowData.s101 = !visitedValue ? false : s101;
      }

      updateSlow(updatedSlowData,
        {
          onSuccess: () => {
            mutateCountriesData(
              { id, token },
              {
                onSuccess: (data) => {
                  setUserData({ type: 'countries', id, ...data.data });
                }
              }
            );
          }
        });

      updatedSlow && setUserData(updatedSlow);
    },
    [userData, token]
  );

  const handleUpdateNMList = useCallback(
    (id: number, first: number, last: number, visits: number, quality: number) => {
      const currentYear = new Date().getFullYear();
      const currentMonth = new Date().getMonth() + 1;

      const updatedNM = nmRegions.map((item) => {
        if (item.id === id) {
          return {
            ...item,
            year: visits === 0 ? first : undefined,
            last: visits === 0 ? last : undefined,
            quality: visits === 0 ? quality : 3,
            visits
          };
        }
        return item;
      });

      if (visits === 0) {
        unvisitRegion(
          { token, region: id },
          {
            onSuccess: (res) => {
              updatedNM && setNmRegions(updatedNM);
            },
            onError: (err) => {
              console.log('err', err);
            }
          }
        );

        return;
      }

      const updatedNMData = {
        token,
        region: id,
        quality: 3,
        year_from: undefined,
        month_from: undefined,
        day_from: undefined,
        year_to: undefined,
        month_to: undefined,
        day_to: undefined,
        hidden: 0
      };

      addVisit(updatedNMData as never, {
        onError: (error) => {
          console.log('addVisit error', error);
        }
      });

      updatedNM && setNmRegions(updatedNM);
    },
    [nmRegions]
  );

  const handleUpdateDareList = useCallback(
    (region: number, visits: 0 | 1) => {
      const updatedDARE = dareRegions?.map((item) => {
        if (item.id === region) {
          return {
            ...item,
            visited: String(visits)
          };
        }

        return item;
      });

      const updatedDareData = {
        token,
        region,
        visits
      };

      updateDARE(updatedDareData);
      updatedDARE && setDareRegions(updatedDARE);
    },
    [dareRegions]
  );

  const handleUpdateSlowList = useCallback(
    (
      id: number,
      v?: boolean,
      s11?: boolean,
      s31?: boolean,
      s101?: boolean,
      onDone?: () => void
    ) => {
      const updatedSlowData: any = {
        token,
        id
      };

      if (v !== undefined) {
        updatedSlowData.v = v;
      }
      if (s11 !== undefined) {
        const visitedValue = v !== undefined ? v : true;
        updatedSlowData.s11 = !visitedValue ? false : s11;
      }
      if (s31 !== undefined) {
        const visitedValue = v !== undefined ? v : true;
        updatedSlowData.s31 = !visitedValue ? false : s31;
      }
      if (s101 !== undefined) {
        const visitedValue = v !== undefined ? v : true;
        updatedSlowData.s101 = !visitedValue ? false : s101;
      }

      updateSlow(updatedSlowData, {
        onSuccess: async () => {
          await mutateCountriesData(
            { id, token },
            {
              onSuccess: (data) => {
                const updatedSlow = slow?.map((item) => {
                  if (item.country_id === id) {
                    const dataItem = data.data;
                    const updatedItem = { ...item };

                    updatedItem.visited = Number(dataItem.visited) as 0 | 1;
                    updatedItem.slow11 = Number(dataItem.slow11) as 0 | 1;
                    updatedItem.slow31 = Number(dataItem.slow31) as 0 | 1;
                    updatedItem.slow101 = Number(dataItem.slow101) as 0 | 1;
                    updatedItem.visited_regions = Number(dataItem?.visited_regions) as 0 | 1;
                    updatedItem.info_text = dataItem?.info_text;

                    return updatedItem;
                  }
                  return item;
                });
                updatedSlow && setSlow(updatedSlow);
                onDone?.();
              }
            }
          );
        }
      });
    },
    [slow]
  );

  return (
    <RegionContext.Provider
      value={{
        userData,
        setUserData,
        setNmRegions,
        nmRegions,
        setDareRegions,
        dareRegions,
        handleUpdateNM,
        handleUpdateDare,
        handleUpdateNMList,
        handleUpdateDareList,
        handleUpdateSlow,
        handleUpdateSlowList,
        slow,
        setSlow
      }}
    >
      {children}
    </RegionContext.Provider>
  );
};
