import { Component, OnInit } from '@angular/core';
import { UserResponse, UsersResponse } from '../../../interfaces/users.interface';
import { UsersProfilesService } from '../../../services/users-profiles.service';
import { EncService } from '../../../services/enc.service';
import { SocketService } from '../../../services/socket.service';
import { ConnectionsService } from '../../../services/connections.service';
import { Router } from '@angular/router';
import { ResourcesService } from '../../../services/resources.service';
import { FunctionsService } from '../../../services/functions.service';
import { Permissions } from '../../../interfaces/permissions.interface';
import { lastValueFrom } from 'rxjs';
import { UserConsultResponse } from '../../../interfaces/user.interface';
import { ProfileInterface } from '../../../interfaces/profile.interface';
import { ConnectionsResponse } from '../../../interfaces/connections.interface';

@Component({
    selector: 'app-connections',
    templateUrl: './connections.component.html',
    styleUrl: './connections.component.css',
    standalone: false
})
export class ConnectionsComponent implements OnInit {
  isLoading: boolean;
  hasError: boolean;
  errorStr: string;
  modIcon: string;
  modName: string;
  menuIcon: string;
  menuName: string;
  usersNames: Map<string, string>;
  usersLastConnections: Map<string, string>;

  users: UserResponse[];
  usersConnected: string[];
  usersDisconnected: string[];

  connectedUsers: number;
  disconnectedUsers: number;

  monitoringConnectionsEnabled: boolean;
  connectionsHistoryEnabled: boolean;

  constructor(
    private _usersProfilesService: UsersProfilesService, 
    private _encService: EncService,
    private _socketService: SocketService,
    private _connectionsService: ConnectionsService,
    private _router: Router,
    private _resourcesService: ResourcesService,
    private _functionsService: FunctionsService,
  ) {
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = "";
    this.modIcon = "";
    this.modName = "";
    this.menuIcon = "";
    this.menuName = "";
    this.usersNames = new Map();
    this.usersLastConnections =  new Map();

    this.users = [];
    this.usersConnected = [];
    this.usersDisconnected = [];

    this.connectedUsers = 0;
    this.disconnectedUsers = 0;

    this.monitoringConnectionsEnabled = true;
    this.connectionsHistoryEnabled = true;
  }

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

  async init(){
    try{
      let permissionsEnc = localStorage.getItem('permisos');
      let permissionsDec = await this._encService.decrypt(permissionsEnc!);
      let permissionsArr: Permissions = JSON.parse(permissionsDec);

      let modPerm = permissionsArr.permissions.filter(item => item.id == 'S002V01M01ADSI')[0];
      let funPerm = modPerm.children.filter(item => item.id == 'S002V01F01MAUS')[0];

      this.monitoringConnectionsEnabled = funPerm.children.filter(item => item.id == 'S002V01P01MOCO')[0].access > 0;
      this.connectionsHistoryEnabled = funPerm.children.filter(item => item.id == 'S002V01P02HICO')[0].access > 0;
      
      this.getUsers();
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
    }
  }

  async getUsers(){
    try{
      let idEnc = localStorage.getItem('idusuario')!;
      let users: UsersResponse = await lastValueFrom(this._usersProfilesService.getUsers(idEnc, 1));
      
      this.hasError = users.error;
      this.errorStr = users.msg;

      if(!this.hasError){
        let currentUser = localStorage.getItem('idusuario');
        let decryptedUser = await this._encService.decrypt(currentUser!);

        for(const item of users.response){
          item.IDUSUARIO = await this._encService.decrypt(item.IDUSUARIO);
          
          if(decryptedUser != item.IDUSUARIO){
            this.users.push(item);
            this.usersNames.set(item.IDUSUARIO, this.getUserName(item));
            this.usersLastConnections.set(item.IDUSUARIO, this.getLastConnection(item));
          }
        }
        
        this.buildConnections();
        this.initSocketListener();
      }

      this.isLoading = false;
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
    }
  }

