import { DOCUMENT } from '@angular/common';
import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { ResourcesService } from '../../../../services/resources.service';
import { CorrectiveWorkOrderDetailsResponse, WorkOrderStatusHistoryListItem } from '../../../../interfaces/corrective-maintenance.interface';
import { lastValueFrom } from 'rxjs';
import { CorrectiveMaintenanceService } from '../../../../services/corrective-maintenance.service';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { EncService } from '../../../../services/enc.service';
import { EmployeeService } from '../../../../services/personal-management/employee.service';
import { EmployeesListItem, EmployeesListResponse } from '../../../../interfaces/personal-managment/employee.interface';
import { SubcontratistService } from '../../../../services/personal-management/subcontratist.service';
import { SubcontratistItem, SubcontratistsResponse } from '../../../../interfaces/personal-managment/subcontratists.interface';

@Component({
  selector: 'app-staff-selection',
  standalone: false,
  templateUrl: './staff-selection.component.html',
  styleUrl: './staff-selection.component.css'
})
export class StaffSelectionComponent implements OnInit {
  isLoading: boolean;
  hasError: boolean;
  errorStr: string;
  staffSpecialtiesMap: Map<string, string>;
  staffOperariesMap: Map<string, string[]>;
  employees: EmployeesListItem[];
  subcontratists: EmployeesListItem[];
  excludedUsers: string[];

  formGroup: FormGroup;

  constructor(
    @Inject(MAT_DIALOG_DATA) private _data: any,
    @Inject(DOCUMENT) private _document: Document,
    private _resourcesService: ResourcesService,
    private _dialogRef: MatDialogRef<StaffSelectionComponent>,
    private _correctiveMaintenanceService: CorrectiveMaintenanceService,
    private _encService: EncService,
    private _employeeService: EmployeeService,
    private _subcontratistService: SubcontratistService,
  ) {
    this.isLoading = true;
    this.hasError = true;
    this.errorStr = "";
    this.staffSpecialtiesMap = new Map();
    this.staffOperariesMap = new Map();
    this.employees = [];
    this.subcontratists = [];
    this.excludedUsers = [];

    this.formGroup = new FormGroup({});
  }

  ngOnInit(): void {
    if(this._data.idOrder != null && this._data.idOrder != undefined){
      this.getOrderDetails();
    }else{
      this._resourcesService.openSnackBar('No se envió el ID de la orden de mantenimiento.');
      this._dialogRef.close();
    }
  }

