import { MatSnackBar } from '@angular/material/snack-bar';
import { UserConsultResponse } from './../../interfaces/user.interface';
import { MyProfileComponent } from './my-profile/my-profile.component';
import { MaintenanceStatusResponse } from './../../interfaces/maintenance-status.interface';
import { SystemAdminService } from './../../services/system-admin.service';
import { BasicAlertComponent } from './../resources/dialogs/basic-alert/basic-alert.component';
import { AdviceAlertComponent } from './advice-alert/advice-alert.component';
import { Advice, AdviceResponse } from './../../interfaces/advice.interface';
import { AdvicesService } from './../../services/advices.service';
import { NavItem } from './../../interfaces/nav-item.interface';
import { NestedMenuInterface, MenuModules } from './../../interfaces/nested-menu.interface';
import { lastValueFrom } from 'rxjs';
import { UsersProfilesService } from './../../services/users-profiles.service';
import { SocketService } from './../../services/socket.service';
import { EncService } from './../../services/enc/enc.service';
import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Router } from '@angular/router';
import { LoginDataService } from 'src/app/services/login/login-data.service';
import { ProfileInterface } from 'src/app/interfaces/profile.interface';
import { Permissions } from './../../interfaces/permissions.interface';
import { AlertComponent } from '../resources/dialogs/alert/alert.component';
import { ModulesService } from 'src/app/services/modules.service';
import { ResourcesService } from 'src/app/services/resources/resources.service';

@Component({
  selector: 'app-template',
  templateUrl: './template.component.html',
  styleUrls: ['./template.component.css']
})
export class TemplateComponent implements OnInit {
  nestedMenu: MenuModules[];
  navItems: NavItem[];
  menuItems: MenuModules[];

  showFiller = false;
  panelOpenState = false;
  public screen_small = false;

  maintenanceActivated = false;
  maintenanceMode = false;
  isLoading = true;
  minutesLeft = 5;
  secondsLeft = 0;
  errorsCont = 0;
  timeLeft = "5:00";

  userName = "";

  public title:string = 'Sistema de Ayuda al Manteniemiento L1';

  modulesActivated = false;

  constructor(
    private _router: Router,
    private _loginDataService: LoginDataService,
    private _encService: EncService,
    private _socketService: SocketService,
    private _profilesService: UsersProfilesService,
    private _dialg: MatDialog,
    private _modulesService: ModulesService,
    private _advicesService: AdvicesService,
    private _sysAdminService: SystemAdminService,
    private _resouceService: ResourcesService,
    private _snackBar: MatSnackBar,
  ) {
    this.navItems = [];
    this.menuItems = [];
    this.nestedMenu = [];
  }

  ngOnInit(): void {
    this.init();
  }

