import { HttpErrorResponse } from '@angular/common/http';
import { Component, Inject, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { lastValueFrom, map, startWith } from 'rxjs';
import * as reserved_words from 'src/app/components/resources/json/reserved_words.json';
import { GETBFOService } from 'src/app/services/getb/getbfo/getbfo.service';
import { GETBGTService } from 'src/app/services/getb/getbgt/getbgt.service';
import { GETBTBService } from 'src/app/services/getb/getbtb/getbtb.service';
import { ResourcesService } from 'src/app/services/resources/resources.service';
import * as data from 'src/assets/icons.json';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-getbfo-select',
  templateUrl: './getbfo-select.component.html',
  styleUrls: ['./getbfo-select.component.css'],
})
export class GETBFOSELECTComponent implements OnInit {
  public formGroup: FormGroup;
  public arrSelect: Array<string>;
  public arrGrupos: Array<string>;
  public arrOption: Array<any>;

  public num_cols: number;
  public arr_columns: Array<string>;

  public arr_relationship: Array<any> = [];
  public arr_column: Array<any> = [];

  public arr_tables_rel: Array<any> = [];
  public arr_columns_rel: Array<any> = [];

  public opc_select_disable: boolean = false;

  public arr_columns_main: any = [];
  public arr_tabla_mm: any = [];
  public isTablaMM: boolean = false;

  public arr_icons: Array<any> = [];

  @ViewChild("nombreGrupo") nombreGrupo: any;
  filteredOptions?: Observable<string[]>;

  constructor(
    private _snackBar: MatSnackBar,
    private _getbtbService: GETBTBService,
    private _getbfoService: GETBFOService,
    private _resourceService: ResourcesService,
    private _getbgtService: GETBGTService,
    public dialogRef: MatDialogRef<GETBFOSELECTComponent>,
    @Inject(MAT_DIALOG_DATA) public data: any
  ) {
    this.getColumnMain(data.table_main);
    this.num_cols = data.num_cols;
    this.arr_columns = data.column;


    this.arr_tables_rel = data.tables_rel;
    this.arr_columns_rel = data.columns;

    this.arrSelect = [];
    this.arrGrupos = [];
    this.arrOption = [];
    this.formGroup = this.createFormGroup();
  }

