import * as _ from 'lodash-es';
import { 
  Fragment,
  useCallback,
  useEffect,
  useState
} from 'react';
import { Outlet } from 'react-router-dom';
import { HeaderNavigation } from '@/widgets/navigation/header';
import { FooterNavigation } from '@/widgets/navigation/footer';
import { 
  CodeListItem, 
  CodesSelectParams, 
  CodesSelectPostResponse, 
  HeaderType 
} from '@/entities/common/model/types';
import { useHomeGroupsMutation } from '@/entities/home/api/use-home-groups-mutation';
import { useUserInfo } from '@/entities/user/lib/use-user-info';
import { useAppBridge } from '@/hooks';
import { useStore } from '@/shared/model/store';
import { HomeGroupsParams, HomeGroupsResponse } from '@/entities/home/model/types';
import { 
  BusinessPropertyParams, 
  BusinessPropertyResponse, 
  LoginResponse, 
  MenuGrantsItem, 
  ShortcutUserParams, 
  ShortcutUserResponse, 
  UserFindAuthMethodParams   
} from '@/entities/user/model/types';
import { useShortcutUserMutation } from '@/entities/user/api/use-shortcut-user-mutation';
import { useShortcutDefaultMutation } from '@/entities/user/api/use-shortcut-detault-mutation';
import { useBusinessPropertyMutation } from '@/entities/user/api/use-business-property-mutation';
import { useUserFindAuthMethodMutation } from '@/entities/user/api/use-user-find-authmethod-mutation';
import { useCodesSelectMutation } from '@/entities/common/api/use-codes-select-mutation';
import { MenuItems } from '@/entities/common/model/constant';
import { AlarmLinkOptions } from '@/entities/alarm/model/types';
import { AlarmRoutes } from '@/entities/alarm/ui/alarm-routes';

export interface ContextType {
  setOnBack: (onBack: () => void) => void;
  setHeaderTitle: (title: string) => void;
  setIsPullToRefreshEnabled: (enabled: boolean) => void;
  setMenuOn: (menuOn: boolean) => void;
  setHeaderType: (headerType: HeaderType) => void;
  setFooterMode: (footerMode: boolean) => void;
  setFooterCurrentPage: (footerCurrentPage?: string | null) => void;
  setFavoriteEdit: (favoriteEdit?: boolean) => void;
};

export interface CallCodesSelectProps {
  codeCl: string;
  code1Filter?: Array<any>;
};
export interface OnSetCommonCodesProps {
  data: Array<CodeListItem>;
  codeCl: string;
  code1Filter?: Array<any>;
};