  async init(){
    try{
      //Ejecutar el tamaño de la pantalla inicial
      this.onResize();
      //Consultar el estado del modo mantenimiento
      let idUser = localStorage.getItem('idusuario');
      let shortEnc = await lastValueFrom(this._encService.shortEncrypt(idUser!));
      let maintenanceStatus: MaintenanceStatusResponse = await lastValueFrom(this._sysAdminService.getMaintenanceStatus(shortEnc.response.encrypted, 1));

      this.maintenanceMode = maintenanceStatus.response.activated;
      
      //Obtención del menú de módulos, submódulos, funciones y pantallas del SAM
      let menu: NestedMenuInterface = await lastValueFrom(this._modulesService.getMenu(shortEnc.response.encrypted, 1));
      //Lectura, decodificación y procesamiento de los permisos del usuario
      let permissions = localStorage.getItem('permisos');
      let permStr = await this._encService.desencriptar(permissions!);
      let permObj: Permissions = JSON.parse(permStr);
      menu.response.forEach(item => {
        let idMod = item.IDMODULO;
        let modPerm = permObj.permissions.filter(item2 => item2.id == idMod)[0];
        let access = modPerm.access;
        if(access > 0){
          this.menuItems.push(item);
        }
      });
      
      //Conexiones a los eventos del Socket
      if (window.innerWidth <= 616) {
        this.screen_small = false;
      }else if(window.innerWidth > 616){
        this.screen_small = true;
      }
  
      this._socketService.refreshPermissions().subscribe(async (profUpdEnc) => {
        let shortID = await lastValueFrom(this._encService.shortEncrypt(localStorage.getItem('idusuario')!));
        let usrInfo: UserConsultResponse = await lastValueFrom(this._profilesService.getUser(shortID.response.encrypted, shortID.response.encrypted, 1));
        let currentProfile = await this._encService.desencriptar(localStorage.getItem('perfil')!);

        if(parseInt(currentProfile) != usrInfo.response.PERFIL){
          let perfEnc = await this._encService.encriptar(`${usrInfo.response.PERFIL}`);
          localStorage.setItem('perfil', perfEnc);
          currentProfile = `${usrInfo.response.PERFIL}`;
        }

        let profileUpdated = await this._encService.desencriptar(`${profUpdEnc}`);
  
        if(profileUpdated == currentProfile){
          try{
            let shortProf = await lastValueFrom(this._encService.shortEncrypt(localStorage.getItem('perfil')!));
            let profInfo: ProfileInterface = await lastValueFrom(this._profilesService.getProfile(
              shortProf.response.encrypted,
              shortID.response.encrypted,
              1
            ));
  
            let oldPerm = await this._encService.desencriptar(localStorage.getItem('permisos')!);
            let newPerm = JSON.stringify(profInfo.response.PERMISOS);
  
            if(oldPerm != newPerm){
              let permiEnc = await this._encService.encriptar(newPerm);
              localStorage.setItem('permisos', permiEnc);
              this.menuItems = [];

              this.nestedMenu.forEach(item => {
                let idMod = item.IDMODULO;
                let modPerm = profInfo.response.PERMISOS.permissions.filter(item2 => item2.id == idMod)[0];
                let access = modPerm.access;
                if(access > 0){
                  this.menuItems.push(item);
                }
              });

              this.openSnackBar('Sus permisos fueron actualizados.');
            }
          }catch(error: any){
            if(error.error == undefined){
              this.openDialog('Ocurrió un error al actualizar su perfil');
            }else if(error.error.msg == undefined){
              this.openDialog('Ocurrió un error al actualizar su perfil');
            }else{
              this.openDialog(error.error.msg);
            }
          }
        }
      });
  
      this._socketService.advicePublished().subscribe(async (adviceID) => {
        let idShort = await lastValueFrom(this._encService.shortEncrypt(`${adviceID}`));
        let idEnc = localStorage.getItem('idusuario');
        let shortEnc = await lastValueFrom(this._encService.shortEncrypt(idEnc!));
  
        let advice: AdviceResponse = await lastValueFrom(this._advicesService.getAdvice(idShort.response.encrypted, shortEnc.response.encrypted, 1));
        let userPublish = await this._encService.desencriptar(advice.response.IDUSUARIO);
        let idDec = await this._encService.desencriptar(idEnc!);
  
        if(userPublish != idDec){
          let audStr = await this._encService.desencriptar(advice.response.AUDIENCIA);
          let audArr = JSON.parse(audStr);
  
          let profiles: string[] = [];
          let users: string[] = [];
  
          audArr.forEach((item: any) => {
            let itemArr = item.split('-');
  
            if(itemArr[0] == 'prof'){
              profiles.push(itemArr[1]);
            }else{
              users.push(itemArr[1]);
            }
          });
  
          let perfEnc = localStorage.getItem('perfil');
          let perfDec = await this._encService.desencriptar(perfEnc!);
  
          if(profiles.includes(perfDec) || users.includes(idDec)){
            this.openAdviceAlert(advice.response);
          }
        }
      })
  
      this._socketService.closeSessions().subscribe((data) => {
        this._dialg.open(BasicAlertComponent, {
          data: {
            title: 'Modo mantenimiento activado',
            body: 'El modo mantenimiento fue activado por un administrador, el sistema entrará en este modo en 5 minutos, por lo tanto deberá guardar sus cambios y cerrar sesión antes de terminar el tiempo.'
          }
        });
  
        this.maintenanceActivated = true;
  
        let interval = setInterval(() => {
          if(this.secondsLeft == 0 && this.minutesLeft > 0){
            this.minutesLeft--;
            this.secondsLeft = 59;
          }else if(this.secondsLeft > 0 && this.minutesLeft >= 0){
            this.secondsLeft--;
          }else{
            clearInterval(interval);
            this.logout();
          }
  
          let secondsStr = this.secondsLeft > 9 ? `${this.secondsLeft}` : `0${this.secondsLeft}`;
          this.timeLeft = `${this.minutesLeft}:${secondsStr}`;
        }, 1000);
      });

      let userName = localStorage.getItem('nombre_usuario');
      let name = await this._encService.desencriptar(userName!);
      
      this.userName = name;
      this.nestedMenu = menu.response;
      this.isLoading = false;
    }catch(error: any){
      let msg = '';
      if(error.error == undefined){
        msg = 'Ocurrió un error inesperado';
      }else if(error.error.msg == undefined){
        msg = 'Ocurrió un error inesperado';
      }else{
        msg = error.error.msg;
      }

      this.errorsCont++;
      this.openDialog(msg);
    }
  }

