import {
  Component,
  Input,
  OnInit,
  ViewEncapsulation,
  AfterViewInit,
  ViewChild,
} from '@angular/core';
import {
  FormControl,
  FormGroup,
  FormGroupDirective,
  Validators,
} from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { MCOMAUService } from 'src/app/services/mco/mcomau/mcomau.service';

import { MESMSVService } from 'src/app/services/mes/mesmsv/mesmsv.service';
import {
  MAT_MOMENT_DATE_FORMATS,
  MomentDateAdapter,
  MAT_MOMENT_DATE_ADAPTER_OPTIONS,
} from '@angular/material-moment-adapter';
import {
  DateAdapter,
  MAT_DATE_FORMATS,
  MAT_DATE_LOCALE,
} from '@angular/material/core';
import {
  MatCalendarCellClassFunction,
  MatCalendarCellCssClasses,
} from '@angular/material/datepicker';

import { AlertaComponent } from '../../resources/dialogos/alerta/alerta.component';
import { USERInterface } from 'src/app/interfaces/user-interface';
import { ENCService } from 'src/app/services/enc/enc.service';
import { MCOMDFService } from 'src/app/services/mco/mcomdf/mcomdf.service';
import { MCOMPVService } from 'src/app/services/mco/mcompv/mcompv.service';
import { Call } from '@angular/compiler';
import { lastValueFrom, map, Observable, startWith } from 'rxjs';
import { ValidationsService } from 'src/app/services/validations.service';
import { HttpErrorResponse } from '@angular/common/http';

@Component({
  selector: 'app-mesmsv',
  templateUrl: './mesmsv.component.html',
  styleUrls: ['./mesmsv.component.css'],
  providers: [
    { provide: MAT_DATE_LOCALE, useValue: 'es-MX ' },
    {
      provide: DateAdapter,
      useClass: MomentDateAdapter,
      deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS],
    },
    { provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS },
  ],
  encapsulation: ViewEncapsulation.None,
})
export class MESMSVComponent implements OnInit {
  dates_disable: any = [];
  days_week_disable: any = [];
  formGroup: FormGroup;
  dias: number = 0;
  envioForm: any = {
    text: 'Enviar',
    status: false,
  };
  loading = false;
  contadorCellDate: number = 0;

  minDate = new Date(
    new Date().getFullYear(),
    new Date().getMonth(),
    new Date().getDate() + 1
  );

  dias_feriados: any[] = null!;
  politica: string = null!;
  usuario_session: USERInterface = JSON.parse(
    localStorage.getItem('TIMUSERENC')!
  );

  public perfil: number = 0;
  public otros_usuarios_arr: Array<any> = [];
  public enable = true;
  public enableAux = true;

  diasFeriados: any[] = [];
  myControl: FormControl = new FormControl();
  filteredOptions!: Observable<any>;

  public disabledFechas: boolean = false;

  @ViewChild(FormGroupDirective) formDirective!: FormGroupDirective;

  constructor(
    private _encService: ENCService,
    public dialog: MatDialog,
    private _mcomdfService: MCOMDFService,
    private _mcompvService: MCOMPVService,
    private _mesmsv: MESMSVService,
    private _validationService: ValidationsService,
    private _mcomauService: MCOMAUService
  ) {
    this.formGroup = this.createFormGroup();
    this.perfil = parseInt(
      this._encService.desencriptar(this.usuario_session.PERFIL.toString())
    );

    this.filteredOptions = this.myControl.valueChanges.pipe(
      startWith(''),
      map((value) => this._filter(value))
    );
  }

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

  private _filter(value: string): string[] {
    const filterValue = value;
    return this.otros_usuarios_arr
      .map((option: any) => {
        return `${option.IDUSUARIO} - ${option.NOMBRE} ${option.APELLIDO_PATERNO}`;
      })
      .filter((option: any) => option.toLowerCase().includes(filterValue));
  }