  private async getOrderDetails(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let order: CorrectiveWorkOrderDetailsResponse = await lastValueFrom(this._correctiveMaintenanceService.getWorkOrder(
        this._data.idOrder,
        idUser,
        1
      ));

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

      if(this.hasError){
        this.isLoading = false;
      }else{
        let statusHistory: WorkOrderStatusHistoryListItem[] = JSON.parse(order.response.HISTORIAL_ESTATUS);
        let validatedStatus = statusHistory.filter(item => item.ESTADO == 'VA');

        if(validatedStatus.length > 0){
          let excludedUsersArr: string[] = [];
          for(const item of validatedStatus[0].ATENCION!){
            if(item.RESPUESTA == 'R') excludedUsersArr.push(item.ID);
          }

          this.excludedUsers = excludedUsersArr;
        }

        let staffArr = JSON.parse(order.response.PERSONAL);
        for(const specialty of staffArr){
          let idDec = await this._encService.decrypt(specialty.ID);
          this.staffSpecialtiesMap.set(idDec, specialty.NAME);

          let operaries: string[] = this.staffOperariesMap.get(idDec) === undefined ? [] : this.staffOperariesMap.get(idDec)!;
          for(let i = 0; i < specialty.CANT; i++){
            let index = `${idDec}${i}Control`;
            this.formGroup.addControl(index, new FormControl('', Validators.required));
            
            operaries.push(index);
          }

          this.staffOperariesMap.set(idDec, operaries);
        }

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

  private async getEmployees(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let employees: EmployeesListResponse = await lastValueFrom(this._employeeService.getConsultOfEmployees(idUser, 1));

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

      if(this.hasError){
        this.isLoading = false;
      }else{
        let employeesArr: EmployeesListItem[] = [];
        let subcontratistsEmployees: EmployeesListItem[] = [];
        
        for(const employee of employees.response){
          let idEmployee = await this._encService.decrypt(employee.ID_EMPLOYEE);
          employee.NAME = `${employee.NAME} (${idEmployee})`;

          if(employee.CONTRACT_TYPE == 'Interno' && employee.STATUS == 'Activo'){
            let specialtiesArr = JSON.parse(employee.SPECIALITY);
            let specialtiesStrArr: string[] = [];

            for(const specialtyStr of specialtiesArr){
              let specialtyEnc = await this._encService.isEncrypted(specialtyStr);
              let specialtyDec = specialtyEnc ? await this._encService.decrypt(specialtyStr) : specialtyStr;
              let specialtyArr = specialtyDec.split(" - ");
              let specialtyInd = specialtyArr[0];

              specialtiesStrArr.push(specialtyInd);
            }

            employee.SPECIALITY_ARR = specialtiesStrArr;
            let idUser = await this._encService.decrypt(employee.ID_USUARIO);
            let userExceptionFilt = this.excludedUsers.filter(item => item == idUser);

            if(userExceptionFilt.length <= 0){
              employeesArr.push(employee);
            }
          }else if(employee.CONTRACT_TYPE == 'Subcontratista'){
            subcontratistsEmployees.push(employee);
          }
        }

        this.employees = employeesArr;
        this.getSubcontratists(subcontratistsEmployees);
      }
    }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;
      }
    }
  }

  private async getSubcontratists(subcontratistsEmployees: EmployeesListItem[]){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let subcontratists: SubcontratistsResponse = await lastValueFrom(this._subcontratistService.getConsultOfSubcontratists(idUser, 1));

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

      if(!this.hasError){
        let subcontratistsArr: SubcontratistItem[] = [];
        for(const subcontratist of subcontratists.response){
          subcontratist.ID_SUBCONTRATIST = await this._encService.decrypt(subcontratist.ID_SUBCONTRATIST);
          subcontratistsArr.push(subcontratist);
        }

        let subcontratistEmployeesArr: EmployeesListItem[] = [];
        for(const employee of subcontratistsEmployees){
          let idSubcontratistDec = await this._encService.decrypt(employee.ID_SUBCONTRATISTA!);
          let subcontratistFilt = subcontratistsArr.filter(item => item.ID_SUBCONTRATIST == idSubcontratistDec);

          if(subcontratistFilt.length > 0){
            let specialtiesArr = JSON.parse(employee.SPECIALITY);
            let specialtiesStrArr: string[] = [];

            for(const specialtyStr of specialtiesArr){
              let specialtyEnc = await this._encService.isEncrypted(specialtyStr);
              let specialtyDec = specialtyEnc ? await this._encService.decrypt(specialtyStr) : specialtyStr;
              let specialtyArr = specialtyDec.split(" - ");
              let specialtyInd = specialtyArr[0];

              specialtiesStrArr.push(specialtyInd);
            }
            
            employee.SPECIALITY_ARR = specialtiesStrArr;
            employee.NAME = `${subcontratistFilt[0].NAME} - ${employee.NAME}`;
            let idUser = await this._encService.decrypt(employee.ID_USUARIO);
            let userExceptionFilt = this.excludedUsers.filter(item => item == idUser);

            if(userExceptionFilt.length <= 0){
              subcontratistEmployeesArr.push(employee);
            }
          }
        }

        this.subcontratists = subcontratistEmployeesArr;
      }

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

  isSelected(value: string): boolean{
    let isSelected = false;

    for(const key in this.formGroup.controls){
      let control = this.formGroup.controls[key];
      let selection = control.value;

      if(selection != null && selection != undefined && selection != '' && selection == value){
        isSelected = true;
      }
    }

    return isSelected;
  }

  async saveConfig(){
    let config = [];
    for(const key of this.staffOperariesMap.keys()){
      let operaries = this.staffOperariesMap.get(key)!;
      let operariesConfig = [];

      for(const control of operaries){
        let controlValue = this.formGroup.controls[control].value;
        let valueArr = controlValue.split('|');

        if(valueArr.length > 1){
          let operaryConfig = {
            ID: valueArr[0],
            TYPE: valueArr[1],
          };

          operariesConfig.push(operaryConfig);
        }
      }

      let specialtyConfig = {
        SPECIALTY: await this._encService.encrypt(key),
        STAFF: operariesConfig
      };

      config.push(specialtyConfig);
    }

    let configStr = JSON.stringify(config);
    this._dialogRef.close(configStr);
  }
}
