import { Component, OnInit } from '@angular/core';
import { EquipmentsListItem, EquipmentsListResponse } from '../../../../interfaces/equipment-management.interface';
import { SymptomList } from '../../../../interfaces/failure-analysis/symptom.interface';
import { SCADA, SCADAList } from '../../../../interfaces/scada-list.interface';
import { lastValueFrom, map, Observable, startWith } from 'rxjs';
import { ActivatedRoute } from '@angular/router';
import { EncService } from '../../../../services/enc.service';
import { ResourcesService } from '../../../../services/resources.service';
import { EquipmentManagementService } from '../../../../services/equipment-management.service';
import { FormBuilder, FormControl, Validators } from '@angular/forms';
import { SystemAdminService } from '../../../../services/system-admin.service';
import { CountersActivatorsService } from '../../../../services/counters-activators.service';
import { CounterDetailsResponse } from '../../../../interfaces/counters-activators.interface';

@Component({
    selector: 'app-counter-form',
    templateUrl: './counter-form.component.html',
    styleUrl: './counter-form.component.css',
    standalone: false
})
export class CounterFormComponent implements OnInit {
  screenSize: number;
  isNew: boolean;
  isLoading: boolean;
  hasError: boolean;
  errorStr: string;
  idCounter: string;
  action: string;
  loadingChildren: boolean;
  loadingSymptoms: boolean;

  equipments: Map<number, EquipmentsListItem[]>;
  arborescence: boolean[];
  symptoms: SymptomList[];
  symptomsStr: string[];
  scadas: SCADA[];
  scadasStr: string[];
  counterFormGroup: any;

  filteredSymptoms?: Observable<string[]>;
  filteredSCADAs?: Observable<string[]>;

  constructor(
    private _activatedRoute: ActivatedRoute,
    private _encService: EncService,
    private _resourcesService: ResourcesService,
    private _equipmentManagementService: EquipmentManagementService,
    private _formBuilder: FormBuilder,
    private _systemAdminService: SystemAdminService,
    private _contersActivatorsService: CountersActivatorsService,
  ) {
    this.screenSize = window.innerWidth;
    this.isNew = true;
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = ""; 
    this.idCounter = "";
    this.action = "";
    this.loadingChildren = false;
    this.loadingSymptoms = false;

    this.equipments = new Map();
    this.arborescence = [false];
    this.symptoms = [];
    this.symptomsStr = [];
    this.scadas = [];
    this.scadasStr = [];

    this.counterFormGroup = this._formBuilder.group({
      equipment0Control: new FormControl('', Validators.required),
      arborescenceControl: this._formBuilder.array(this.arborescence),
      readIntervalControl: new FormControl('', Validators.required),
      readIntervalTimeUnitControl: new FormControl('', Validators.required),
      toleranceIntervalControl: new FormControl('', Validators.required),
      toleranceIntervalTimeUnitControl: new FormControl('', Validators.required),
      scadaControl: new FormControl({value: '', disabled: true}, Validators.required),
    });
  }

  ngOnInit(): void {
    for(const control of this.counterFormGroup.controls['arborescenceControl'].controls){
      control.disable();
    }

    this._activatedRoute.queryParams.subscribe(params => {
      let idCounterEnc = params['idCounter'];
      if(idCounterEnc == null || idCounterEnc == undefined || idCounterEnc == ''){
        this._resourcesService.openSnackBar('No se envió información.');
        this.goBack(1);
      }else{
        this.init(idCounterEnc);
      }
    });

    this.filteredSCADAs = this.counterFormGroup.controls['scadaControl'].valueChanges.pipe(
      startWith(''),
      map((value: string) => this._filterSCADAs(value || '')),
    );
  }

  goBack(steps: number){
    window.history.go(steps * -1);
  }

  private _filterSCADAs(value: string): string[]{
    const filterValue = value.toLowerCase();
    return this.scadasStr.filter(option => option.toLowerCase().includes(filterValue));
  }

  async init(idCounterEnc: string){
    let route = location.href;
    let routeArr = route.split('/').reverse();
    let typeArr = routeArr[0].split('?');
    let type = typeArr[0];

    if(type == 'nuevo'){
      this.isNew = true;
      this.action = "Registrar";

      this.getEquipments();
    }else{
      this.isNew = false;
      this.idCounter = await this._encService.decrypt(idCounterEnc);
      this.action = "Editar";

      this.getCounter(idCounterEnc);
    }
  }

