import { CopyOperationComponent } from './copy-operation/copy-operation.component';
import { AlertComponent } from './../../../resources/dialogs/alert/alert.component';
import { FunctionsService } from './../../../../services/functions.service';
import { PreventiveWorkOrder, PreventiveWorkOrderResponse } from './../../../../interfaces/preventive-work-order.interface';
import { MatTableDataSource } from '@angular/material/table';
import { WorkOrdersByDayResponse, WorkOrderDay } from './../../../../interfaces/work-orders-by-day.interface';
import { lastValueFrom } from 'rxjs';
import { PreventiveMaintenanceService } from 'src/app/services/preventive-maintenance.service';
import { MAT_DIALOG_DATA, MatDialogRef, MatDialog } from '@angular/material/dialog';
import { Component, OnInit, Inject } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { EncService } from 'src/app/services/enc/enc.service';

export interface Specialties{
  type: string;
  staff: string[];
  specialty: string;
}
@Component({
  selector: 'app-calendar-events',
  templateUrl: './calendar-events.component.html',
  styleUrls: ['./calendar-events.component.css']
})
export class CalendarEventsComponent implements OnInit {
  isLoading: boolean;
  hasError: boolean;
  actionsEnabled: boolean;
  errorStr: string;
  title: string;

  MONTHS = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
  displayedColumns = ['ID', 'TITULO', 'HORAINICIO', 'TIEMPO', 'EQUIPO', 'CLASIFICACION', 'PRIORIDAD', 'ESTADO', 'ACCIONES'];
  dayNames = ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'];

  workOrders: WorkOrderDay[];
  hourLabels: string[];
  selectedOrder: number;
  gettingWorkOrder: boolean;
  selectedWorkOrder: PreventiveWorkOrder | null;
  selectedDay: Date;

  constructor(
    @Inject(MAT_DIALOG_DATA) private data: any,
    private _snackBar: MatSnackBar,
    private _encService: EncService,
    private _prevMaintService: PreventiveMaintenanceService,
    private _functionsService: FunctionsService,
    private _dialogRef: MatDialogRef<CalendarEventsComponent>,
    private _dialog: MatDialog,
  ) { 
    this.title = '';
    this.isLoading = true;
    this.hasError = false;
    this.actionsEnabled = true;
    this.errorStr = '';

    this.workOrders = [];
    this.hourLabels = [];
    this.selectedOrder = 0;
    this.gettingWorkOrder = false;
    this.selectedWorkOrder = null;
    this.selectedDay = new Date();
  }

  ngOnInit(): void {
    let dateArr = this.data.date.split('-');
    let monthNum = parseInt(dateArr[1]);

    for(let i = 0; i < 24; i++){
      let period = i < 12 ? 'AM' : 'PM';
      let hour = i < 13 ? i : i - 12;

      this.hourLabels.push(`${hour} ${period}`);
    }

    this.title = `${dateArr[0]} de ${this.MONTHS[monthNum]} del ${dateArr[2]}`;
    this.selectedDay = new Date(parseInt(dateArr[2]), monthNum, parseInt(dateArr[0]));
    this.getDayEvents(parseInt(dateArr[0]), monthNum + 1, parseInt(dateArr[2]));
  }

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

