import { Component, Inject, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ActivatedRoute } from '@angular/router';
import { lastValueFrom } from 'rxjs';
import { PreventiveWorkOrder, PreventiveWorkOrderResponse } from 'src/app/interfaces/preventive-work-order.interface';
import { EncService } from 'src/app/services/enc/enc.service';
import { PreventiveMaintenanceService } from 'src/app/services/preventive-maintenance.service';
import { OrderDetailsComponent } from '../order-details/order-details.component';
import { DOCUMENT } from '@angular/common';
import { FormControl } from '@angular/forms';

interface ResourcesConfig{
  ID: string,
  NOM: string,
  REQ: number,
  TYPE: string,
  UNIT: string,
  COSTUNIT: number,
  COSTTOTAL: number,
}
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-budget-analysis',
  templateUrl: './budget-analysis.component.html',
  styleUrls: ['./budget-analysis.component.css']
})
export class BudgetAnalysisComponent implements OnInit {
  public btnSmall: boolean = false;

  idOrder: number;
  isLoading: boolean;
  hasError: boolean;
  errorStr: string;
  workOrder: PreventiveWorkOrder | null;
  
  extraComments = new FormControl('');
  tools: ResourcesConfig[];
  spareParts: ResourcesConfig[];
  toolsArr: ToolInfo[];
  sparePartsArr: ToolInfo[];
  staffArr: any[];

  constructor(
    @Inject(DOCUMENT) private _document: Document,
    private _prevMaintService: PreventiveMaintenanceService,
    private _encService: EncService,
    private _router: ActivatedRoute,
    private _snackBar: MatSnackBar,
    private _dialog: MatDialog,
  ) { 
    this.idOrder = 0;
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = "";
    this.workOrder = null;
    this.btnSmall = window.innerWidth <= 1405;
    this.tools = [];
    this.spareParts = [];
    this.toolsArr = TOOLS_TMP;
    this.sparePartsArr = SPARE_PARTS_TMP;
    this.staffArr = []
  }

  ngOnInit(): void {
    this._router.queryParams.subscribe(res => {
      let idOrderEnc = res['data'];
      if(idOrderEnc == undefined || idOrderEnc == null || idOrderEnc == ''){
        this.openSnackBar('No se envió información.');
        this.goBack(1);
      }else{
        this.getWorkOrder(idOrderEnc);
      }
    });
  }

