import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { availableFiles, docClassification, modules } from '../../../../environments/environment.prod';
import { TempFileInfo } from '../../../interfaces/temp-file-info.interface';
import { PriorityInterface } from '../../system-admin/system-params/system-params.component';
import { FormControl, Validators } from '@angular/forms';
import { EncService } from '../../../services/enc.service';
import { GdelService } from '../../../services/gdel.service';
import { PreventiveMaintenanceService } from '../../../services/preventive-maintenance.service';
import { SystemAdminService } from '../../../services/system-admin.service';
import { MatDialogRef } from '@angular/material/dialog';
import { lastValueFrom } from 'rxjs';
import { PreventiveWorkOrdersActiveResponse } from '../../../interfaces/preventive-work-orders-active.interface';
import { ResourcesService } from '../../../services/resources.service';

interface WorkOrdersAssociated{
  IDORDEN: string;
  NUMORDEN: string;
  TIPOACTIVADOR: string;
  PRIORIDAD: string;
}
@Component({
    selector: 'app-upload-dialog',
    templateUrl: './upload-dialog.component.html',
    styleUrl: './upload-dialog.component.css',
    standalone: false
})
export class UploadDialogComponent implements OnInit {
  clasificationsArr = docClassification;
  modulesArr = modules;
  
  isUploading: boolean;
  hasOrder: boolean;
  isLoading: boolean;
  hasError: boolean;
  errorStr: string;
  uploadedFile: TempFileInfo | null;
  workOrders: WorkOrdersAssociated[];
  priorities: PriorityInterface[];

  @ViewChild('file') private uploader?: ElementRef;

  moduleControl = new FormControl('', Validators.required);
  clasificationControl = new FormControl('', Validators.required);
  orderControl = new FormControl({value: '', disabled: true}, Validators.required);

  constructor(
    private _encService: EncService,
    private _gdelService: GdelService,
    private _prevMaintService: PreventiveMaintenanceService,
    private _sysAdminService: SystemAdminService,
    private _dialogRef: MatDialogRef<UploadDialogComponent>,
    private _resourcesService: ResourcesService,
  ) {
    this.isUploading = false;
    this.uploadedFile = null;
    this.hasOrder = false;
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = '';
    this.workOrders = [];
    this.priorities = [];
  }

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

  async getPriorities(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let priorities = await lastValueFrom(this._sysAdminService.getOrderPriorities(idUser, 1));

      if(priorities.error){
        this.hasError = true;
        this.errorStr = priorities.msg;
        this.isLoading = false;
      }else{
        this.priorities = priorities.response.order_priorities;
        this.getWorOrders();
      }
    }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 = 'Ocurrió un error inesperado.';
      }

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

  async getWorOrders(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let orders: PreventiveWorkOrdersActiveResponse = await lastValueFrom(this._prevMaintService.getActiveWorkOrders(idUser, 1));

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

      if(!this.hasError){
        for(const order of orders.response){
          let idOrderEnc = await this._encService.encrypt(`${order.IDORDEN}`);
          let priority = this.priorities.filter(item => item.value == order.PRIORIDAD)[0];
          
          let orderAssociated: WorkOrdersAssociated = {
            IDORDEN: idOrderEnc,
            NUMORDEN: order.IDORDEN,
            TIPOACTIVADOR: order.TIPOACTIVADOR,
            PRIORIDAD: priority.label,
          };

          this.workOrders.push(orderAssociated);
        }
      }

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

  moduleChanged(module: string){
    if(module != 'GMPR' && module != 'GMCO'){
      this.hasOrder = false;
      this.orderControl.disable();
    }
  }

  checkFile(event: any){
    let fileTypes = availableFiles;
    let sizes = Object.keys(fileTypes);
    let extensions = Object.values(fileTypes);
    let maxSizeMB = 0;

    let extArr = event.target.files[0].name.split(".").reverse();
    let extStr = extArr[0];

    let i = 0;
    extensions.forEach(ext => {
      let size = parseInt(sizes[i]);

      if(ext.includes(extStr)) maxSizeMB = size;
      i++;
    });

    if(maxSizeMB == 0){
      this._resourcesService.openSnackBar(`Los archivos ${extStr} no están soportados`);
    }else{
      let maxFileSize = 1048576 * maxSizeMB;
      let fileSize = event.target.files[0].size;

      if(fileSize > maxFileSize){
        this._resourcesService.openSnackBar(`El tamaño del archivo supera el límite de ${maxSizeMB} MB`);
      }else{
        this.isUploading = true;
        this.uploadTmp(event.target.files[0]);
      }
    }
  }

  async uploadTmp(fileData: any){
    try{
      let idUser = localStorage.getItem('idusuario');
      let formData = new FormData();

      formData.append('file', fileData);
      formData.append('id_user', idUser!);
      formData.append('linea', "1");

      let response = await lastValueFrom(this._gdelService.uploadTempFile(formData));

      if(response.error){
        this._resourcesService.openSnackBar(response.msg);
      }else{
        this.uploadedFile = {
          id: response.response.idArchivo,
          name: fileData.name,
          size: this.formatBytes(fileData.size)
        };
      }

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

  formatBytes(bytes: number, decimals = 2) {
    if (bytes === 0) return '0 Bytes';

    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

    const i = Math.floor(Math.log(bytes) / Math.log(k));

    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
  }

  openFileUploader(){
    this.uploader?.nativeElement.click();
  }

  async deleteTempFile(){
    try{
      let idUser = localStorage.getItem('idusuario');
      let formData = new FormData();

      formData.append('id_user', idUser!);
      formData.append('id_file', this.uploadedFile!.id);
      formData.append('linea', '1');

      await lastValueFrom(this._gdelService.deleteTempFile(formData));

      this.uploadedFile = null;
    }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);
      }
    }
  }

  checkIfOrdersNeeded(event: any){
    if(event.checked){
      this.orderControl.enable();
    }else{
      this.orderControl.disable();
    }
  }

  async saveFinalFile(){
    try{
      let idUser = localStorage.getItem('idusuario');
      let formData = new FormData();

      formData.append('id_user', idUser!);
      formData.append('id_file', this.uploadedFile!.id);
      formData.append('linea', '1');
      formData.append('module', this.moduleControl.value!);
      formData.append('clasification', this.clasificationControl.value!);
      formData.append('has_order', this.hasOrder ? 'S' : 'N');
      if(this.hasOrder){
        formData.append('id_order', this.orderControl.value!);
      }

      await lastValueFrom(this._gdelService.saveFinalFile(formData));
      this._dialogRef.close(true);
    }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);
      }
    }
  }
}
