import { Component, Inject, OnInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { EquipmentDetailsResponse, EquipmentsListItem, EquipmentsListResponse } from '../../../../interfaces/equipment-management.interface';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { EmployeesListItem, EmployeesListResponse } from '../../../../interfaces/personal-managment/employee.interface';
import { SubcontratistItem, SubcontratistsResponse } from '../../../../interfaces/personal-managment/subcontratists.interface';
import { DOCUMENT } from '@angular/common';
import { PreventiveMaintenanceService } from '../../../../services/preventive-maintenance.service';
import { EquipmentManagementService } from '../../../../services/equipment-management.service';
import { EncService } from '../../../../services/enc.service';
import { ResourcesService } from '../../../../services/resources.service';
import { MatDialog } from '@angular/material/dialog';
import { EmployeeService } from '../../../../services/personal-management/employee.service';
import { SubcontratistService } from '../../../../services/personal-management/subcontratist.service';
import { WorkTeamService } from '../../../../services/personal-management/work-team.service';
import { lastValueFrom } from 'rxjs';
import { EquipmentDetailsDialogComponent } from '../../../equipment-management/new-equipment/equipment-details-dialog/equipment-details-dialog.component';
import { EquipmentDocumentsComponent } from '../../../equipment-management/equipment-documents/equipment-documents.component';

interface ToolInfo{
  ID: string;
  NOMB: string;
  MODE: string;
  CANTDISP: number;
  TYPE: string;
  UNIT: string;
}
const TOOLS_TMP: ToolInfo[] = [
  {ID: 'H1', NOMB: 'Pinzas eléctricas', MODE: 'PE-862', CANTDISP: 35, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H2', NOMB: 'Pinzas mecánicas', MODE: 'M985', CANTDISP: 27, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H3', NOMB: 'Pinzas de presión', MODE: 'RG-12', CANTDISP: 30, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H4', NOMB: 'Juego de llaves Allen', MODE: 'ALL88', CANTDISP: 75, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H5', NOMB: 'Extractor de rodamientos', MODE: 'EX-ROD-1500', CANTDISP: 3, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H6', NOMB: 'Kit llaves inglesas', MODE: '5530S', CANTDISP: 7, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H7', NOMB: 'Kit llaves españolas', MODE: '964F', CANTDISP: 8, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H8', NOMB: 'Juego de llaves Torx', MODE: 'TORX3423W', CANTDISP: 42, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H9', NOMB: 'Cautín de lápiz 33W', MODE: '33WCL', CANTDISP: 15, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H10', NOMB: 'Juego de dados milimétricos', MODE: 'DMM450', CANTDISP: 6, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H11', NOMB: 'Juego de dados pulgadas', MODE: 'DIN865', CANTDISP: 9, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H12', NOMB: 'Probador de corriente', MODE: '569', CANTDISP: 33, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H13', NOMB: 'Multímetro', MODE: 'TGH885', CANTDISP: 17, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H14', NOMB: 'Planta generadora para soldadura', MODE: 'PLAGEN-589', CANTDISP: 1, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H15', NOMB: 'Amperímetro de gancho', MODE: 'A0032', CANTDISP: 4, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H16', NOMB: 'Rotomartillo', MODE: '551', CANTDISP: 2, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H17', NOMB: 'Kit taladro inalámbrico', MODE: 'FP581', CANTDISP: 12, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H18', NOMB: 'Kit taládro alámbrico', MODE: 'HG862', CANTDISP: 10, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H19', NOMB: 'Juego de desarmadores', MODE: '8913-KSOA', CANTDISP: 5, TYPE: 'Herramienta', UNIT: 'Pieza'},
  {ID: 'H20', NOMB: 'Martillo', MODE: 'TS438', CANTDISP: 23, TYPE: 'Herramienta', UNIT: 'Pieza'},
];
const SPARE_PARTS_TMP: ToolInfo[] = [
  {ID: 'S1', NOMB: 'Neumático para NM-16', MODE: 'NM16NEU235', CANTDISP: 45, TYPE: 'Refaccción', UNIT: 'Pieza'},
  {ID: 'S2', NOMB: 'Neumático para NM-22', MODE: 'NM22NEU652', CANTDISP: 51, TYPE: 'Refaccción', UNIT: 'Pieza'},
  {ID: 'S3', NOMB: 'Rodamiento cónico', MODE: 'RC-4265', CANTDISP: 84, TYPE: 'Refaccción', UNIT: 'Pieza'},
  {ID: 'S4', NOMB: 'Rodamiento axial', MODE: 'RA-5130', CANTDISP: 96, TYPE: 'Refaccción', UNIT: 'Pieza'},
  {ID: 'S5', NOMB: 'Rodamiento angular', MODE: 'RN-3541', CANTDISP: 79, TYPE: 'Refaccción', UNIT: 'Pieza'},
  {ID: 'S6', NOMB: 'Grasa 1-310', MODE: 'G1.310', CANTDISP: 9, TYPE: 'Refaccción', UNIT: 'Kilogramo'},
  {ID: 'S7', NOMB: 'Aceite 10W-40', MODE: 'A10W40', CANTDISP: 16, TYPE: 'Refaccción', UNIT: 'Litro'},
  {ID: 'S8', NOMB: 'Soldadura de estaño', MODE: 'LDA-913', CANTDISP: 39, TYPE: 'Refaccción', UNIT: 'Metro'},
  {ID: 'S9', NOMB: 'Soldadura de plata', MODE: 'BDA-516', CANTDISP: 21, TYPE: 'Refaccción', UNIT: 'Metro'},
  {ID: 'S10', NOMB: 'Pastilla de frenado', MODE: '754SSV', CANTDISP: 25, TYPE: 'Refaccción', UNIT: 'Pieza'},
  {ID: 'S11', NOMB: 'Cable de cobre calibre 0', MODE: 'CC0-884', CANTDISP: 120, TYPE: 'Refaccción', UNIT: 'Metro'},
  {ID: 'S12', NOMB: 'Rosetas de cable Ethernet', MODE: '165-BFS', CANTDISP: 12, TYPE: 'Refaccción', UNIT: 'Pieza'},
  {ID: 'S13', NOMB: 'Pintura', MODE: '53469', CANTDISP: 250, TYPE: 'Refaccción', UNIT: 'Litro'},
  {ID: 'S14', NOMB: 'Solvente de pintura', MODE: '2516', CANTDISP: 310, TYPE: 'Refaccción', UNIT: 'Litro'},
  {ID: 'S15', NOMB: 'Lámina galvanizada', MODE: 'SFAS-320', CANTDISP: 38, TYPE: 'Refaccción', UNIT: 'Pieza'},
  {ID: 'S16', NOMB: 'Botón de freno de emergencia', MODE: 'B-51321', CANTDISP: 14, TYPE: 'Refaccción', UNIT: 'Pieza'},
  {ID: 'S17', NOMB: 'Disco duro de estado sólido 512GB', MODE: 'SSD-512', CANTDISP: 22, TYPE: 'Refaccción', UNIT: 'Pieza'},
  {ID: 'S18', NOMB: 'Mouse óptico', MODE: 'MO1165', CANTDISP: 26, TYPE: 'Refaccción', UNIT: 'Pieza'},
  {ID: 'S19', NOMB: 'Teclado para PC', MODE: '5413', CANTDISP: 24, TYPE: 'Refaccción', UNIT: 'Pieza'},
  {ID: 'S20', NOMB: 'Cable HDMI 2m', MODE: 'ASD-181', CANTDISP: 6, TYPE: 'Refaccción', UNIT: 'Pieza'},
];
@Component({
    selector: 'app-new-visit',
    templateUrl: './new-visit.component.html',
    styleUrl: './new-visit.component.css',
    standalone: false
})
export class NewVisitComponent implements OnInit {
  btnSmall: boolean;

  equipmentDataSource?: MatTableDataSource<EquipmentsListItem>;
  personalDataSource?: MatTableDataSource<any>;
  toolsDataSource?: MatTableDataSource<any>;

  equipmentDisplayedColumns = ['EQUIPO', 'ACCIONES'];
  personalDisplayedColumns = ['EMPLEADO', 'ESPECIALIDAD'];
  toolsDisplayedColumns = ['ITEM', 'TIPO', 'CANTDISP', 'CANTNEC', 'CANTRES'];

  equipments: EquipmentsListItem[];
  tools: ToolInfo[];
  toolsParts: ToolInfo[];
  spareParts: ToolInfo[];

  formGroup: FormGroup = new FormGroup({
    equipmentControl: new FormControl('', Validators.required),
    staffControl: new FormControl([], Validators.required),
    toolsControl: new FormControl([], Validators.required),
    sparePartsControl: new FormControl([], Validators.required),
    comments: new FormControl('', [Validators.required, Validators.minLength(35)]),
  });

  isSaving: boolean;
  isLoading: boolean;
  hasError: boolean;
  errorStr: string;
  employees: EmployeesListItem[];
  subcontratists: SubcontratistItem[];
  workTeams: any[];

  constructor(
    @Inject(DOCUMENT) private _document: Document,
    private _prevMaintService: PreventiveMaintenanceService,
    private _equipmentsService: EquipmentManagementService,
    private _encService: EncService,
    private _resourcesService: ResourcesService,
    private _dialog: MatDialog,
    private _employeeService: EmployeeService,
    private _subcontratistService: SubcontratistService,
    private _workTeamsService: WorkTeamService,
  ) { 
    this.btnSmall = window.innerWidth <= 1405;
    this.equipments = [];
    this.tools = TOOLS_TMP;
    this.spareParts = SPARE_PARTS_TMP;
    this.equipmentDataSource = new MatTableDataSource();
    this.personalDataSource = new MatTableDataSource();
    this.toolsDataSource = new MatTableDataSource();
    this.toolsParts = [];

    this.isSaving = false;
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = '';
    this.employees = [];
    this.subcontratists = [];
    this.workTeams = [];
  }

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

  async getEquipments(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let equipments: EquipmentsListResponse = await lastValueFrom(this._equipmentsService.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 equipmentCodeDec = await this._encService.decrypt(equipment.CODIGO);
          equipment.TIPO = `${equipmentCodeDec} - ${equipment.TIPO}`;

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

          equipmentsArr.push(equipment);
        }

        this.equipments = equipmentsArr;
        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;
      }
    }
  }

  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;
      }
      if(!this.hasError){
        for(const employee of employees.response){
          if(employee.STATUS == 'Activo'){
            let idEmployeeDec = await this._encService.decrypt(employee.ID_EMPLOYEE);
            employee.NAME = `${employee.NAME} (${idEmployeeDec})`;

            let specialtiesArr = JSON.parse(employee.SPECIALITY);
            let specialtiesArrDec: string[] = [];

            for(const specialty of specialtiesArr){
              let specialtyDec = await this._encService.decrypt(specialty);
              specialtiesArrDec.push(specialtyDec);
            }

            employee.SPECIALITY = JSON.stringify(specialtiesArrDec);
            this.employees.push(employee);
          }
        }

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

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

  async getSubcontratists(){
    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){
        this.isLoading = false;
      }else{
        for(const subcontratist of subcontratists.response){
          let idSubcontratistDec = await this._encService.decrypt(subcontratist.ID_SUBCONTRATIST);
          subcontratist.NAME = `${subcontratist.NAME} (${idSubcontratistDec})`;
          if(subcontratist.STATUS == 'Activo'){
            this.subcontratists.push(subcontratist);
          }
        }

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

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

  async getWorkTeams(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let workTeams = await lastValueFrom(this._workTeamsService.getConsultOfWorkteams(idUser, 1));

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

      if(!this.hasError){
        for(const workTeam of workTeams.response){
          if(workTeam.STATUS == 'Activo'){
            let idWorkTeamDec = await this._encService.decrypt(workTeam.WORKTEAM_ID);
            workTeam.NAME = `${workTeam.NAME} (${idWorkTeamDec})`;

            let specialtiesArr = JSON.parse(workTeam.SPECIALITY);
            let specialtiesArrDec: string[] = [];

            for(const specialty of specialtiesArr){
              let specialtyDec = await this._encService.decrypt(specialty);
              specialtiesArrDec.push(specialtyDec);
            }

            workTeam.SPECIALITY = JSON.stringify(specialtiesArrDec);
            this.workTeams.push(workTeam);
          }
        }
      }

      this.isLoading = false;
    }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);
      }

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

  public onResize():void {
    this.btnSmall = window.innerWidth <= 1405;
  }
  
  goBack(steps: number){
    window.history.go(steps * -1);
  }

  changeEquipmentTable(equimpentCode: string){
    let equipment = this.equipments.filter(item => item.CODIGO == equimpentCode);
    this.equipmentDataSource = new MatTableDataSource(equipment);
  }

  async openEquipmentDetails(equipmentCode: string){
    this._dialog.open(EquipmentDetailsDialogComponent, {
      width: '480px',
      maxWidth: '480px',
      data: {
        code: equipmentCode,
      }
    });
  }

  async openEquipmentDocuments(equipmentCode: string){
    try{
      this._resourcesService.openSnackBar('Obteniendo lista de documentos...');

      let idUser = localStorage.getItem('idusuario')!;
      let equipment: EquipmentDetailsResponse = await lastValueFrom(this._equipmentsService.equipmentConsultOnly(equipmentCode, idUser, 1));

      if(equipment.error){
        this._resourcesService.openSnackBar(equipment.msg);
      }else{
        equipment.response.CODIGO = await this._encService.decrypt(equipment.response.CODIGO);
        equipment.response.TIPO_EQUIPAMIENTO = await this._encService.decrypt(equipment.response.TIPO_EQUIPAMIENTO);
        equipment.response.MODELO = await this._encService.decrypt(equipment.response.MODELO);
        equipment.response.ID_EQUIPAMIENTO = await this._encService.decrypt(equipment.response.ID_EQUIPAMIENTO);

        this._dialog.open(EquipmentDocumentsComponent, {
          width: '520px',
          maxWidth: '520px',
          data: {
            equipment: `${equipment.response.CODIGO} - ${equipment.response.TIPO_EQUIPAMIENTO} - ${equipment.response.MODELO} (${equipment.response.ID_EQUIPAMIENTO})`,
            documents: JSON.parse(equipment.response.DOCUMENTOS as string)
          }
        });
      }
    }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);
      }
    }
  }

  toolsChange(toolsValue: string[], partsValue: string[]){
    this.toolsDataSource = new MatTableDataSource();
    this.toolsParts = [];

    let toolsAux: ToolInfo[] = [];
    if(toolsValue != undefined && !toolsValue.includes('SH')){
      toolsValue.forEach(item => {
        let tool = this.tools.filter(item2 => item == item2.ID)[0];
        toolsAux.push(tool);
      });
    }else if(toolsValue.includes('SH')){
      this.formGroup.controls['toolsControl'].setValue(['SH']);
    }

    let partsAux: ToolInfo[] = [];
    if(partsValue != undefined && !partsValue.includes('SH')){
      partsValue.forEach(item => {
        let part = this.spareParts.filter(item2 => item == item2.ID)[0];
        partsAux.push(part);
      });
    }else if(partsValue.includes('SH')){
      this.formGroup.controls['sparePartsControl'].setValue(['SH']);
    }

    toolsAux.forEach(item => this.toolsParts.push(item));
    partsAux.forEach(item => this.toolsParts.push(item));

    this.toolsDataSource = new MatTableDataSource(this.toolsParts);
  }

  changeReq(action: string, id: string){
    let input = this._document.getElementById(`cant-req-${id}`) as HTMLInputElement;
    let val = parseInt(input.value);
    if(action == 'add'){
      val++;
      input.value = `${val}`;
    }else if(val > 1){
      val--;
      input.value = `${val}`;
    }else{
      input.value = '1';
    }
  }

  validateCant(value: string, id: string){
    let input = this._document.getElementById(`cant-req-${id}`) as HTMLInputElement;
    if(value == ""){
      input.value = '1';
    }else if(value == '0'){
      input.value = '1';
    }else{
      let validString = "";
      let valueArr = value.split('');
      let numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];

      valueArr.forEach(char => {
        if(numbers.includes(char)){
          validString += char;
        }
      });

      input.value = validString;
    }
  }

  isPositive(calcDisp: string, id: string): boolean{
    let input = this._document.getElementById(`cant-req-${id}`) as HTMLInputElement;
    let cd = parseInt(calcDisp);
    let cr = parseInt(input.value);
    
    return cd - cr > 0;
  }

  calcRest(calcDisp: string, id: string): string{
    let input = this._document.getElementById(`cant-req-${id}`) as HTMLInputElement;
    let cd = parseInt(calcDisp);
    let cr = parseInt(input.value);
    
    return `${cd - cr}`;
  }

  async registerVisit(){
    try{
      this.isSaving = true;

      let formValue = this.formGroup.getRawValue();
      let selectedTools = formValue.toolsControl;
      let selectedSpareParts = formValue.sparePartsControl;
      let toolsConf: any[] = [];
      let validTools = true;

      selectedTools.forEach((item: string) => {
        if(item == 'SH'){
          toolsConf.push({
            ID: 'SH',
            REQ: '-',
            TYPE: 'T'
          });
        }else{
          let input = this._document.getElementById(`cant-req-${item}`) as HTMLInputElement;
          let tool = this.tools.filter(item2 => item2.ID == item)[0];
          if(input.value == ''){
            this._resourcesService.openSnackBar(`La cantidad requerida no se ha configurado para la herramienta ${tool.NOMB}`);

            validTools = false;
          }else{
            toolsConf.push({
              ID: tool.ID,
              REQ: input.value,
              TYPE: 'T'
            });
          }
        }
      });

      selectedSpareParts.forEach((item: string) => {
        if(item == 'SH'){
          toolsConf.push({
            ID: 'SH',
            REQ: '-',
            TYPE: 'S'
          });
        }else{
          let input = this._document.getElementById(`cant-req-${item}`) as HTMLInputElement;
          let part = this.spareParts.filter(item2 => item2.ID == item)[0];
          if(input.value == ''){
            this._resourcesService.openSnackBar(`La cantidad requerida no se ha configurado para la herramienta ${part.NOMB}`);

            validTools = false;
          }else{
            toolsConf.push({
              ID: part.ID,
              REQ: input.value,
              TYPE: 'S'
            });
          }
        }
      });

      if(validTools){
        let formData = new FormData();
        let idUser = localStorage.getItem('idusuario');
        let staffArr: any[] = [];
        for(const item of formValue.staffControl){
          let itemArr = item.split('-');
          staffArr.push({
            ID: itemArr[0],
            TYPE: itemArr[1]
          });
        }

        formData.append('id_user', idUser!);
        formData.append('linea', '1');
        formData.append('equipment', formValue.equipmentControl);
        formData.append('staff', JSON.stringify(staffArr));
        formData.append('resources', JSON.stringify(toolsConf));
        formData.append('comments', formValue.comments);

        await lastValueFrom(this._prevMaintService.newUnprogrammedOrder(formData));

        this.isSaving = false;
        this._resourcesService.openSnackBar('La visita 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);
      }
      this.isSaving = false;
    }
  }
}