  public async changeChBx() {
    if (this.otro_usuario?.value && this.otros_usuarios_arr.length === 0) {
      await lastValueFrom(
        this._mcomauService.obtenerMenos(
          this._encService.desencriptar(this.usuario_session.IDUSUARIO)
        )
      ).then(
        (data: any) => {
          if (!data.error) this.otros_usuarios_arr = data.response;
        },
        (error: HttpErrorResponse) => {
          if (!error.ok)
            this._validationService.openSnackBar('Ocurrió un error inesperado');
          if (error.error.msg != undefined)
            this._validationService.openSnackBar(error.error.msg);
          if (error.status == 408)
            this._validationService.openSnackBar('Conexion lenta');
        }
      );
    }
    this.filteredOptions = this.myControl.valueChanges.pipe(
      startWith(''),
      map((value) => this._filter(value))
    );

    this.minDate = this.otro_usuario?.value
      ? new Date()
      : new Date(
          new Date().getFullYear(),
          new Date().getMonth(),
          new Date().getDate() + 1
        );

    if (!this.otro_usuario?.value) {
      this.numero_empleado?.setValue(
        this._encService.desencriptar(this.usuario_session.IDUSUARIO)
      );
      this.disabledFechas = false;
      this.dias_vacacionales?.enable();
    } else this.numero_empleado?.setValue('');

    this.fecha_inicio?.reset();
    this.fecha_fin?.reset();
    this.myControl.reset();
  }

  public async cambioEmpleado() {
    this.enable = true;
    this.enableAux = true;
    this.fecha_inicio?.reset();
    this.fecha_fin?.reset();

    let campo_empleado: string = this.myControl.value;
    let id_empleado: string = '';

    if (campo_empleado !== null) {
      id_empleado = campo_empleado.includes(' - ')? campo_empleado.split(' - ')[0]: campo_empleado;
      let usr_obj: any = this.otros_usuarios_arr.filter(
        (element) => element.IDUSUARIO === id_empleado
      );
      if (usr_obj[0] === undefined) {
        this.disabledFechas = true;
        this.dias_vacacionales?.disable();
      } else {
        this.disabledFechas = false;
        this.dias_vacacionales?.enable();

        
      }
    } else if (!this.otro_usuario?.value) {
      this.disabledFechas = false;
      this.dias_vacacionales?.enable();
    } else {
      this.disabledFechas = true;
      this.dias_vacacionales?.disable();
    }

    

    let idpolitica: any = [];

    if (this.otro_usuario?.value) {
      if(campo_empleado !== null){
        
        id_empleado = campo_empleado.includes(' - ')? campo_empleado.split(' - ')[0]: campo_empleado;
        let usr_obj: any = this.otros_usuarios_arr.filter(
          (element) => element.IDUSUARIO === id_empleado
        );
          

        if (usr_obj[0] === undefined) {
          this.disabledFechas = true;
          this.dias_vacacionales?.disable();
        } else {
          
          this.disabledFechas = false;
          this.dias_vacacionales?.enable();
          await lastValueFrom(this._mcompvService.obtenerPoliticaUsuario(usr_obj[0].POLITICA)
          ).then(
            (data: any) => {
              console.log(data);
              
              if (!data.error) {
                this.politica = data.response.DIASDESCANSO;
                this.getDaysPolitician(JSON.parse(data.response.DIASDESCANSO));
                console.log(this.politica);
                
              }
            },
            (error: HttpErrorResponse) => {
              if (!error.ok)
                this._validationService.openSnackBar('Ocurrió un error inesperado');
              if (error.error.msg != undefined)
                this._validationService.openSnackBar(error.error.msg);
              if (error.status == 408)
                this._validationService.openSnackBar('Conexion lenta');
            }
          );
        }
      }

      


    } else {
      idpolitica = this._encService.desencriptar(this.usuario_session.POLITICA);
      await lastValueFrom(
        this._mcompvService.obtenerPoliticaUsuario(idpolitica)
      ).then(
        (data: any) => {
          if (!data.error) {
            this.politica = data.response.DIASDESCANSO;
            this.getDaysPolitician(JSON.parse(data.response.DIASDESCANSO));
            console.log(this.politica);
          }
        },
        (error: HttpErrorResponse) => {
          if (!error.ok)
            this._validationService.openSnackBar('Ocurrió un error inesperado');
          if (error.error.msg != undefined)
            this._validationService.openSnackBar(error.error.msg);
          if (error.status == 408)
            this._validationService.openSnackBar('Conexion lenta');
        }
      );
    }

   
  }

