import backgroundImage from "@Assets/images/background_refonte.svg";
import CoffreIcon from "@Assets/logo_small_blue.svg";
import Auth from "@Front/Api/Auth/IdNot";
import Loader from "@Front/Components/DesignSystem/Loader";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import HelpBox from "@Front/Components/Elements/HelpBox";
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
import Module from "@Front/Config/Module";
import UserStore from "@Front/Stores/UserStore";
import Image from "next/image";
import { useRouter } from "next/router";
import React, { useEffect, useState } from "react";
import classes from "./classes.module.scss";

import AuthModal from "src/sdk/AuthModal";

import MessageBus from "src/sdk/MessageBus";
import Iframe from "src/sdk/Iframe";

import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService";
import RuleService from "src/common/Api/LeCoffreApi/sdk/RuleService";
import RuleGroupService from "src/common/Api/LeCoffreApi/sdk/RuleGroupService";
import RoleService from "src/common/Api/LeCoffreApi/sdk/RoleService";
import OfficeService from "src/common/Api/LeCoffreApi/sdk/OfficeService";
import CollaboratorService from "src/common/Api/LeCoffreApi/sdk/CollaboratorService";
import OfficeRoleService from "src/common/Api/LeCoffreApi/sdk/OfficeRoleService";

export default function LoginCallBack() {
  const router = useRouter();
  const [idNotUser, setIdNotUser] = useState<any>(null);
  const [isAuthModalOpen, setIsAuthModalOpen] = useState(false);
  const [isConnected, setIsConnected] = useState(false);

  const getOffice = async (idNotUser: any) => {
    return await new Promise<any>((resolve: (office: any) => void) => {
      OfficeService.getOffices().then((processes: any[]) => {
        const officeFound: any = processes.length > 0 ? processes.map((process: any) => process.processData).find((office: any) => office.idNot === idNotUser.office.idNot) : null;
        if (officeFound) {
          resolve(officeFound);
        } else {
          const officeData: any = {
            idNot: idNotUser.office.idNot,
            name: idNotUser.office.name,
            crpcen: idNotUser.office.crpcen,
            address: {
              create: {
                address: idNotUser.office.address.address,
                zip_code: idNotUser.office.address.zip_code,
                city: idNotUser.office.address.city
              }
            },
            office_status: 'ACTIVATED'
          };
          const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
          OfficeService.createOffice(officeData, validatorId).then((process: any) => {
            if (process) {
              const office: any = process.processData;
              resolve(office);
            }
          });
        }
      });
    });
  };

  const initDefaultData = async (office: any) => {
    const rules: any[] = await new Promise<any[]>((resolve: (rules: any[]) => void) => {
      const defaultRules: any[] = [
        // Actes et documents
        {
          name: "POST deeds",
          label: "Créer un template de type d'acte",
          namespace: "collaborator"
        },
        {
          name: "PUT deeds",
          label: "Modifier un type d'acte",
          namespace: "collaborator"
        },
        {
          name: "DELETE deeds",
          label: "Supprimer des types d'actes",
          namespace: "collaborator"
        },
        {
          name: "GET deed-types",
          label: "Lecture des types d'actes",
          namespace: "collaborator"
        },
        {
          name: "POST deed-types",
          label: "Création des types d'actes",
          namespace: "collaborator"
        },
        {
          name: "PUT deed-types",
          label: "Modification des types d'actes",
          namespace: "collaborator"
        },
        {
          name: "DELETE deed-types",
          label: "Suppression des types d'actes",
          namespace: "collaborator"
        },
        {
          name: "GET document-types",
          label: "Lecture des types de documents",
          namespace: "collaborator"
        },
        {
          name: "POST document-types",
          label: "Création des types de documents",
          namespace: "collaborator"
        },
        {
          name: "PUT document-types",
          label: "Modification des types de documents",
          namespace: "collaborator"
        },
        {
          name: "DELETE document-types",
          label: "Suppression des types de documents",
          namespace: "collaborator"
        },
        // RIB
        {
          name: "GET rib",
          label: "Lire le RIB de l'office",
          namespace: "collaborator"
        },
        {
          name: "POST rib",
          label: "Déposer le RIB de l'office",
          namespace: "collaborator"
        },
        {
          name: "PUT rib",
          label: "Editer le RIB de l'office",
          namespace: "collaborator"
        },
        {
          name: "DELETE rib",
          label: "Supprimer le RIB de l'office",
          namespace: "collaborator"
        },
        // Abonnements
        {
          name: "GET subscriptions",
          label: "Récupérer les abonnements",
          namespace: "collaborator"
        },
        {
          name: "POST subscriptions",
          label: "Inviter un collaborateur à l'abonnement",
          namespace: "collaborator"
        },
        {
          name: "PUT subscriptions",
          label: "Modifier l'abonnement",
          namespace: "collaborator"
        },
        {
          name: "GET stripe",
          label: "Gérer l'abonnement de l'office",
          namespace: "collaborator"
        },
        {
          name: "POST stripe",
          label: "Payer un abonnement",
          namespace: "collaborator"
        }
      ];
      RuleService.getRules().then(async (processes: any[]) => {
        const rules: any[] = processes.map((process: any) => process.processData);
        if (rules.length === 0) {
          for (let ruleData of defaultRules) {
            const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
            rules.push((await RuleService.createRule(ruleData, validatorId)).processData);
          }
        }
        resolve(rules);
      });
    });

    await new Promise<void>((resolve: () => void) => {
      const defaultRuleGroups: any[] = [
        {
          name: "Gestion des matrices d'actes et des documents",
          rules: rules
            .filter((rule: any) => rule.name.includes("deeds") || rule.name.includes("deed-types") || rule.name.includes("document-types"))
            .map((rule: any) => ({ uid: rule.uid }))
        },
        {
          name: "Intégration du RIB",
          rules: rules
            .filter((rule: any) => rule.name.includes("rib"))
            .map((rule: any) => ({ uid: rule.uid }))
        },
        {
          name: "Gestion de l'abonnement",
          rules: rules
            .filter((rule: any) => rule.name.includes("subscriptions") || rule.name.includes("stripe"))
            .map((rule: any) => ({ uid: rule.uid }))
        }
      ];
      RuleGroupService.getRuleGroups().then(async (processes: any[]) => {
        const ruleGroups: any[] = processes.map((process: any) => process.processData);
        if (ruleGroups.length === 0) {
          for (let ruleGroupData of defaultRuleGroups) {
            const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
            ruleGroups.push((await RuleGroupService.createRuleGroup(ruleGroupData, validatorId)).processData);
          }
        }
        resolve();
      });
    });

    await new Promise<void>((resolve: () => void) => {
      const defaultRoles: any[] = [
        {
          name: 'super-admin',
          label: 'Super administrateur'
        },
        {
          name: 'admin',
          label: 'Administrateur'
        },
        {
          name: 'notary',
          label: 'Notaire'
        },
        {
          name: 'default',
          label: 'Utilisateur'
        }
      ];
      RoleService.getRoles().then(async (processes: any[]) => {
        const roles: any[] = processes.map((process: any) => process.processData);
        if (roles.length === 0) {
          for (let roleData of defaultRoles) {
            const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
            roles.push((await RoleService.createRole(roleData, validatorId)).processData);
          }
        }
        resolve();
      });
    });

    await new Promise<void>((resolve: () => void) => {
      const defaultOfficeRoles: any[] = [
        {
          name: 'Notaire',
          office: {
            uid: office.uid
          }
        },
        {
          name: 'Collaborateur',
          office: {
            uid: office.uid
          }
        }
      ];
      OfficeRoleService.getOfficeRoles().then(async (processes: any[]) => {
        const roles: any[] = processes.map((process: any) => process.processData);
        if (roles.length === 0) {
          for (let officeRoleData of defaultOfficeRoles) {
            const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
            roles.push((await OfficeRoleService.createOfficeRole(officeRoleData, validatorId)).processData);
          }
        }
        resolve();
      });
    });
  };

  const getCollaborator = async (collaboratorData: any) => {
    return await new Promise<any>(async (resolve: (role: any) => void) => {
      const collaboratorFound: any | null = await CollaboratorService.getCollaboratorBy({ idNot: idNotUser.idNot });
      if (collaboratorFound) {
        resolve(collaboratorFound);
      } else {
        const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
        CollaboratorService.createCollaborator(collaboratorData, validatorId).then((process: any) => {
          if (process) {
            const collaborator: any = process.processData;
            resolve(collaborator);
          }
        });
      }
    });
  };

  useEffect(() => {
    async function getUser() {
      UserStore.instance.disconnect();

      // TODO: review
      // HACK: If start with http://local.lecoffreio.4nkweb:3000/authorized-client 
      //       Replace with http://localhost:3000/authorized-client
      if (window.location.href.startsWith('http://local.lecoffreio.4nkweb:3000/authorized-client')) {
        window.location.href = window.location.href.replace('http://local.lecoffreio.4nkweb:3000/authorized-client', 'http://localhost:3000/authorized-client');
        return;
      }

      const code = router.query["code"];
      if (code) {
        try {
          // Nettoyer l'URL pour ne garder que la racine
          const rootUrl = window.location.origin;
          if (window.location.href !== rootUrl) {
            window.history.replaceState({}, document.title, rootUrl);
          }

          const user: any = await Auth.getInstance().getIdNotUser(code as string);
          setIdNotUser(user.idNotUser);
          setIsAuthModalOpen(true);
          /*
          const token: any = null;
          if (!token) return router.push(Module.getInstance().get().modules.pages.Login.props.path);
          await UserStore.instance.connect(token.accessToken, token.refreshToken);
          const jwt = JwtService.getInstance().decodeJwt();
          if (!jwt) return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1");
          if (jwt.rules && !jwt.rules.includes("GET folders")) {
            return router.push(Module.getInstance().get().modules.pages.Subscription.pages.New.props.path);
          }
          setIsAuthModalOpen(true);
          //return router.push(Module.getInstance().get().modules.pages.Folder.props.path);
          */
          return;
        } catch (e: any) {
          if (e.http_status === 401 && e.message === "Email not found") {
            return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=3");
          }
          if (e.http_status === 409) {
            return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=4");
          }
          return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1");
        }
      }
      /*
      const refreshToken = CookieService.getInstance().getCookie("leCoffreRefreshToken");
      if (!refreshToken) return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1");
      const isTokenRefreshed = await JwtService.getInstance().refreshToken(refreshToken);
      const jwt = JwtService.getInstance().decodeJwt();
      if (!jwt) return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1");
      if (!jwt.rules.includes("GET folders")) {
        return router.push(Module.getInstance().get().modules.pages.Subscription.pages.New.props.path);
      }
      if (isTokenRefreshed) {
        //setIsAuthModalOpen(true);
        //return router.push(Module.getInstance().get().modules.pages.Folder.props.path);
        return;
      }
      */
      return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=2");
    }
    getUser();
  }, [router]);

  return (
    <DefaultDoubleSidePage title={"Login"} image={backgroundImage}>
      <div className={classes["root"]}>
        <div className={classes["title-container"]}>
          <Image alt="coffre" src={CoffreIcon} width={56} />
          <Typography typo={ETypo.TITLE_H1} color={ETypoColor.TEXT_ACCENT}>
            Connexion à votre espace professionnel
          </Typography>
        </div>

        <Loader color={"var(--secondary-default-base, #FF4617)"} width={29} />
        <div />
        <HelpBox
          title="Vous n'arrivez pas à vous connecter ?"
          description="Notre équipe de support est là pour vous aider."
          button={{ text: "Contacter l'administrateur", link: "mailto:support@lecoffre.io" }}
        />
        {isAuthModalOpen && <AuthModal
          isOpen={isAuthModalOpen}
          onClose={() => {
            setIsAuthModalOpen(false);
            setIsConnected(true);
            setTimeout(() => {
              LoaderService.getInstance().show();
              MessageBus.getInstance().initMessageListener();
              MessageBus.getInstance().isReady().then(async () => {
                const office: any = await getOffice(idNotUser);
                await initDefaultData(office);

                const role: any = (await RoleService.getRoles())
                  .map((process: any) => process.processData)
                  .find((role: any) => role.name === idNotUser.role.name);

                const officeRole: any = (await OfficeRoleService.getOfficeRoles())
                  .map((process: any) => process.processData)
                  .filter((officeRole: any) => officeRole.office.uid === office.uid)
                  .find((officeRole: any) => officeRole.name === idNotUser.office_role.name);

                const collaboratorData: any = {
                  idNot: idNotUser.idNot,
                  contact: idNotUser.contact,
                  office: {
                    uid: office.uid
                  },
                  role: {
                    uid: role.uid
                  },
                  office_role: {
                    uid: officeRole.uid
                  }
                };
                const collaborator: any = await getCollaborator(collaboratorData);
                UserStore.instance.connect(collaborator);

                MessageBus.getInstance().destroyMessageListener();
                LoaderService.getInstance().hide();

                /*
                if (jwt.rules && !jwt.rules.includes("GET folders")) {
                  router.push(Module.getInstance().get().modules.pages.Subscription.pages.New.props.path);
                }
                */

                window.location.href = Module.getInstance().get().modules.pages.Folder.props.path;
              });
            }, 100);
          }}
        />}
        {isConnected && <Iframe />}
      </div>
    </DefaultDoubleSidePage>
  );
}