  getUserName(item: UserResponse): string{
    let fullName = `${item.NOMBRE} ${item.APEPAT}`;
    if(item.APEMAT != null && item.APEMAT != undefined){
      fullName += ` ${item.APEMAT}`;
    }
    
    return `${fullName} (${item.IDUSUARIO})`;
  }

  getLastConnection(item: UserResponse): string{
    let meses = new Map<string, string>([
      ["01", "enero"],
      ["02", "febrero"],
      ["03", "marzo"],
      ["04", "abril"],
      ["05", "mayo"],
      ["06", "junio"],
      ["07", "julio"],
      ["08", "agosto"],
      ["09", "septiembre"],
      ["10", "octubre"],
      ["11", "noviembre"],
      ["12", "diciembre"],
    ]);
    
    let lastCon = item.ULCON;
    if(lastCon == null){
      return "-";
    }

    let dateTimeArr = lastCon.split(" ");
    let dateArr = dateTimeArr[0].split("-");
    let timeArr = dateTimeArr[1].split(":");

    let period = parseInt(timeArr[0]) > 12 ? "PM": "AM";
    let hour = parseInt(timeArr[0]) > 12 ? parseInt(timeArr[0]) - 12 : parseInt(timeArr[0]);
    let hourStr = hour < 10 ? `0${hour}` : `${hour}`;
    let la = hour == 1 ? "la" : "las";

    return `El ${dateArr[2]} de ${meses.get(dateArr[1])} del ${dateArr[0]} a ${la} ${hourStr}:${timeArr[1]} ${period}`;
  }

  buildConnections(){
    this.usersDisconnected = [];
    this.disconnectedUsers = 0;
    this.users.forEach(item => {
      if(!this.usersConnected.includes(item.IDUSUARIO)){
        this.usersDisconnected.push(item.IDUSUARIO);
        this.disconnectedUsers++;
      }
    });
  }