  async getEquipments(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let equipments: EquipmentsListResponse = await lastValueFrom(this._equipmentManagementService.equipmentConsult(idUser, 1));

      this.hasError = equipments.error;
      this.errorStr = equipments.msg;

      if(this.hasError){
        this.isLoading = false;
      }else{
        let equipmentsArr: EquipmentsListItem[] = [];
        for(const equipment of equipments.response){
          let codeDec = await this._encService.decrypt(equipment.CODIGO);
          let idDec = await this._encService.decrypt(equipment.ID_EQUIPO);

          equipment.TIPO = `${codeDec} - ${equipment.TIPO}`;
          equipment.MODELO = `${equipment.MODELO} (${idDec})`;

          if(equipment.EQUIPO_PADRE == null){
            equipmentsArr.push(equipment);
          }
        }

        this.equipments.set(0, equipmentsArr);
        this.getSCADAs();
      }
    }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 getSCADAs(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let scadas: SCADAList = await lastValueFrom(this._systemAdminService.getSCADAList(idUser, 1));

      this.hasError = scadas.error;
      this.errorStr = scadas.msg;

      if(!this.hasError){
        let scadasArr: SCADA[] = [];
        let scadasStrArr: string[] = [];

        for(const scada of scadas.response){
          let scadaStr = `${scada.NOMBRESCADA} (${scada.IDSCADA})`;
          let idEnc = await this._encService.encrypt(`${scada.IDSCADA}`);
          scada.IDSCADA = idEnc;

          if(scada.ESTATUS == 'Activo'){
            scadasArr.push(scada);
            scadasStrArr.push(scadaStr);
          }
        }

        this.scadas = scadasArr;
        this.scadasStr = scadasStrArr;
      }

      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;
    }
  }

  async getCounter(idCounterEnc: string){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let counter: CounterDetailsResponse = await lastValueFrom(this._contersActivatorsService.counterConsultOnly(idCounterEnc, idUser, 1));

      this.hasError = counter.error;
      this.errorStr = counter.msg;

      if(this.hasError){
        this.isLoading = false;
      }else{
        let codeDec = await this._encService.decrypt(counter.response.CODIGO_EQUIPAMIENTO);
        let idEquipmentDec = await this._encService.decrypt(counter.response.ID_EQUIPAMIENTO);

        let equipment: EquipmentsListItem = {
          CODIGO: counter.response.CODIGO_EQUIPAMIENTO,
          TIPO: `${codeDec} - ${counter.response.TIPO_EQUIPAMIENTO}`,
          MODELO: `${counter.response.MODELO_EQUIPAMIENTO} (${idEquipmentDec})`,
          ID_EQUIPO: counter.response.ID_EQUIPAMIENTO,
          ESTADO_FUNCIONAMIENTO: '',
          ELEMENTO_ORIGEN: '',
          TIPO_CODIGO: '',
          EQUIPO_PADRE: null,
          TIENE_HIJOS: ''
        }

        let equipmentsArr: EquipmentsListItem[] = [equipment];
        this.equipments.set(0, equipmentsArr);

        this.counterFormGroup.controls['equipment0Control'].setValue(counter.response.CODIGO_EQUIPAMIENTO);
        this.counterFormGroup.controls['equipment0Control'].disable();

        let idScadaDec = await this._encService.decrypt(counter.response.ID_SCADA);
        this.counterFormGroup.controls['scadaControl'].setValue(`${counter.response.SCADA} (${idScadaDec})`);

        this.counterFormGroup.controls['readIntervalControl'].setValue(counter.response.INTERVALO);
        this.counterFormGroup.controls['readIntervalTimeUnitControl'].setValue(counter.response.UNIDAD_INTERVALO);
        this.counterFormGroup.controls['toleranceIntervalControl'].setValue(counter.response.TOLERANCIA_INTERVALO);
        this.counterFormGroup.controls['toleranceIntervalTimeUnitControl'].setValue(counter.response.UNIDAD_TOLERANCIA_INTERVALO);

        this.getSCADAs();
      }
    }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;
    }
  }

  public onResize(): void {
    this.screenSize = window.innerWidth;
  }

  async equipmentChange(position: number, value: string){
    let codeDec = await this._encService.decrypt(value);
    let equipmentFilt: EquipmentsListItem | null = null;

    for(const child of this.equipments.get(position)!){
      let cDec = await this._encService.decrypt(child.CODIGO);
      if(cDec == codeDec){
        equipmentFilt = child;
      }
    }

    let arborescenceAux: boolean[] = [];
    for(let i = 0; i <= position; i++){
      if(i > position){
        arborescenceAux[i] = false;
      }else{
        arborescenceAux[i] = this.arborescence[i];
      }
    }

    this.counterFormGroup.controls['arborescenceControl'].controls[position].setValue(false);
    this.arborescence = arborescenceAux;
    this.counterFormGroup.controls['arborescenceControl'] = this._formBuilder.array(this.arborescence);
    
    if(value != null && value != undefined && value != ''){
      if(equipmentFilt!.TIENE_HIJOS == 'Si'){
        this.counterFormGroup.controls['arborescenceControl'].controls[position].enable();
      }else{
        this.counterFormGroup.controls['arborescenceControl'].controls[position].disable();
      }
    }else{
      this.counterFormGroup.controls['arborescenceControl'].controls[position].disable();
    }
    this.counterFormGroup.controls['scadaControl'].enable();
  }

  async searchChildren(position: number){
    let value = this.counterFormGroup.controls['arborescenceControl'].controls[position].value;
    this.arborescence[position] = value;

    if(value){
      this.loadingChildren = true;
      this.arborescence.push(false);
      this.counterFormGroup.addControl(`equipment${position + 1}Control`, new FormControl('', Validators.required));

      let parent = this.counterFormGroup.controls[`equipment${position}Control`].value;
      let idUser = localStorage.getItem('idusuario')!;
      let children: EquipmentsListResponse = await lastValueFrom(this._equipmentManagementService.equipmentConsultByParent(
        parent, 
        idUser, 
        1
      ));

      if(children.error){
        this._resourcesService.openSnackBar(children.msg);
      }else{
        let equipmentsArr: EquipmentsListItem[] = [];
        for(const equipment of children.response){
          let codeDec = await this._encService.decrypt(equipment.CODIGO);
          equipment.TIPO = `${codeDec} - ${equipment.TIPO}`;

          let idDec = await this._encService.decrypt(equipment.ID_EQUIPO);
          equipment.MODELO = `${equipment.MODELO} (${idDec})`;
          
          equipmentsArr.push(equipment);
        }

        this.equipments.set(position + 1, equipmentsArr);
      }
      
      this.loadingChildren = false;
    }else{
      this.arborescence.pop();
      this.counterFormGroup.removeControl(`equipment${position + 1}Control`);
    }

    this.counterFormGroup.controls['arborescenceControl'] = this._formBuilder.array(this.arborescence);
    let index = 0;

    for(const control of this.counterFormGroup.controls['arborescenceControl'].controls){
      let equipment = this.counterFormGroup.controls[`equipment${index}Control`].value;
      
      if(equipment != null && equipment != undefined && equipment != ''){
        control.enable();
      }else{
        control.disable();
      }

      index++;
    }
  }

  validateNumber(value: string, controlName: string, event: string){
    let validChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
    let valueArr = value.split('');
    let validVal = '';
    let pointCont = 0;

    valueArr.forEach(char => {
      if(char == '.' && pointCont < 1){
        validVal += '.';
        pointCont++;
      }else if(validChars.includes(char)){
        validVal += char;
      }
    });

    if(event == 'blur' && validVal.charAt(0) == '.'){
      this.counterFormGroup.controls[controlName].setValue(`0${validVal}`);
    }else{
      this.counterFormGroup.controls[controlName].setValue(validVal);
    }
  }

  async registerCounter(){
    try{
      let formValue = this.counterFormGroup.getRawValue();
      let formData = new FormData();
      let idUser = localStorage.getItem('idusuario')!;

      formData.append('id_user', idUser);
      formData.append('linea', '1');

      let scadaArr = formValue.scadaControl.split('(').reverse();
      let scadaStr = scadaArr[0].replace(')', '');
      let scadaEnc = await this._encService.encrypt(scadaStr);

      formData.append('scada', scadaEnc);

      let equipment = '';
      if(this.isNew){
        equipment = formValue[`equipment${this.arborescence.length - 1}Control`];
      }else{
        equipment = formValue.equipment0Control;
      }

      formData.append('equipment', equipment);
      formData.append('time_interval', formValue.readIntervalControl);
      formData.append('time_interval_unit', formValue.readIntervalTimeUnitControl);
      formData.append('time_interval_tolerance', formValue.toleranceIntervalControl);
      formData.append('time_interval_tolerance_unit', formValue.toleranceIntervalTimeUnitControl);

      if(this.isNew){
        await lastValueFrom(this._contersActivatorsService.counterRegister(formData));
      }else{
        let idCounterEnc = await this._encService.encrypt(this.idCounter);
        formData.append('id_counter', idCounterEnc);

        await lastValueFrom(this._contersActivatorsService.counterUpdate(formData));
      }
      
      this._resourcesService.openSnackBar('El contador se registró correctamente.');
      this.goBack(1);
    }catch(error: any){
      if(error.error == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      }else if(error.error.msg == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      }else{
        this._resourcesService.openSnackBar(error.error.msg);
      }
    }
  }
}
