import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { LoginService } from '../../services/login.service';
import { GeolocationService } from '@ng-web-apis/geolocation';
import { LoginDataService } from '../../services/login-data.service';
import { EncService } from '../../services/enc.service';
import { SystemAdminService } from '../../services/system-admin.service';
import { GeolocationService as Gservice } from '../../services/geolocation.service';
import { ResourcesService } from '../../services/resources.service';
import { lastValueFrom, take } from 'rxjs';
import { LoginPlace } from '../../interfaces/user-connections.interface';
import { GeolocationResponse } from '../../interfaces/location-response.interface';
import { LoginResponse } from '../../interfaces/login.interface';
import { MaintenanceStatusResponse } from '../../interfaces/maintenance-status.interface';
import { Permissions } from '../../interfaces/permissions.interface';

@Component({
    selector: 'app-login',
    templateUrl: './login.component.html',
    styleUrl: './login.component.css',
    standalone: false
})
export class LoginComponent implements OnInit {
  formGroup: FormGroup;
  hide: boolean;
  isLoading: boolean;

  constructor(
    private _router: Router,
    private _loginService: LoginService,
    private _resourcesService: ResourcesService,
    private readonly _geolocation$: GeolocationService,
    private _loginDataService: LoginDataService,
    private _encService: EncService,
    private _systemAdminService: SystemAdminService,
    private _geolocationService: Gservice,
  ) {
    this.formGroup = this.createFormGroup();
    this.hide = true;
    this.isLoading = false;
  }

  ngOnInit(): void { }

  private createFormGroup() {
    return new FormGroup({
      email: new FormControl('', [Validators.required, Validators.email]),
      password: new FormControl('', Validators.required),
    });
  }

  public login() {
    this.isLoading = true;
    if(this.formGroup.controls['email'].invalid){
      this._resourcesService.openSnackBar("El correo electrónico es un campo obligatorio.");
      return;
    }

    if(this.formGroup.controls['password'].invalid){
      this._resourcesService.openSnackBar("La contraseña es un campo obligatorio.");
      return;
    }
    
    let uriArr = window.location.href.split(':');
    if(uriArr[0] == 'https'){
      this._geolocation$.pipe(take(1)).subscribe(position => {
        let userPosition: LoginPlace = {
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
          accuracy: position.coords.accuracy
        };
  
        this.requestLogin(userPosition);
      });
    }else{
      let userPosition: LoginPlace = {
        latitude: 19.3477,
        longitude: -99.1877,
        accuracy: 169665
      };
  
      this.requestLogin(userPosition);
    }
  }
  
  async requestLogin(position: LoginPlace){
    try{
      let pwdEnc = await this._encService.encrypt(this.formGroup.controls['password'].value);
      let loginPlace: GeolocationResponse | boolean = await this._getPlace(position);

      if(!loginPlace){
        this._resourcesService.openSnackBar('No se pudo obtener la ubicación del usuario, por favor intente más tarde.');
        this.isLoading = false;
      }else{
        let location: GeolocationResponse = loginPlace as GeolocationResponse;

        let lati = position.latitude;
        let long = position.longitude;
        let prec = position.accuracy;

        let ciud = location.locality;
        let esta = location.city;
        let pais = location.countryName;

        let loginResponse: LoginResponse = await lastValueFrom(this._loginService.login({
          email: this.formGroup.controls['email'].value,
          password: pwdEnc,
          linea: 1,
          latitude: lati,
          longitude: long,
          accuracy: prec,
          city: ciud,
          state: esta == '' ? '-' : esta,
          country: pais,
        }));

        if (loginResponse.error == false) {
          let maintenanceStatus: MaintenanceStatusResponse = await lastValueFrom(this._systemAdminService.getMaintenanceStatus(
            loginResponse.response.IDUSUARIO, 1, loginResponse.response.TOKEN
          ));

          if(maintenanceStatus.response.activated){
            let permisosDec = await this._encService.decrypt(loginResponse.response.PERMISOS);
            let permisosArr: Permissions = JSON.parse(permisosDec);

            let systemAdmin = permisosArr.permissions.filter(mod => mod.id == 'S002V01M01ADSI')[0];
            if(systemAdmin.access != 0){
              let maintenanceMode = systemAdmin.children.filter(func => func.id == 'S002V01F05MOMA')[0];

              if(maintenanceMode.access != 0){
                let activateMaintenance = maintenanceMode.children.filter(scr => scr.id == 'S002V01P01AMMA')[0];

                if(activateMaintenance.access == 2){
                  let maintenance = await this._encService.encrypt(JSON.stringify({
                    idUser: loginResponse.response.IDUSUARIO,
                    maintenance: 'enabled',
                  }));

                  this._loginDataService.saveLoginInformation(
                    loginResponse.response.TOKEN,
                    loginResponse.response.IDUSUARIO,
                    loginResponse.response.NOMBREUSUARIO,
                    loginResponse.response.CORREO,
                    loginResponse.response.PERFIL,
                    loginResponse.response.PERMISOS,
                    loginResponse.response.PANEL,
                  );

                  this._router.navigate(['sam/home'], { queryParams: { data: maintenance } });
                }else{
                  this.isLoading = false;
                  this._resourcesService.openSnackBar("Lo sentimos, en este momento el sistema se encuentra en modo mantenimiento.");
                }
              }else{
                this.isLoading = false;
                this._resourcesService.openSnackBar("Lo sentimos, en este momento el sistema se encuentra en modo mantenimiento.");
              }
            }else{
              this.isLoading = false;
              this._resourcesService.openSnackBar("Lo sentimos, en este momento el sistema se encuentra en modo mantenimiento.");
            }
          }else{
            this._loginDataService.saveLoginInformation(
              loginResponse.response.TOKEN,
              loginResponse.response.IDUSUARIO,
              loginResponse.response.NOMBREUSUARIO,
              loginResponse.response.CORREO,
              loginResponse.response.PERFIL,
              loginResponse.response.PERMISOS,
              loginResponse.response.PANEL,
            );

            this._router.navigate(['sam/home']);
          }
        }
      }
    }catch(error: any){
      console.log(error);
      
      if(error.error == undefined){
        this._resourcesService.openSnackBar("Ocurrió un error inesperado (1).");
      }else if(error.error.msg == undefined){
        this._resourcesService.openSnackBar("Ocurrió un error inesperado (2).");
      }else{
        this._resourcesService.openSnackBar(error.error.msg);
      }

      this.isLoading = false;
    }
  }

  async _getPlace(coords: LoginPlace): Promise<GeolocationResponse | boolean>{
    try{
      let location: GeolocationResponse = await lastValueFrom(this._geolocationService.getLocationName(coords));

      return location;
    }catch(error: any){
      let msgError = "";

      if(error.error !== undefined){
        msgError = error.error.msg;
      }else{
        msgError = "Ocurrió un error inesperado (3).";
      }

      this._resourcesService.openSnackBar(msgError);

      return false;
    }
  }
}