  async initSocketListener(){
    let currentId = localStorage.getItem('idusuario')!;
    let currentIdDec = await this._encService.decrypt(currentId);

    this._socketService.currentConnections().subscribe(async (res) => {
      let resStr = `${res}`;
      let resArr: string[] = JSON.parse(resStr);

      this.usersConnected = [];
      this.connectedUsers = 0;

      for(const item of resArr){
        let itemArr = `${item}`.split('.');
        let idDec = await this._encService.decrypt(itemArr[0]);

        if(idDec != currentIdDec){
          if(!this.usersConnected.includes(idDec)){
            this.usersConnected.push(idDec);
            this.connectedUsers++;
          }
            
          this.buildConnections();
        }
      }
    });

    this._socketService.newConnection().subscribe(async (res) => {
      let resStr = `${res}`;
      let resArr = JSON.parse(resStr);

      this.usersConnected = [];
      this.connectedUsers = 0;

      for(const item of resArr){
        let itemArr = `${item}`.split('.');
        let idDec = await this._encService.decrypt(itemArr[0]);

        if(idDec != currentIdDec){
          if(!this.usersConnected.includes(idDec)){
            this.usersConnected.push(idDec);
            this.connectedUsers++;
          }
          
          this.buildConnections();
        }
      }
    });

    this._socketService.disconnection().subscribe(async (res) => {
      let resStr = `${res}`;
      let resArr = JSON.parse(resStr);

      this.usersConnected = [];
      this.connectedUsers = 0;
      
      for(const item of resArr){
        let itemArr = `${item}`.split('.');
        let idDec = await this._encService.decrypt(itemArr[0]);

        if(idDec != currentIdDec){
          if(!this.usersConnected.includes(idDec)){
            this.usersConnected.push(idDec);
            this.connectedUsers++;
          }
          
          this.buildConnections();
        }else{
          this.getConnections();
          this.buildConnections();
        }
      }
    });
    
    this._socketService.getConnections();

    this._socketService.refreshPermissions().subscribe(async (profUpdEnc) => {
      try{
        let idUser = localStorage.getItem('idusuario')!;
        let usrInfo: UserConsultResponse = await lastValueFrom(this._usersProfilesService.getUser(idUser, idUser, 1));
        
        if(usrInfo.error){
          this._resourcesService.openSnackBar('ERR_NPE000: Ocurrió un error inesperado.');
        }else{
          let idProfDec = await this._encService.decrypt(usrInfo.response.PERFIL);
          let currentProfile = await this._encService.decrypt(localStorage.getItem('perfil')!);

          if(idProfDec != currentProfile){
            this._router.navigate(['/sam/home']);
            return;
          }
          
          let profileUpdated = await this._encService.decrypt(`${profUpdEnc}`);
          if(profileUpdated == currentProfile){
            let profile = localStorage.getItem('perfil')!;
            let profInfo: ProfileInterface = await lastValueFrom(this._usersProfilesService.getProfile(
              profile,
              idUser,
              1
            ));

            let permArr = await this._functionsService.processPermissions(profInfo.response.PERMISOS.permissions);
            let modPerm = permArr.filter(item => item.id == 'S002V01M01ADSI');
            if(modPerm.length > 0){
              let funPerm = modPerm[0].children.filter(item => item.id == 'S002V01F01MAUS');
              if(funPerm.length > 0){
                let monitoringConnectionsEnabled = funPerm[0].children.filter(item => item.id == 'S002V01P01MOCO');
                if(monitoringConnectionsEnabled.length > 0){
                  this.monitoringConnectionsEnabled = monitoringConnectionsEnabled[0].access > 0;
                }

                let connectionsHistoryEnabled = funPerm[0].children.filter(item => item.id == 'S002V01P02HICO');
                if(connectionsHistoryEnabled.length > 0){
                  this.connectionsHistoryEnabled = connectionsHistoryEnabled[0].access > 0;
                }
              }
            }
          }
        }
      }catch(error: any){
        if(error.error == undefined){
          this._resourcesService.openSnackBar('ERR_PAD001: Ocurrió un error inesperado.');
        }else if(error.error.msg == undefined){
          this._resourcesService.openSnackBar('ERR_PAD002: Ocurrió un error inesperado.');
        }else{
          this._resourcesService.openSnackBar(`ERR_PAD003: ${error.error.msg}`);
        }
      }
    });
  }

  async getConnections(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let connections: ConnectionsResponse = await lastValueFrom(this._connectionsService.getUsersConnections(
        idUser,
        1
      ));

      if(connections.error){
        this._resourcesService.openSnackBar(connections.msg);
      }else{
        for(const connection of connections.response){
          let userFilt = this.users.filter(item => item.IDUSUARIO == connection.IDUSUARIO);
          if(userFilt.length > 0){
            let index = this.users.indexOf(userFilt[0]);
          
            let usrSus: UserResponse = {
              IDUSUARIO: userFilt[0].IDUSUARIO,
              NOMBRE: userFilt[0].NOMBRE,
              APEPAT: userFilt[0].APEPAT,
              APEMAT: userFilt[0].APEMAT,
              EMAIL: userFilt[0].EMAIL,
              PERFIL: userFilt[0].PERFIL,
              ESTATUS: userFilt[0].ESTATUS,
              ULCON: connection.ULCON,
              TIENE_PANEL: false,
              PANEL_CONTROL: ''
            }
          
            this.users[index] = usrSus;
          }
        }
      }
    }catch(error: any){
      this._resourcesService.openSnackBar("No fue posible recuperar las últimas conexiones de los usuarios");
    }
  }

  async openConnections(id: string){
    if(!this.connectionsHistoryEnabled){
      this._resourcesService.openSnackBar('Su perfil no tiene permisos suficientes para ejecutar la acción solicitada.');
    }else{
      let idEnc = await this._encService.encrypt(id);
      this._router.navigate(['sam/ADSI/MAUS/detalles'], {
        queryParams: {
          info: idEnc
        }
      });
    }
  }
}
