import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatDialog } from '@angular/material/dialog';
import { lastValueFrom } from 'rxjs';

import { AlertData } from 'src/app/interfaces/alert.interface';
import { AlertComponent } from '../../resources/dialogs/alert/alert.component';
import { GETBGTService } from 'src/app/services/forms-management/getbgt/getbgt.service';
import { ResourcesService } from 'src/app/services/resources/resources.service';
import { TableManagementFormComponent } from './table-management-form/table-management-form.component';

import { EncService } from 'src/app/services/enc/enc.service';
import { ResponseData, DataDelete, TablaResponse, DialogModule, DataForm, RequestDataRegister, RequestDataUpdate } from 'src/app/interfaces/getb/getbgt.interface';

@Component({
  selector: 'app-getbgt',
  templateUrl: './table-management.component.html',
  styleUrls: ['./table-management.component.css'],
})
export class TableManagementComponent implements AfterViewInit, OnInit {

  // Variables de la tabla
  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;
  public displayedColumns: Array<string>;
  public dataSource: MatTableDataSource<TablaResponse>;

  // Variables de loadings
  public isLoading: boolean = true;
  public isLoadingForm: boolean = false;
  public txtBuscador: string;

  // ---- SmartPage ----
  public btnSmall: boolean = false;

  constructor(
    public dialog: MatDialog, // Se inicializa los cuadros de diálogos
    private _getbgtService: GETBGTService, // Se inicializa el servicio de las tablas
    public resourceService: ResourcesService, // Se inicializa el servicio de recursos
    private _encService: EncService, // Se inicializa el servicio de Encriptación
  ) {
    // Se inicializan las columnas de ta tabla
    this.displayedColumns = ['CODIGO_TABLA','NOMBRE_TABLA','FECHA_REGISTRA','USUARIO_REGISTRA','ESTADO','ACCIONES'];
    // Se inicializa los datos de las tablas
    this.dataSource = new MatTableDataSource();
    this.txtBuscador = '';
    // Se obtienen las tablas
    this.consultarTablas();
  }

  // Método implementado por angular AfterViewInit
  ngAfterViewInit(): void {
    // Se implementa el páginador
    this.dataSource.paginator = this.paginator;
    // Se implementa el filtro por columnas en la tabla
    this.dataSource.sort = this.sort;
  }

  // Método implementado por angular OnInit
  ngOnInit(): void {
    // Se establecen las dimensiones de la pantalla
    this.onResize();
  }

  // Método para obtener los datos de las tablas
  public async consultarTablas() {
    this.isLoading = true;
    // Servicio para ejecutar la consulta de las tablas
    await lastValueFrom(this._getbgtService.getTables()).then(
      (data: ResponseData) => {
        // Se obtiene la respuesta exitosa
        if (!data.error) {
          // Se implementa la información obtenida a la tabla
          this.dataSource.data = data.response;
        } else {
          // Se muestra el mensaje de error
          this.resourceService.openSnackBar(data.msg);
        }
      }, (error: HttpErrorResponse) => this.resourceService.checkErrors(error) // Se ejecuta el servicio de errores
    );
    this.isLoading = false;
  }

  // Método para ejecutar el formulario
  public openForm(type: string, element: TablaResponse = {} as TablaResponse) {
    // Objeto de datos para el formulario
    let dataDialog: DialogModule = {
      DATA_ELEMENT: element,
      TYPE_ACTION: type
    }
    // Se ejecuta el formulario
    const dialogRef = this.dialog.open(TableManagementFormComponent, {
      width: '500px',
      data: dataDialog
    });

    // Se obtiene la respuesta obtenida por el formulario
    dialogRef.afterClosed().subscribe(result => {
      // Se ejecuta la acción según el tipo seleccionado
      if (result && type === 'REG') {
        this.registerTable(result);
      } else if (result && type === 'MOD') {
        this.updateTable(result);
      }
    });
  }