  async getWorkOrder(idOrderEnc: string){
    try{
      let idOrderDec = await this._encService.decrypt(idOrderEnc);
      this.idOrder = parseInt(idOrderDec);
      let idUser = localStorage.getItem('idusuario')!;

      let order: PreventiveWorkOrderResponse = await lastValueFrom(this._prevMaintService.getWorkOrder(
        idOrderEnc,
        idUser,
        1
      ));

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

      if(!this.hasError){
        this.workOrder = order.response;
        this.staffArr = await this.getStaffObj(this.workOrder.OPERARIOS);
        this.tools = this.getResources(this.workOrder.RECURSOS, 'T');
        this.spareParts = this.getResources(this.workOrder.RECURSOS, 'S');
      }
      
      this.isLoading = false;
      this.initAnalysis();
    }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 initAnalysis(){
    if(this.workOrder != null && this.workOrder.ANALISIS != null){
      let analysisArr = JSON.parse(this.workOrder.ANALISIS);
      console.log(analysisArr);
    }
  }

  async getStaffObj(staffStr: string): Promise<Array<any>>{
    let staffArr = JSON.parse(staffStr);
    let employeesFilt = staffArr.filter((item: any) => item.TYPE == 'EM');
    let teamsFilt = staffArr.filter((item: any) => item.TYPE == 'EQ');
    let subcontratistsFilt = staffArr.filter((item: any) => item.TYPE == 'SU');
    let objTmp: any[] = [];
    let employeesDec: number[] = [];

    for(const team of teamsFilt){
      let teamObj = {
        ID: '',
        TYPE: '',
        NAME: '',
        SPEC: '',
        PERS: [] as any[],
      };

      let idDec = await this._encService.decrypt(team.ID);
      if(team.INFO == 'Desconocido'){
        teamObj.ID = team.ID,
        teamObj.TYPE = 'EQUIPO DE TRABAJO';
        teamObj.NAME = `Desconocido (${idDec})`;
        teamObj.SPEC = 'Desconocido';
      }else{
        teamObj.ID = team.ID,
        teamObj.TYPE = 'EQUIPO DE TRABAJO';
        teamObj.NAME = `${team.INFO.NOMBREEQUIPO} (${idDec})`;
        teamObj.SPEC = `${team.INFO.ESPECIALIDAD}`;

        let persArr: any[] = [];
        for(const item of team.INFO.PERSONAL){
          let idUsrDec = await this._encService.decrypt(item.IDUSUARIO);
          let idEmpDec = await this._encService.decrypt(item.IDEMPLEADO);
          employeesDec.push(parseInt(idEmpDec));

          persArr.push({
            ID: item.IDEMPLEADO,
            NAME: `${item.NOMBREEMPLEADO} (${idUsrDec}) (${idEmpDec})`,
            ESPE: `${item.ESPECIALIDAD}`
          });
        }

        teamObj.PERS = persArr;
      }

      objTmp.push(teamObj);
    }

    for(const subcontratist of subcontratistsFilt){
      let subcontratistObj = {
        ID: '',
        TYPE: '',
        NAME: '',
        SPEC: '',
        PERS: [] as any[],
      };

      let idDec = await this._encService.decrypt(subcontratist.ID);
      if(subcontratist.INFO == 'Desconocido'){
        subcontratistObj.ID = subcontratist.ID,
        subcontratistObj.TYPE = 'SUBCONTRATISTA';
        subcontratistObj.NAME = `Desconocido (${idDec})`;
        subcontratistObj.SPEC = 'Desconocido';
      }else{
        subcontratistObj.ID = subcontratist.ID,
        subcontratistObj.TYPE = 'SUBCONTRATISTA';
        subcontratistObj.NAME = `${subcontratist.INFO.RAZONSOCIAL} (${subcontratist.INFO.REGIMENFISCAL}) (${idDec})`;
        subcontratistObj.SPEC = `${subcontratist.INFO.ESPECIALIDAD}`;

        let persArr: any[] = [];
        for(const item of subcontratist.INFO.PERSONAL){
          let idUsrDec = await this._encService.decrypt(item.IDUSUARIO);
          let idEmpDec = await this._encService.decrypt(item.IDEMPLEADO);

          if(!employeesDec.includes(parseInt(idEmpDec))){
            employeesDec.push(parseInt(idEmpDec));
            persArr.push({
              ID: item.IDUSUARIO,
              NAME: `${item.NOMBREEMPLEADO} (${idUsrDec}) (${idEmpDec})`,
              ESPE: `${item.ESPECIALIDAD}`
            });
          }
        }

        subcontratistObj.PERS = persArr;
      }

      objTmp.push(subcontratistObj);
    }

    for(const employee of employeesFilt){
      let idDec = await this._encService.decrypt(employee.ID);
      if(!employeesDec.includes(parseInt(idDec))){
        objTmp.push({
          ID: employee.ID,
          TYPE: 'EMPLEADO',
          NAME: `${employee.INFO.NOMBREEMPLEADO} (${idDec})`,
          SPEC: `${employee.INFO.ESPECIALIDAD}`,
        });
      }
    }
    
    return Promise.resolve(objTmp);
  }

  getResources(resourcesStr: string, type: string): ResourcesConfig[]{
    let resourcesArr = JSON.parse(resourcesStr);
    let resources: ResourcesConfig[] = [];

    for(const item of resourcesArr){
      if(item.TYPE == type && item.ID != "SH"){
        let res = this.toolsArr.filter(item2 => item2.ID == item.ID)[0];
        if(type == 'T'){
          res = this.toolsArr.filter(item2 => item2.ID == item.ID)[0];
        }else{
          res = this.sparePartsArr.filter(item2 => item2.ID == item.ID)[0];
        }

        let resource: ResourcesConfig = {
          ID: item.ID,
          NOM: `${res.NOMB} (${res.MODE})`,
          REQ: parseInt(item.REQ),
          TYPE: item.TYPE,
          UNIT: res.UNIT,
          COSTUNIT: 0,
          COSTTOTAL: 0
        };

        resources.push(resource);
      }
    }
    
    return resources;
  }

  public onResize():void {
    this.btnSmall = window.innerWidth <= 1405;
  }

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

  openSnackBar(msg: string){
    this._snackBar.open(msg, undefined, {
      duration: 3500,
    })
  }

  openOrderDetails(){
    this._dialog.open(OrderDetailsComponent, {
      width: '820px',
      data: {
        idOrder: this.idOrder,
      }
    })
  }

  async asignAnalysis(){
    try{
      let idUser = localStorage.getItem('idusuario');
      let analysisObj: any[] = [];
      let shouldContinue = true;

      for(const item of this.staffArr){
        if(item.TYPE == 'EMPLEADO'){
          let inputCost = this._document.getElementById(`cost-${item.ID}`) as HTMLInputElement;
          let costValue = inputCost.value;

          if(costValue == '' || costValue == null || costValue == undefined){
            this.openSnackBar(`Aún no se ha ingresado el costo por hora del empleado ${item.NAME}.`);
            inputCost.value = '';
            return;
          }

          let inputHours = this._document.getElementById(`hour-${item.ID}`) as HTMLInputElement;
          let hoursValue = inputHours.value;

          if(hoursValue == '' || hoursValue == null || hoursValue == undefined){
            this.openSnackBar(`Aún no se han ingresado las horas de contrato del empleado ${item.NAME}.`);
            inputHours.value = '';
            return;
          }

          analysisObj.push({
            ID: item.ID,
            TYPE: item.TYPE,
            COST: parseFloat(costValue),
            HOURS: parseFloat(hoursValue),
            TOTALCOST: null,
            ITEMS: null,
          });
        }else if(item.PERS.length == 0){
          let inputCost = this._document.getElementById(`cost-${item.ID}`) as HTMLInputElement;
          let costValue = inputCost.value;

          if(costValue == '' || costValue == null || costValue == undefined){
            this.openSnackBar(`Aún no se ha ingresado el costo por hora del ${item.TYPE} ${item.NAME}.`);
            inputCost.value = '';
            return;
          }

          let inputHours = this._document.getElementById(`hour-${item.ID}`) as HTMLInputElement;
          let hoursValue = inputHours.value;

          if(hoursValue == '' || hoursValue == null || hoursValue == undefined){
            this.openSnackBar(`Aún no se han ingresado las horas de contrato del ${item.TYPE} ${item.NAME}.`);
            inputHours.value = '';
            return;
          }

          analysisObj.push({
            ID: item.ID,
            TYPE: item.TYPE,
            COST: parseFloat(costValue),
            HOURS: parseFloat(hoursValue),
            TOTALCOST: null,
            ITEMS: null,
          });
        }else{
          let totalCost = 0.0;
          let users: any[] = [];
          for(const item1 of item.PERS){
            let inputCost = this._document.getElementById(`cost-${item1.ID}`) as HTMLInputElement;
            let costValue = inputCost.value;
  
            if(costValue == '' || costValue == null || costValue == undefined){
              this.openSnackBar(`Aún no se ha ingresado el costo por hora del empleado ${item1.NAME} perteneciente al ${item.TYPE} ${item.NAME}.`);
              inputCost.value = '';
              return;
            }

            let inputHours = this._document.getElementById(`hour-${item1.ID}`) as HTMLInputElement;
            let hoursValue = inputHours.value;

            if(hoursValue == '' || hoursValue == null || hoursValue == undefined){
              this.openSnackBar(`Aún no se han ingresado las horas de contrato del empleado ${item1.NAME} perteneciente al ${item.TYPE} ${item.NAME}.`);
              inputHours.value = '';
              return;
            }

            totalCost += parseFloat(costValue) * parseFloat(hoursValue);

            users.push({
              ID: item1.ID,
              COST: parseFloat(costValue),
              HOURS: parseFloat(hoursValue)
            });
          }

          analysisObj.push({
            ID: item.ID,
            TYPE: item.TYPE,
            COST: null,
            HOURS: null,
            TOTALCOST: totalCost,
            ITEMS: users,
          });
        }
      }

      if(shouldContinue){
        this.tools.every(tool => {
          if(tool.COSTUNIT <= 0){
            this.openSnackBar(`El costo unitario de la herramienta '${tool.NOM}' no es válido.`);
            shouldContinue = false;
            return false;
          }else{
            shouldContinue = true;
            return true;
          }
        });

        if(shouldContinue){
          this.spareParts.every(part => {
            if(part.COSTUNIT <= 0){
              this.openSnackBar(`El costo unitario de la herramienta '${part.NOM}' no es válido.`);
              shouldContinue = false;
              return false;
            }else{
              shouldContinue = true;
              return true;
            }
          });

          if(shouldContinue){
            let finalObj = {
              teamsConf: analysisObj,
              toolsConf: this.tools,
              sparePartsConf: this.spareParts,
              extraComments: this.extraComments.value,
            };
    
            let analysisStr = JSON.stringify(finalObj);
            let idOrder = await this._encService.encrypt(`${this.idOrder}`);
            let formData = new FormData();
    
            formData.append('id_user', idUser!);
            formData.append('linea', '1');
            formData.append('id_order', idOrder!);
            formData.append('analysis', analysisStr);
    
            await lastValueFrom(this._prevMaintService.setBudgetAnalysis(formData));
            this.openSnackBar('El análisis presupuestario se asignó correctamente.');
            this.goBack(1);
          }
        }
      }
    }catch(error: any){
      if(error.error == undefined){
        this.openSnackBar('Ocurrió un error inesperado.');
      }else if(error.error.msg == undefined){
        this.openSnackBar('Ocurrió un error inesperado.');
      }else{
        this.openSnackBar(error.error.msg);
      }
    }
  }

  updateTotalCost(id: string, type: string, unitPrice: string){
    let res: ResourcesConfig;
    if(type == 'T'){
      res = this.tools.filter(item => item.ID == id)[0];
    }else{
      res = this.spareParts.filter(item => item.ID == id)[0];
    }

    let unitPriceNum = parseFloat(unitPrice);
    if(!isNaN(unitPriceNum)){
      let totalPrice = res.REQ * unitPriceNum;
      res.COSTTOTAL = totalPrice;
      res.COSTUNIT = unitPriceNum
    }
  }
}