  async getDayEvents(day: number, month: number, year: number){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let dayEvents: WorkOrdersByDayResponse = await lastValueFrom(this._prevMaintService.getWorkOrdersByDay(day, month, year, idUser, 1));

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

      if(!this.hasError){
        this.workOrders = dayEvents.response;
      }

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

  getHoraInicio(hora: string): string{
    let horaArr = hora.split(':');
    let horaNum = parseInt(horaArr[0]);
    let period = horaNum < 12 ? 'AM' : 'PM';
    horaNum = horaNum > 12 ? horaNum - 12 : horaNum;

    return `${horaNum}:${horaArr[1]} ${period}`;
  }

  getPriority(priority: string): string{
    if(priority == '1'){
      return 'Alta';
    }else if(priority == '2'){
      return 'Media';
    }else{
      return 'Baja';
    }
  }

  getEvents(label: string): WorkOrderDay[]{
    let labelArr = label.split(' ');
    let hourNum = parseInt(labelArr[0]);

    if(hourNum < 12 && labelArr[1] == 'PM'){
      hourNum += 12;
    }

    let hourStr = hourNum < 10 ? `0${hourNum}` : `${hourNum}`;
    let orders: WorkOrderDay[] = [];

    this.workOrders.forEach(order => {
      let hourArr = order.HORAINICIO.split(':');
      if(hourArr[0] == hourStr){
        orders.push(order);
      }
    });
    
    return orders;
  }

  getStartHour(hour: string): string{
    let hourArr = hour.split(':');
    let hourNum = parseInt(hourArr[0]);
    let period = hourNum < 12 ? 'AM' : 'PM';
    
    hourNum = hourNum > 12 ? hourNum - 12 : hourNum;
    let hourStr = `${hourNum}:${hourArr[1]} ${period}`;
    
    return hourStr;
  }

  updateSelectedEvent(idSelected: number){
    this.selectedOrder = idSelected;
    this.getSelectedOrder();
  }

  getEventSelectedTitle(): string{
    let event = this.workOrders.filter(order => order.IDORDEN == this.selectedOrder)[0];
    return event.TITULO;
  }

  async getSelectedOrder(){
    try{
      this.gettingWorkOrder = true;

      let idUser = localStorage.getItem('idusuario')!;
      let workOrder: PreventiveWorkOrderResponse = await lastValueFrom(this._prevMaintService.getWorkOrder(`${this.selectedOrder}`, idUser, 1));
      /*let execStatus = await lastValueFrom(this._prevMaintService.getExecRegister(
        this.selectedDay.getFullYear(),
        this.selectedDay.getMonth() + 1,
        this.selectedDay.getDate(),
        workOrder.response.IDORDEN,
        idUser,
        1
      ));
      
      this.actionsEnabled = execStatus.response.ESTATUS == 'NA';
      if(execStatus.response.ESTATUS != 'NA'){
        workOrder.response.ESTADO = execStatus.response.ESTATUS;
      }

      this.hasError = workOrder.error;
      if(this.hasError){
        this.openSnackBar(workOrder.msg);
      }else{
        this.selectedWorkOrder = workOrder.response;
      }

      this.gettingWorkOrder = false;*/
    }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);
      }