  public async cambioUsuario() {
    if (!this.otro_usuario?.value) {
      await lastValueFrom(this._mcompvService.obtenerPolitica()).then(
        (response) => {
          this.politica = response.response.DIASDESCANSO;
          let convert = JSON.parse(response.response.DIASDESCANSO);
          this.getDaysPolitician(convert);
        },
        (error: HttpErrorResponse) => {
          if (!error.ok)
            this._validationService.openSnackBar('Ocurrió un error inesperado');
          if (error.error.msg != undefined)
            this._validationService.openSnackBar(error.error.msg);
          if (error.status == 408)
            this._validationService.openSnackBar('Conexion lenta');
        }
      );
    } else if (
      this.myControl.value !== '' &&
      this.myControl.value !== undefined &&
      this.myControl.value !== null
    ) {
      let campo_empleado: string = this.myControl.value;
      let id_empleado = campo_empleado.split(' - ')[0];
      let usr_obj: any = this.otros_usuarios_arr.filter(
        (element) => element.IDUSUARIO === id_empleado
      );

      if (usr_obj[0] !== undefined) {
        this._mcompvService
          .obtenerPoliticaUsuario(usr_obj[0].POLITICA)
          .subscribe(
            (response) => {
              this.politica = response.response.DIASDESCANSO;
              let convert = JSON.parse(response.response.DIASDESCANSO);
              this.getDaysPolitician(convert);
              this.filteredOptions = this.myControl.valueChanges.pipe(
                startWith(''),
                map((value) => this._filter(value))
              );
            },
            (error: HttpErrorResponse) => {
              if (!error.ok)
                this._validationService.openSnackBar(
                  'Ocurrió un error inesperado'
                );
              if (error.error.msg != undefined)
                this._validationService.openSnackBar(error.error.msg);
              if (error.status == 408)
                this._validationService.openSnackBar('Conexion lenta');
            }
          );
      } else
        this._validationService.openSnackBar(
          'Seleccione un empleado antes de solicitar días'
        );
    } else
      this._validationService.openSnackBar(
        'Seleccione un empleado antes de solicitar días'
      );
  }

  dateClass: MatCalendarCellClassFunction<Date> = async (cellDate, view) => {
    if (this.enable) {
      this.getDaysPolitician(JSON.parse(this.politica));
      this.cambioUsuario();
      this.enable = false;
    }

    let dateToString = cellDate?.toString();
    cellDate = new Date(dateToString!);

    if (view === 'month') return this.filterDays(cellDate);

    return '';
  };

  async filterDays(cellDate: any) {
    const collection = document.getElementsByClassName(
      'mat-calendar-body-cell-content'
    ) as HTMLCollectionOf<HTMLElement>;

    let dateToString = cellDate?.toString();
    let lastPosition = this.dates_disable[this.dates_disable.length - 1];
    cellDate = new Date(dateToString!);

    let index = 0;
    for await (let item of this.dates_disable) {
      if (
        cellDate.getDate() == this.dates_disable[index].getDate() &&
        cellDate.getMonth() == this.dates_disable[index].getMonth() &&
        cellDate.getFullYear() == lastPosition.getFullYear()
      ) {
        collection[cellDate.getDate() - 1].style.color = 'white';
        collection[cellDate.getDate() - 1].style.background = 'orange';
        return 'example-custom-date-class';
      }

      if (
        cellDate.getDay() == this.days_week_disable[0] ||
        cellDate.getDay() == this.days_week_disable[1] ||
        cellDate.getDay() == this.days_week_disable[2] ||
        cellDate.getDay() == this.days_week_disable[3] ||
        cellDate.getDay() == this.days_week_disable[4] ||
        cellDate.getDay() == this.days_week_disable[5] ||
        cellDate.getDay() == this.days_week_disable[6]
      ) {
        if (cellDate.getFullYear() == lastPosition.getFullYear()) {
          collection[cellDate.getDate() - 1].style.color = '#0288d1';
          collection[cellDate.getDate() - 1].style.fontWeight = 'bold';
          return 'weekendsDays';
        }
      }

      index++;
    }

    return '';
  }