  // Método para registrar una tabla
  private async registerTable(data_table: DataForm) {
    // Se encripta la información de la tabla
    let enc_table_name: string = '';
    await this._encService.encriptar(data_table.table_name).then((data: string) => enc_table_name = data);

    // Objeto para registrar una tabla
    let obj_table: RequestDataRegister = {
      table_name: enc_table_name,
      user: this.resourceService.getUser(),
    }

    // Servicio para ejecutar el registro de una tabla
    await lastValueFrom(this._getbgtService.registerTable(obj_table)).then(
      (data: ResponseData) => {
        // Se obtiene la respuesta exitosa
        if (!data.error) {
          this.resourceService.openSnackBar('!Registro de tabla existoso!');
          // Recargar tabla
          this.consultarTablas();
        }
      }, (error: HttpErrorResponse) => this.resourceService.checkErrors(error) // Se ejecuta el servicio de errores
    );
  }

  // Método para modificar una tabla
  private async updateTable(data_table: DataForm) {
    // Se encripta la información de la tabla
    let enc_table_name: string = '';
    await this._encService.encriptar(data_table.table_name).then((data: string) => enc_table_name = data);

    // Objeto para registrar una tabla
    let obj_table: RequestDataUpdate = {
      table_code: data_table.table_code,
      table_name: enc_table_name,
      table_type: data_table.table_type,
      user: this.resourceService.getUser(),
      // user: localStorage.getItem('idusuario')!
    }

    // Servicio para ejecutar la modificación de una tabla
    await lastValueFrom(this._getbgtService.updateTable(obj_table)).then(
      (data: ResponseData) => {
        // Se obtiene la respuesta exitosa
        if (!data.error) {
          this.resourceService.openSnackBar('!Modificación de tabla existosa!');
          // Recargar tabla
          this.consultarTablas();
        } else {
          // Se muestra el mensaje de error
          this.resourceService.openSnackBar(data.msg);
        }
      }, (error: HttpErrorResponse) => this.resourceService.checkErrors(error) // Se ejecuta el servicio de errores
    );
  }

  // Método para ejecutar una alerta
  public async alert(type: string, tableData: TablaResponse = {} as TablaResponse) {
    this.isLoadingForm = true;

    // Se asigna la información de la alerta según el tipo de acción
    let info: AlertData = {} as AlertData;
    if (type === 'ELM') {
      info = {
        icon: 'warning',
        title: 'Eliminar Tabla',
        description: '¿Está seguro de eliminar la tabla?',
      };
    }

    // Se ejecuta la alerta
    const dialogRef = this.dialog.open(AlertComponent, {
      data: info,
      disableClose: true,
      width: '350px',
    });

    // Se obtiene la respuesta obtenida por la alerta
    dialogRef.afterClosed().subscribe((result) => {
      // Se ejecuta la acción según el tipo seleccionado
      if (result && type === 'ELM') {
        // Objeto para eliminar una tabla
        let objDataDelete: DataDelete = {
          table_name: tableData.NOMBRE_TABLA,
          state: tableData.ESTADO == 'Activo' ? 'inactive' : 'active',
          user: this.resourceService.getUser(),
          // user: this.resourceService.getUser()
        }
        // Se ejecuta el método para eliminar una tabla
        this.deleteTable(objDataDelete);
      }
      this.isLoadingForm = false;
    });
  }

  // Método para eliminar una tabla
  public async deleteTable(objDataDelete: DataDelete) {
    // Servicio para ejecutar la eliminación de una tabla
    await lastValueFrom(this._getbgtService.updateStateTable(objDataDelete)).then(
      (data: ResponseData) => {
        // Se obtiene la respuesta exitosa
        if (!data.error) {
          this.resourceService.openSnackBar('!Eliminación de tabla existoso!');
          // Recargar tabla
          this.consultarTablas();
        } else {
          // Se muestra el mensaje de error
          this.resourceService.openSnackBar(data.msg);
        }
      }, (error: HttpErrorResponse) => this.resourceService.checkErrors(error) // Se ejecuta el servicio de errores
    );
  }

  // Método de filtrado de datos
  public applyFilter(event: any, type: string):void {
    let filterValue:string;
    if (type == 'INP') {
      filterValue = (event.target as HTMLInputElement).value;
    }else{
      this.txtBuscador = event;
      filterValue = event;
    }
    this.dataSource.filter = filterValue.trim().toLowerCase();
    if (this.dataSource.paginator) {
      this.dataSource.paginator.firstPage();
    }
  }

  // Método para reajustar los botones según sus dimensiones
  public onResize():void {
    this.btnSmall = window.innerWidth <= 1405;
  }


}