  openSnackBar(msg: string){
    this._snackBar.open(msg, undefined, {
      duration: 2500,
    });
  }

  openDialog(msg: string){
    let msgFin = this.errorsCont < 3 ? msg : 'El error persiste, por favor contacte al departamenteo de TI para solucionarlo.';
    let _dialogRef = this._dialg.open(AlertComponent, {
      width: '300px',
      data: {
        icon: "error",
        title: '¡Error!',
        description: msgFin
      }
    });

    _dialogRef.afterClosed().subscribe((_) => {
      if(this.errorsCont < 3){
        location.reload();
      }else{
        this.logoutTemp();
      }
    })
  }

  openAdviceAlert(advice: Advice){
    this._dialg.open(AdviceAlertComponent, {
      data: advice
    });
  }

  async checkMaintenanceMode(){
    try{
      let idUser = localStorage.getItem('idusuario');
      let shortEnc = await lastValueFrom(this._encService.shortEncrypt(idUser!));
      let maintenanceStatus: MaintenanceStatusResponse = await lastValueFrom(this._sysAdminService.getMaintenanceStatus(shortEnc.response.encrypted, 1));

      this.maintenanceMode = maintenanceStatus.response.activated;
    }catch(error: any){
      let errorStr = "";

      if(error.error == undefined){
        errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        errorStr = 'Ocurrió un error inesperado.';
      }else{
        errorStr = error.error.msg;
      }

      this.openDialog(errorStr);
    }
  }

  openViewProfilesAdmin() {
    this._router.navigate([
      'sam/users-profiles'
    ]);
  }

  openViewUsersAdmin() {
    this._router.navigate([
      'sam/new-user'
    ]);
  }

  logout () {
    this._loginDataService.logout()
  }

  async getModules(){
    try{
      let permEnc = localStorage.getItem('permisos');
      let permDec = await this._encService.desencriptar(permEnc!);
      let permissions: Permissions = JSON.parse(permDec);

      let idEnc = localStorage.getItem('idusuario');
      let shortEnc = await lastValueFrom(this._encService.shortEncrypt(idEnc!));

      let menu: NestedMenuInterface = await lastValueFrom(this._modulesService.getMenu(shortEnc.response.encrypted, 1));

      this.menuItems = menu.response;
      this.isLoading = false;
    }catch(error: any){
      let errorStr = "";

      if(error.error == undefined){
        errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        errorStr = 'Ocurrió un error inesperado.';
      }else{
        errorStr = error.error.msg;
      }

      this.openDialog(errorStr);
    }
  }

  async navigate(modID: string){
    let route = modID.substring(10, modID.length);
    this.modulesActivated = false;
    this._router.navigate([`sam/${route}`]);
  }

  // Método de cerrar sesión de manera temporal
  public logoutTemp(){
    localStorage.removeItem('nombre_usuario');
    localStorage.removeItem('idusuario');
    localStorage.removeItem('correo');
    localStorage.removeItem('perfil');
    localStorage.removeItem('token');
    localStorage.removeItem('permisos');
    this._router.navigate(['login']);
    this._resouceService.openSnackBar('Hasta pronto');
  }


  public onResize(){
    this.title = window.innerWidth <= 1050 ? 'SAM L1' : 'Sistema de Ayuda al Manteniemiento L1';
  }

  closeNestedMenu(){
    this.modulesActivated = false;
  }

  openMyProfile(){
    this._dialg.open(MyProfileComponent, {
      width: '580px'
    });
  }
}