  private createFormGroup() {
    return new FormGroup({
      numero_empleado: new FormControl({
        value: this._encService.desencriptar(this.usuario_session.IDUSUARIO),
        disabled: true,
      }),
      fecha_inicio: new FormControl(
        { value: '', disabled: false },
        Validators.required
      ),
      fecha_fin: new FormControl(
        { value: '', disabled: false },
        Validators.required
      ),
      otro_usuario: new FormControl(false),
      dias_vacacionales: new FormControl({ value: '', disabled: false }),
    });
  }

  registrar() {
    this.envioForm.text = 'Enviando...';
    this.envioForm.status = true;

    let insertar = {};

    if (this.otro_usuario?.value) {
      let campo_empleado: string = this.myControl.value;
      let id_usuario = campo_empleado.split(' - ')[0];

      insertar = {
        rfc_empresa: this.usuario_session.RFCEMPRESA,
        fecha_inicio: this.formatDate(this.fecha_inicio?.value),
        fecha_final: this.formatDate(this.fecha_fin?.value),
        numero_dias: this.dias_vacacionales?.value,
        tipo_solicitud: 'admin',
        numero_empleado_solicita: id_usuario,
        numero_empleado_crea: this._encService.desencriptar(
          this.usuario_session.IDUSUARIO
        ),
      };
    } else {
      insertar = {
        rfc_empresa: this.usuario_session.RFCEMPRESA,
        fecha_inicio: this.formatDate(this.fecha_inicio?.value),
        fecha_final: this.formatDate(this.fecha_fin?.value),
        numero_dias: this.dias_vacacionales?.value,
        tipo_solicitud: 'normal',
        numero_empleado_solicita: this._encService.desencriptar(
          this.usuario_session.IDUSUARIO
        ),
      };
    }

    this._mesmsv.crear(insertar).subscribe(
      (data) => {
        if (!data.error)
          this._validationService.openSnackBar('¡Solicitud enviada!');
        else this._validationService.openSnackBar(data.msg);

        this.envioForm.text = 'Enviar';
        this.envioForm.status = false;
      },
      (error: HttpErrorResponse) => {
        if (!error.ok)
          this._validationService.openSnackBar('Ocurrió un error inesperado');
        if (error.error.msg != undefined)
          this._validationService.openSnackBar(error.error.msg);
        if (error.status == 408)
          this._validationService.openSnackBar('Conexion lenta');

        this.envioForm.text = 'Enviar';
        this.envioForm.status = false;
      }
    );

    this.formDirective.resetForm();
    this.otro_usuario?.setValue(false);
    this.numero_empleado?.setValue(
      this._encService.desencriptar(this.usuario_session.IDUSUARIO.toString())
    );
  }

  openDialog() {
    let dataAction = {
      titulo: 'Confirmación',
      descripcion: '¿Está seguro de registrar la solicitud?',
    };

    const dialogRef = this.dialog.open(AlertaComponent, { data: dataAction });

    dialogRef.afterClosed().subscribe((result) => {
      if (result) this.registrar();
    });
  }