  ngOnInit(): void {
    let data_icons = data;
    this.arr_icons = data_icons.icons;
    let arr_icons_aux: any = [];

    this.arr_icons.map((element) => {
      if (!arr_icons_aux.includes(element.name)) {
        arr_icons_aux.push(element.name);
      }
    });
    this.arr_icons = arr_icons_aux;

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

  private _filter(value: string): string[] {
    const filterValue = value.toLowerCase();
    return this.arr_icons.filter(option => option.toLowerCase().includes(filterValue));
  }

  private createFormGroup() {
    return new FormGroup({
      tag: new FormControl('select', Validators.required),
      column: new FormControl('', Validators.required),

      table_rel: new FormControl({
        value: '',
        disabled: this.arr_tables_rel.length === 0,
      }),
      column_rel: new FormControl({
        value: '',
        disabled: this.arr_tables_rel.length === 0,
      }),

      label: new FormControl('', Validators.required),
      id: new FormControl('', [Validators.required, this.applyFilterControl]),
      name: new FormControl('', Validators.required),
      value: new FormControl({ value: '', disabled: true }),
      icon: new FormControl(''),
      required: new FormControl(false),
      disabled: new FormControl(false),
      multi_select: new FormControl(false),
      group_select: new FormControl(false),
      data_select: new FormControl([]),
      deleted: new FormControl(true),
      num_col: new FormControl(1, Validators.required),
      num_row: new FormControl(1, Validators.required),
      columnMM: new FormControl(),
      columnMMtoMain: new FormControl(),
    });
  }

  // Obtener columnas
  public async dataColumns() {
    await lastValueFrom(
      this._getbgtService.getColumns({ tables: [this.table_rel?.value.NOMBRE_TABLA] })
    ).then(
      (data: any) => {
        if (!data.error || data.response.length > 0) {
          this.arr_columns_rel = data.response[0].columns;
          this.opc_select_disable = true;
        } else this.opc_select_disable = false;
      },
      (error) => this._resourceService.checkErrors(error)
    );
  }

  public async getDataSelect() {
    let resp = { table: this.table_rel?.value.NOMBRE_TABLA, column: this.column_rel?.value };
    await lastValueFrom(this._getbfoService.getDataSelect(resp)).then(
      (data: any) => {
        if (!data.error) this.data_select?.setValue(data.response);
      },
      (error: HttpErrorResponse) => this._resourceService.checkErrors(error)
    );
  }

  public selectionMultipleSelect() {
    if (!this.multi_select!.value) this.group_select?.setValue(false);
    this.arrGrupos = [];
    this.data_select?.setValue([]);
    this.arrOption = [];
  }

  public removeData() {
    this.arrGrupos = [];
    // this.data_select?.setValue([]);
    this.arrOption = [];
    if (!this.group_select!.value) this.multi_select?.setValue(false);
  }

  public addGroup(nombreGrupo: string) {
    if (!this.arrGrupos.includes(nombreGrupo) && nombreGrupo !== '') {
      this.arrGrupos.push(nombreGrupo);
      this.openSnackBar('Grupo añadido');
      this.nombreGrupo.nativeElement.value = "";
    }
  }

  public addOption(opcion: string, valor: string, grupo: string) {
    if (this.group_select!.value && grupo == undefined)
      this.openSnackBar('Debe seleccionar un grupo');
    else if (opcion == '' || valor == '')
      this.openSnackBar('Los campos opción y valor son obligatorios');
    else if (this.group_select!.value) {
      if (grupo !== undefined) {
        let auxArr: any[] = [];
        this.data_select!.value.forEach(
          (element: any) => (auxArr = element.datos)
        );
        let filter = auxArr.filter((element) => element.valor == valor);
        if (filter.length == 0) {
          let index = this.data_select!.value.findIndex(
            (element: any) => element.grupo == grupo
          );
          if (index !== -1)
            this.data_select!.value[index].datos.push({
              opcion: opcion,
              valor: valor,
            });
          else {
            this.data_select!.value.push({
              grupo: grupo,
              datos: [{ opcion: opcion, valor: valor }],
            });
            this.openSnackBar('Opción añadida');
          }
        } else this.openSnackBar('Los valores no pueden repetirse');
      } else this.openSnackBar('Debe seleccionar un grupo');
    } else {
      let filter = this.data_select!.value.filter(
        (element: any) => element.valor == valor
      );
      if (filter.length == 0) {
        this.data_select!.value.push({
          opcion: opcion,
          valor: valor,
          grupo: grupo,
        });
        this.openSnackBar('Opción añadida');
      } else this.openSnackBar('Los valores no pueden repetirse');
    }
  }

  public numColumn(type: string) {
    if (type == 'add' && this.num_col?.value + 1 <= this.num_cols)
      this.num_col?.setValue(this.num_col?.value + 1);
    else if (this.num_col?.value - 1 >= 1)
      this.num_col?.setValue(this.num_col?.value - 1);
  }

  private applyFilterControl(control: any) {
    const filterValue = control.value;
    let arrWords = reserved_words;
    let filter = arrWords.reserved_words.filter(
      (element: string) => element == filterValue.trim().toUpperCase()
    );
    if (filter.length > 0) {
      this.openSnackBar(`${filterValue} es una palabra reservada`);
      return { validWords: { word: filterValue } };
    }
    return null;
  }

  public onChangeColumn() {
    let valueColumn = this.column?.value;
    let arrTableMM = this.arr_columns_rel.filter((element: any) => element.type == 'De M:M');

    arrTableMM.map((infoTabla: any) => {
      infoTabla.columns.map((column: string) => {
        if (valueColumn === column) {
          this.arr_tabla_mm = infoTabla;
          let arrTemp: any = [];
          this.arr_tabla_mm['columns'].map((columns: any) => {
            arrTemp.push({ column: columns, table: this.arr_tabla_mm['table'] });
          });
          this.arr_tabla_mm = arrTemp;
          this.isTablaMM = true;
        }
      });
    });

    this.name?.setValue(valueColumn);
    this.id?.setValue(valueColumn);
  }

  private async getColumnMain(table_name: string) {
    await lastValueFrom(this._getbgtService.getColumns({ tables: [table_name] })).then(
      (data: any) => {
        if (!data.error) {
          this.arr_columns_main = data.response[0];
          let arrTemp: any = [];
          this.arr_columns_main['columns'].map((columns: any) => {
            arrTemp.push({ column: columns, table: this.arr_columns_main['table'] });
          });
          this.arr_columns_main = arrTemp;

          this.multi_select?.setValue(true);
        }
      },
      (error: HttpErrorResponse) => this._resourceService.checkErrors(error)
    );
  }

  private openSnackBar(
    message: string,
    action: string = 'Cerrar',
    duration: number = 4000
  ) {
    this._snackBar.open(message, action, { duration: duration });
  }

  get tag() {
    return this.formGroup.get('tag');
  }
  get columnMM() {
    return this.formGroup.get('columnMM');
  }
  get columnMMtoMain() {
    return this.formGroup.get('columnMMtoMain');
  }

  get column() {
    return this.formGroup.get('column');
  }

  get table_rel() {
    return this.formGroup.get('table_rel');
  }
  get column_rel() {
    return this.formGroup.get('column_rel');
  }

  get label() {
    return this.formGroup.get('label');
  }
  get id() {
    return this.formGroup.get('id');
  }
  get name() {
    return this.formGroup.get('name');
  }
  get disabled() {
    return this.formGroup.get('disabled');
  }
  get value() {
    return this.formGroup.get('value');
  }
  get required() {
    return this.formGroup.get('required');
  }
  get icon() {
    return this.formGroup.get('icon');
  }
  get multi_select() {
    return this.formGroup.get('multi_select');
  }
  get group_select() {
    return this.formGroup.get('group_select');
  }
  get data_select() {
    return this.formGroup.get('data_select');
  }
  get num_col() {
    return this.formGroup.get('num_col');
  }
}