export const SubLayout = () => {
  const { 
    callLogin,
    updateUserData
  } = useUserInfo();

  const [onBack, setOnBack] = useState(undefined);
  const [headerTitle, setHeaderTitle] = useState<string>('');
  const [isPullToRefreshEnabled, setIsPullToRefreshEnabled] = useState<boolean>(false);
  const [menuOn, setMenuOn] = useState<boolean>(false);
  const [headerType, setHeaderType] = useState<HeaderType>(HeaderType.NoHeader);
  const [footerMode, setFooterMode] = useState<boolean>(false);
  const [footerCurrentPage, setFooterCurrentPage] = useState<undefined | string | null>(undefined);
  const [favoriteEdit, setFavoriteEdit] = useState<boolean>(false);
  const [headerNavigationKey, setHeaderNavigationKey] = useState<number>(1);
  const [loginSuccess, setLoginSuccess] = useState<boolean>(false);
  const [mid, setMid] = useState<string>();
  const [alarmRoutesOn, setAlarmRoutesOn] = useState<boolean>(false);
  const [alarmOptions, setAlarmOptions] = useState<AlarmLinkOptions>();

  const { isNativeEnvironment } = useAppBridge();
  const { mutateAsync: homeGroups } = useHomeGroupsMutation();
  const { mutateAsync: codesSelect} = useCodesSelectMutation();
  const { mutateAsync: shortcutUser } = useShortcutUserMutation();
  const { mutateAsync: shortcutDefault } = useShortcutDefaultMutation();
  const { mutateAsync: businessProperty } = useBusinessPropertyMutation();
  const { mutateAsync: findAuthMethod } = useUserFindAuthMethodMutation();

  const wrapperClassName = 'wrapper';
  
  const callHomeGroups = () => {
    let userInfo = useStore.getState().UserStore.userInfo;
    let params: HomeGroupsParams = {
      userid: userInfo.usrid
    };
    homeGroups(params).then((rs: HomeGroupsResponse) => {
      useStore.getState().UserStore.setUserMids(rs.mids);
      if(!!rs.mids[0]){
        useStore.getState().UserStore.setMid(rs.mids[0]);
        setMid(rs.mids[0]);
      }
      let options: Array<Record<string, string>> = rs.mids.map((value, index) => {
        return {
          name: value,
          value: value
        };
      });
      useStore.getState().UserStore.setSelectOptionsMids(options);

      let options2 = _.cloneDeep(options);
      options2.sort((a: Record<string, any>, b: Record<string, any>) => {
        if(a.value.toLowerCase() > b.value.toLowerCase()) return 1;
        else if(a.value.toLowerCase() < b.value.toLowerCase()) return -1;
        else return 0;
      });
      let optionsWithoutGids = options2.filter((value: Record<string, any>, index: number) => {
        let last = value.value.slice(-1); 
        return last.toLowerCase() !== 'g';
      });
      useStore.getState().UserStore.setSelectOptionsMidsWithoutGids(optionsWithoutGids);
      
      setLoginSuccess(true);
      setHeaderNavigationKey(headerNavigationKey + 1);
    });
  };

  const callBusinessProperty = () => {
    if(!!mid){
      let params: BusinessPropertyParams = {
        mid: mid
      };
      businessProperty(params).then((rs: BusinessPropertyResponse) => {
        useStore.getState().UserStore.setBusinessInfo(rs);
      });
    }
    
  };

  const callSortcutDefault = () => {
    let userInfo = useStore.getState().UserStore.userInfo;
    if(userInfo.usrid){
      let params: ShortcutUserParams = {
        usrid: userInfo.usrid,
      };
      shortcutDefault(params).then((rs: ShortcutUserResponse) => {
        const modifiedShortcuts = rs.shortcuts.map(shortcut => ({
          ...shortcut,
          iconFilePath: `/images/menu_icon_${shortcut.menuId}.svg`,
          programPath: getProgramPath(shortcut.menuId)
        }));

        useStore.getState().UserStore.setUserFavorite(modifiedShortcuts);
      });
    }
  };

  // 맵 형태로 상수로 만들어 놓을 필요가 있다. 무의미한 반복문 너무 많이 사용
  const getProgramPath = (menuId: number) => {
    let programPath: string = '';
    Loop1:
    for(let i=0;i<MenuItems.length;i++){
      let menuItem = MenuItems[i];
      if(menuItem){
        let subMenu = menuItem.subMenu;
        if(subMenu){
          Loop2:
          for(let j=0;j<subMenu.length;j++){
            let subMenuItem = subMenu[j];
            if(subMenuItem){
              if(subMenuItem.menuId === menuId){
                programPath = subMenuItem.programPath;
                break Loop1;
              }
            }
          }
        }
      }
    }
    return programPath;
  };

  const callShortcutUser = () => {
    let userInfo = useStore.getState().UserStore.userInfo;
    if(userInfo.usrid){
      let params: ShortcutUserParams = {
        usrid: userInfo.usrid
      };
      shortcutUser(params).then((rs: ShortcutUserResponse) => {
        if(!rs.usingDefault && rs.shortcuts){
          if(rs.shortcuts.length > 0){
            const modifiedShortcuts = rs.shortcuts.map(shortcut => ({
              ...shortcut,
              iconFilePath: `/images/menu_icon_${shortcut.menuId}.svg`,
              programPath: getProgramPath(shortcut.menuId)
            }));
            useStore.getState().UserStore.setUserFavorite(modifiedShortcuts);
          }
          else if(!!rs.usingDefault){
            callSortcutDefault();
          }
        }
      });
    }
    
  };

  const callFindAuthMethod = () => {
    let userInfo = useStore.getState().UserStore.userInfo;
    if(!!userInfo.usrid && !! mid){
      let params: UserFindAuthMethodParams = {
        usrid: userInfo.usrid,
        mid: mid
      };
      findAuthMethod(params).then((rs: any) => {
        let emails = rs.emails.map((value: any, index: any) => {
          return value.content;
        });
        useStore.getState().UserStore.setUserEmails(emails);
        let options: Array<Record<string, string>> = emails.map((value: any, index: any) => {
          return {
            name: value,
            value: value
          };
        });
        useStore.getState().UserStore.setSelectOptionsEmails(options);
        if(!!emails[0]){
          useStore.getState().UserStore.setEmail(emails[0]);
        }
      });
    }
    
  };
    
  const handleLogin = useCallback(async () => {
    let userParmas;
    if(!isNativeEnvironment){
      userParmas = {
        id: 'nictest00',
        password: 'nictest00'
      };
      // userParmas = {
      //   id: 'woowahan5',
      //   password: 'nictest00'
      // };

    }
    callLogin(userParmas).then(() => {
      callHomeGroups();
      callShortcutUser();

      callCodesSelect({ codeCl: '0001' });
      callCodesSelect({ codeCl: '0002' });

      let filter0022: Array<string> = ['01', '02', '03', '05', '14', '21', '24', '26', '31'];
      callCodesSelect({
        codeCl: '0022', 
        code1Filter: filter0022
      });
      callCodesSelect({ codeCl: '0325' });
      callCodesSelect({ codeCl: '0074' });
      onSetGrant();
    }).catch((error: any) => {
      setLoginSuccess(false);
    });
  }, []);

  const callCodesSelect = ({
    codeCl, 
    code1Filter
  }: CallCodesSelectProps) => {
    let params: CodesSelectParams = {
      codeCl: codeCl,
      useCl: 0,
      method: 'post'
    };
    
    codesSelect(params).then((rs: CodesSelectPostResponse) => {
      if(rs){
        onSetCommonCodes({
          data: rs.codeList, 
          codeCl: codeCl, 
          code1Filter: code1Filter
        });
      }
    });
  };

  const onSetGrant = () => {
    let userInfo = useStore.getState().UserStore.userInfo;
    const menuGrants = userInfo.menuGrants;
    let grantObj: Record<string, Array<string>> = {};
    let grantKeys = [8, 4, 2, 1];
    if(!!menuGrants){
      for(let i=0;i<menuGrants.length;i++){
        let menuGrantItem = menuGrants[i];
        if(menuGrantItem){
          let menuId: number = menuGrantItem.menuId;
          let grant: number = menuGrantItem.grant;
          if(!grantObj.hasOwnProperty(''+menuId)){
            grantObj[''+menuId] = [];
          }
          for(let j=0;j<grantKeys.length;j++){
            let grantKey = grantKeys[j];
            if(!!grantKey){
              //grant = grant - grantKey;
              if((grant - grantKey) >= 0){
                grant = grant - grantKey;
                if(j === 0){
                  grantObj[''+menuId]?.push('D');
                }
                else if(j === 1){
                  grantObj[''+menuId]?.push('X');
                }
                else if(j === 2){
                  grantObj[''+menuId]?.push('W');
                }
                else if(j === 3){
                  grantObj[''+menuId]?.push('R');
                }
              }
              else{
                continue;
              }
            }
          }
        }
      }
    }
    useStore.getState().UserStore.setMenuGrantsByKey(grantObj);
  };

  const onSetCommonCodes = ({
    data,
    codeCl,
    code1Filter
  }: OnSetCommonCodesProps) => {
    if(codeCl === '0001'){
      useStore.getState().CommonStore.setBankList(data);
    }
    else if(codeCl === '0002'){
      useStore.getState().CommonStore.setCreditCardList(data);
    }
    else if(codeCl === '0022'){
      let options = [];
      options = data.map((value, index) => {
        return {
          name: value.desc1,
          value: value.code1
        }
      });
      if(!!code1Filter){
        options = options.filter((value, index) => {
          return code1Filter.includes(value.value);
        });
      }
      options = options.sort((a, b) => {
        if(a > b) return 1;
        else if(a < b) return -1;
        else return 0;
      });
      options.unshift({
        name: '전체', value: ''
      });
      useStore.getState().CommonStore.setServiceCodes(options);
    }
    else if(codeCl === '0325'){
      useStore.getState().CommonStore.setAppNotificationCategories(data);
    }
    else if(codeCl === '0074'){
      useStore.getState().CommonStore.setVirtualBankList(data);
    } 
  };

  const saveToken = (token: LoginResponse) => {
    updateUserData(token);
  };
  const alarmLink = (options: AlarmLinkOptions) => {
    if(options?.linkUrl){
      setAlarmRoutesOn(true);
      setAlarmOptions(options);
    }
  };

  window.saveToken = saveToken;
  window.alarmLink = alarmLink;
  
  useEffect(() => {
    handleLogin();
  }, []);
  useEffect(() => {
    if(!!mid){
      callBusinessProperty();
      callFindAuthMethod();
    }
  }, [mid]);

  return (
    <div className={ wrapperClassName }>
      <Fragment>
        <HeaderNavigation 
          onBack={ onBack } 
          headerTitle={ headerTitle } 
          menuOn={ menuOn }
          setMenuOn={ setMenuOn } 
          headerType={ headerType }
          favoriteEdit={ favoriteEdit }
          key={ headerNavigationKey }
          loginSuccess={ loginSuccess }
          mid={ mid }
          setMid={ setMid }
        />
        { loginSuccess && 
          <Outlet
            context={{
              setOnBack,
              setHeaderTitle,
              setIsPullToRefreshEnabled,
              setMenuOn,
              setHeaderType,
              setFooterMode,
              setFooterCurrentPage,
              setFavoriteEdit
            }}
          />
        }
        {
          footerMode && 
          <FooterNavigation
            setMenuOn={ setMenuOn }
            footerCurrentPage={ footerCurrentPage }
            setFavoriteEdit={ setFavoriteEdit }
          ></FooterNavigation>
        }
        { alarmRoutesOn &&
          <AlarmRoutes
            options={ alarmOptions }
          ></AlarmRoutes>
        }
        
      </Fragment>
    </div>
  );
};