  calcular_dias() {
    let dias_semana: any = [];
    if (this.politica != null)
      dias_semana = Object.values(JSON.parse(this.politica));

    let cont = 0;
    if (this.fecha_fin?.value != null) {
      if (
        (this.fecha_inicio?.value._d != undefined &&
          this.fecha_fin?.value._d != undefined) ||
        (this.fecha_inicio?.value._d != null &&
          this.fecha_fin?.value._d != null)
      ) {
        let fecha1: Date = this.fecha_inicio?.value._d;
        let fecha2: Date = this.fecha_fin?.value._d;

        this.dias = this.difference(fecha1, fecha2) + 1;

        for (let index = 0; index < this.dias; index++) {
          let dia_semana_recorrida = fecha1.getDay();

          if (dias_semana[0] != 'Si' && dia_semana_recorrida == 0) cont++;
          if (dias_semana[1] != 'Si' && dia_semana_recorrida == 4) cont++;
          if (dias_semana[2] != 'Si' && dia_semana_recorrida == 1) cont++;
          if (dias_semana[3] != 'Si' && dia_semana_recorrida == 2) cont++;
          if (dias_semana[4] != 'Si' && dia_semana_recorrida == 3) cont++;
          if (dias_semana[5] != 'Si' && dia_semana_recorrida == 6) cont++;
          if (dias_semana[6] != 'Si' && dia_semana_recorrida == 5) cont++;

          this.dias_feriados.forEach((element) => {
            if (
              element.DIA == fecha1.getDate() &&
              element.MES - 1 == fecha1.getMonth()
            ) {
              if (dia_semana_recorrida == 6 || dia_semana_recorrida == 0) {
              } else cont--;
            }
          });
          fecha1 = new Date(
            fecha1.getFullYear(),
            fecha1.getMonth(),
            fecha1.getDate() + 1
          );
        }
        this.dias_vacacionales?.setValue(cont);
        return cont;
      }
      return 0;
    }
    return 0;
  }

  applyFilter(e: any) {
    let dias_semana = Object.values(JSON.parse(this.politica));
    let diasVacaciones = parseInt(e.target.value);
    let cont = 0;
    let diasFeriados = 0;
    let fecha1: Date = this.fecha_inicio?.value._d;

    do {
      this.dias_feriados.forEach((element) => {
        if (
          element.DIA == fecha1.getDate() &&
          element.MES - 1 == fecha1.getMonth()
        ) {
          if (dias_semana[0] != 'Si' && fecha1.getDay() == 0) diasFeriados++;
          if (dias_semana[1] != 'Si' && fecha1.getDay() == 4) diasFeriados++;
          if (dias_semana[2] != 'Si' && fecha1.getDay() == 1) diasFeriados++;
          if (dias_semana[3] != 'Si' && fecha1.getDay() == 2) diasFeriados++;
          if (dias_semana[4] != 'Si' && fecha1.getDay() == 3) diasFeriados++;
          if (dias_semana[5] != 'Si' && fecha1.getDay() == 6) diasFeriados++;
          if (dias_semana[6] != 'Si' && fecha1.getDay() == 5) diasFeriados++;
        }
      });

      if (dias_semana[0] == 'Si' && fecha1.getDay() == 0) diasFeriados++;
      if (dias_semana[1] == 'Si' && fecha1.getDay() == 4) diasFeriados++;
      if (dias_semana[2] == 'Si' && fecha1.getDay() == 1) diasFeriados++;
      if (dias_semana[3] == 'Si' && fecha1.getDay() == 2) diasFeriados++;
      if (dias_semana[4] == 'Si' && fecha1.getDay() == 3) diasFeriados++;
      if (dias_semana[5] == 'Si' && fecha1.getDay() == 6) diasFeriados++;
      if (dias_semana[6] == 'Si' && fecha1.getDay() == 5) diasFeriados++;

      if (cont + 1 == diasVacaciones)
        fecha1 = new Date(
          fecha1.getFullYear(),
          fecha1.getMonth(),
          fecha1.getDate() + diasFeriados
        );
      else {
        if (diasFeriados > 0)
          fecha1 = new Date(
            fecha1.getFullYear(),
            fecha1.getMonth(),
            fecha1.getDate() + diasFeriados
          );
        else
          fecha1 = new Date(
            fecha1.getFullYear(),
            fecha1.getMonth(),
            fecha1.getDate() + 1
          );
      }

      if (diasFeriados == 0) cont++;
      diasFeriados = 0;
    } while (cont < diasVacaciones);

    this.fecha_fin?.setValue(fecha1);
  }