      this.gettingWorkOrder = false;
    }
  }

  orderDate(date: string): string{
    let dateArr = date.split('-');
    dateArr = dateArr.reverse();
    return `${dateArr[0]} de ${this.MONTHS[parseInt(dateArr[1]) - 1]} del ${dateArr[2]}`;
  }

  getRepeat(repeat: string): string{
    let repObj = JSON.parse(repeat);
    
    switch(repObj.type){
      case "SE":
        let dayNum = this.selectedDay.getDay();
        let dayStr = '';

        switch(dayNum){
          case 0: dayStr = 'domingos'; break;
          case 1: dayStr = 'lunes'; break;
          case 2: dayStr = 'martes'; break;
          case 3: dayStr = 'miércoles'; break;
          case 4: dayStr = 'jueves'; break;
          case 5: dayStr = 'viernes'; break;
          case 6: dayStr = 'sábados'; break;
        }

        return `Semanalmente los ${dayStr}`;
      break;
      case "TD":
        return "Todos los días a partir de la fecha de inicio.";
      break;
      case "PE":
        return this.customRepeat(repObj.config);
      break;
    }
    console.log(repObj);
    return "";
  }

  customRepeat(value: string): string{
    let resObj = JSON.parse(value);
    let repeatEvery = resObj.repeatEvery.split('|');
    let customRepeat = 'Repetir cada ';

    if(repeatEvery[0] != "1"){
      customRepeat += repeatEvery[0];
    }

    switch(repeatEvery[1]){
      case "0": customRepeat += repeatEvery[0] != "1" ? ' días' : ' día'; break;
      case "1": customRepeat += repeatEvery[0] != "1" ? ' semanas' : ' semana'; break;
      case "2": customRepeat += repeatEvery[0] != "1" ? ' meses' : ' mes'; break;
      case "3": customRepeat += repeatEvery[0] != "1" ? ' años' : ' año'; break;
    }

    let days = 0;
    let daysValues = Object.values(resObj.repeatOn);
    let daysStr = '';
    let cont = 0;
    
    daysValues.forEach(val => {
      if(val){
        daysStr += `${this.dayNames[cont]}, `; 
        days++;
      }

      cont++;
    });

    daysStr = daysStr.substring(0, daysStr.length - 2);
    
    if(days > 1){
      customRepeat += ' los días: ';
    }else{
      customRepeat += ' el día: ';
    }

    customRepeat += daysStr;

    let endsAt = resObj.endsAt.split('|');
    if(endsAt[0] == 'O'){
      let dateArr = endsAt[1].split('-').reverse();
      customRepeat += '. Finaliza el ' + dateArr[0] + ' de ' + this.MONTHS[parseInt(dateArr[1])] + ' del ' + dateArr[2] + '.';
    }else if(endsAt[0] == 'A'){
      let after = endsAt[2];
      customRepeat += '. Finaliza después de ' + after + ' repeti';

      if(after == '1'){
        customRepeat += 'ción.';
      }else{
        customRepeat += 'ciones.';
      }
    }

    return customRepeat.replace('  ', ' ');
  }

  getPersonal(personal: string): Specialties[]{
    let personalObj: Specialties[] = JSON.parse(personal);
    return personalObj!;
  }

  getDocumentation(documentation: string | null): string[]{
    if(documentation == null){
      return []
    }else{
      console.log(documentation);
    }
    return [];
  }

  getUser(usrReg: string, usrMod: string | null): string{
    if(usrMod == null){
      return usrReg;
    }else{
      return usrMod;
    }
  }

  getDate(dateReg: string, dateMod: string | null): string{
    if(dateMod == null){
      return this._functionsService.orderDate(dateReg)!;
    }else{
      return this._functionsService.orderDate(dateMod)!;
    }
  }

  executeOrder(){
    let dialogRef = this._dialog.open(AlertComponent, {
      data: {
        title: 'Ejecutar orden',
        icon: 'warning',
        description: '¿Está seguro de ejecutar esta orden ahora?',
        description2: 'Esta acción notificará a los usuarios involucrados a cerca del inicio de la ejecución de la orden de trabajo.'
      },
      width: '320px'
    });

    dialogRef.afterClosed().subscribe(res => {
      if(res == true){
        this._dialogRef.close(`execute|${this.selectedOrder}|${this.selectedDay.getFullYear()}-${this.selectedDay.getMonth() + 1}-${this.selectedDay.getDate()}`);
      }
    });
  }

  cancelOrder(){
    let dialogRef = this._dialog.open(AlertComponent, {
      data: {
        title: 'Cancelar ejecución',
        icon: 'warning',
        description: '¿Está seguro de cancelar la ejecución de la orden para este día?',
        description2: 'Esta acción cancelará la ejecución de la orden de trabajo programada para este día.'
      },
      width: '320px'
    });

    dialogRef.afterClosed().subscribe(res => {
      if(res == true){
        this._dialogRef.close(`cancel|${this.selectedOrder}|${this.selectedDay.getFullYear()}-${this.selectedDay.getMonth() + 1}-${this.selectedDay.getDate()}`);
      }
    });
  }

  deleteOrder(){
    let dialogRef = this._dialog.open(AlertComponent, {
      data: {
        title: 'Eliminar orden de traajo',
        icon: 'warning',
        description: '¿Está seguro de eliminar la orden de trabajo?',
        description2: 'Esta acción eliminará todas las ejecuciones programadas para esta orden de trabajo.'
      },
      width: '320px'
    });

    dialogRef.afterClosed().subscribe(res => {
      if(res == true){
        this._dialogRef.close(`delete|${this.selectedOrder}|${this.selectedDay.getFullYear()}-${this.selectedDay.getMonth() + 1}-${this.selectedDay.getDate()}`);
      }
    });
  }

  editOrder(){
    this._dialogRef.close(`edit|${this.selectedOrder}|${this.selectedDay.getFullYear()}-${this.selectedDay.getMonth() + 1}-${this.selectedDay.getDate()}`);
  }

  openCopyDialog(){
    /*console.log(this.selectedWorkOrder);
    
    let dialogRef = this._dialog.open(CopyOperationComponent, {
      width: '720px',
      data: {
        equipment: this.selectedWorkOrder?.CODIGOEQUIPO,
      }
    });

    dialogRef.afterClosed().subscribe(res => {
      if(res != null && res != undefined && res != ""){
        this.copyWorkOrder(res);
      }
    })*/
  }

  async copyWorkOrder(response: string){
    try{
      let resObj = JSON.parse(response);
      let idUser = localStorage.getItem('idusuario');
      let eqEnc = await this._encService.encrypt(resObj.equipment);
      let formData = new FormData();
      
      formData.append('id_user', idUser!);
      formData.append('linea', '1');
      formData.append('id_order', `${this.selectedWorkOrder?.IDORDEN}`);
      formData.append('equipment', eqEnc);
      formData.append('new_title', resObj.title);
      
      await lastValueFrom(this._prevMaintService.copyWorkOrder(formData));

      this.openSnackBar('La orden de trabajo se copió correctamente.');
      this._dialogRef.close('copy');
    }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);
      }
    }
  }
}