  private formatDate(date: Date) {
    var d = new Date(date),
      month = '' + (d.getMonth() + 1),
      day = '' + d.getDate(),
      year = d.getFullYear();

    if (month.length < 2) month = '0' + month;
    if (day.length < 2) day = '0' + day;

    return [year, month, day].join('-');
  }

  private obtenerDiasFeriados() {
    this._mcomdfService.obtener().subscribe(
      (response) => {
        this.dias_feriados = response.response;
        this.dates_disable = response.response.map((object: any) => {
          return new Date(object.ANIO, object.MES - 1, object.DIA);
        });
      },
      (error: HttpErrorResponse) => {
        if (!error.ok)
          this._validationService.openSnackBar('Ocurrió un error inesperado');
        if (error.error.msg != undefined)
          this._validationService.openSnackBar(error.error.msg);
        if (error.status == 408)
          this._validationService.openSnackBar('Conexion lenta');
      }
    );

    if (!this.otro_usuario?.value) {
      this._mcompvService.obtenerPolitica().subscribe(
        (response) => {
          this.politica = response.response.DIASDESCANSO;
          let convert = JSON.parse(response.response.DIASDESCANSO);
          this.getDaysPolitician(convert);
        },
        (error: HttpErrorResponse) => {
          if (!error.ok)
            this._validationService.openSnackBar('Ocurrió un error inesperado');
          if (error.error.msg != undefined)
            this._validationService.openSnackBar(error.error.msg);
          if (error.status == 408)
            this._validationService.openSnackBar('Conexion lenta');
        }
      );
    } else if (
      this.numero_empleado?.value !== '' &&
      this.numero_empleado?.value !== undefined &&
      this.numero_empleado?.value !== null
    ) {
      let campo_empleado: string = this.myControl.value;
      let id_empleado = campo_empleado.split(' - ')[0];

      this._mcompvService.obtenerPoliticaUsuario(id_empleado).subscribe(
        (response) => {
          this.politica = response.response.DIASDESCANSO;
          let convert = JSON.parse(response.response.DIASDESCANSO);
          this.getDaysPolitician(convert);
        },
        (error: HttpErrorResponse) => {
          if (!error.ok)
            this._validationService.openSnackBar('Ocurrió un error inesperado');
          if (error.error.msg != undefined)
            this._validationService.openSnackBar(error.error.msg);
          if (error.status == 408)
            this._validationService.openSnackBar('Conexion lenta');
        }
      );
    } else
      this._validationService.openSnackBar(
        'Seleccione un empleado antes de solicitar días'
      );
  }

  async getDaysPolitician(convert: any) {
    this.days_week_disable = [];
    if (convert.Do == 'Si') this.days_week_disable.push(0);
    if (convert.Lu == 'Si') this.days_week_disable.push(1);
    if (convert.Ma == 'Si') this.days_week_disable.push(2);
    if (convert.Mi == 'Si') this.days_week_disable.push(3);
    if (convert.Ju == 'Si') this.days_week_disable.push(4);
    if (convert.Vi == 'Si') this.days_week_disable.push(5);
    if (convert.Sa == 'Si') this.days_week_disable.push(6);
  }

  get numero_empleado() {
    return this.formGroup.get('numero_empleado');
  }
  get fecha_inicio() {
    return this.formGroup.get('fecha_inicio');
  }
  get fecha_fin() {
    return this.formGroup.get('fecha_fin');
  }
  get dias_vacacionales() {
    return this.formGroup.get('dias_vacacionales');
  }
  get otro_usuario() {
    return this.formGroup.get('otro_usuario');
  }

  private difference(date1: Date, date2: Date) {
    const date1utc = Date.UTC(
      date1.getFullYear(),
      date1.getMonth(),
      date1.getDate()
    );
    const date2utc = Date.UTC(
      date2.getFullYear(),
      date2.getMonth(),
      date2.getDate()
    );
    let day = 1000 * 60 * 60 * 24;
    return (date2utc - date1utc) / day;
  }
}
