import { Component, Inject, OnInit } from '@angular/core';
import { ComponentInformationCheckbox, ComponentInformationInput, ComponentInformationRadio, ComponentInformationSelect, ComponentInformationTextarea, DataDynamicForm, DataFormComponents, InformationDynamicForm, RequestDataForm, RequestDynamicForm, ResponseDataGetFormById } from '../../../interfaces/forms-management/form-management.interface';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
import { ResourcesService } from '../../../services/resources.service';
import { DynamicFormService } from '../../../services/forms-management/dynamic-form.service';
import { EncService } from '../../../services/enc.service';
import { lastValueFrom } from 'rxjs';
import { HttpErrorResponse } from '@angular/common/http';
import { ResponseData } from '../../../interfaces/response-data';
import { AlertComponent } from '../../resources/dialogs/alert/alert.component';

@Component({
    selector: 'app-generate-dynamic-form',
    templateUrl: './generate-dynamic-form.component.html',
    styleUrl: './generate-dynamic-form.component.css',
    standalone: false
})
export class GenerateDynamicFormComponent implements OnInit {
  public title: string;
  public arrComponents: DataFormComponents[];
  public isLoading: boolean;

  public idForm!: string;
  public formGroup: FormGroup;
  public typeForm!: 'R' | 'M';

  constructor(
    @Inject(MAT_DIALOG_DATA) public dataDynamicForm: DataDynamicForm,
    public resourcesService: ResourcesService,
    private _dynamicFormService: DynamicFormService,
    private _encService: EncService,
    private _dialog: MatDialog,
    private _dialogRef: MatDialogRef<boolean>,
  ) {
    this.title = '...';
    this.arrComponents = [];
    this.isLoading = false;
    this.formGroup = new FormGroup({});
  }
  
  async ngOnInit() {
    this.isLoading = true;
    await this._getDataInformation();
    this._setFormGroup();
    this.isLoading = false;
  }
  
  private async _getDataInformation() {
    const TYPE_DIALOG: 'GENERATE' | 'EXAMPLE' = this.dataDynamicForm.TYPE_DIALOG;
    this.typeForm = this.dataDynamicForm.TYPE_FORM;
    
    if (TYPE_DIALOG === 'EXAMPLE' && this.dataDynamicForm.INFO_FORM !== undefined) {
      let INFO_FORM: InformationDynamicForm = this.dataDynamicForm.INFO_FORM;
      this.title = INFO_FORM.TITLE;
      this.arrComponents = INFO_FORM.COMPONENTS;
    } else if (TYPE_DIALOG === 'GENERATE' && this.dataDynamicForm.ID_FORM !== undefined) {
      this.idForm = this.dataDynamicForm.ID_FORM;

      if (this.typeForm === 'R') {
        await this._getFormById();

      } else if (this.typeForm === 'M') {
        await this._getFormDataById();

      }      
    } else {
      this.resourcesService.openSnackBar(`Opción no disponible.`);
      this._dialogRef.close(false);
    }
  }

  private async _getFormDataById() {
    const ENC_FORM: string = await this._encService.encrypt(this.idForm);
    const USER: string = this.resourcesService.getUser();
    const LINE: number = this.resourcesService.getLineNumber();

    const REQUEST_DATA_FORM: RequestDataForm = {
      VALUES: this.dataDynamicForm.DEFAULT_VALUE
    }

    await lastValueFrom(this._dynamicFormService.getFormDataById( REQUEST_DATA_FORM, ENC_FORM, USER, LINE, )).then(
      async (responseData: ResponseData) => {
        if (!responseData.error) {
          this.arrComponents = responseData.response.DATOS_FORMULARIO.COMPONENTS;
          
          if (this.typeForm === 'R') {
            this.title = responseData.response.TITULO_REGISTRO;
          } else {
            this.title = responseData.response.TITULO_MODIFICACION;
          }
            
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this._getFormDataById();
        }
        this._dialogRef.close(false);
      }
    )
  }

  private async _getFormById() {

    const ENC_FORM: string = await this._encService.encrypt(this.idForm);
    const USER: string = this.resourcesService.getUser();
    const LINE: number = this.resourcesService.getLineNumber();

    await lastValueFrom(this._dynamicFormService.getFormById(ENC_FORM, USER, LINE)).then(
      async (responseData: ResponseDataGetFormById) => {
        if (!responseData.error) {

          for (const DEFAULT_VALUE of this.dataDynamicForm.DEFAULT_VALUE) {
            for (let index = 0; index < responseData.response.DATOS_FORMULARIO.COMPONENTS.length; index++) {
              let COMPONENT: DataFormComponents = responseData.response.DATOS_FORMULARIO.COMPONENTS[index];
              if ( DEFAULT_VALUE.TYPE === COMPONENT.TYPE_COMPONENT && DEFAULT_VALUE.COLUMN === COMPONENT.COMPONENT.COLUMNA) {
                let COMPONENT_DATA = COMPONENT.COMPONENT;
              
                if (DEFAULT_VALUE.TYPE === 'INPUT') {
                  COMPONENT_DATA = COMPONENT_DATA as ComponentInformationInput;
                  COMPONENT_DATA.VALOR_DEFECTO = DEFAULT_VALUE.VALUE;
                } else if (DEFAULT_VALUE.TYPE === 'SELECT') {
                  COMPONENT_DATA = COMPONENT_DATA as ComponentInformationSelect;
                  COMPONENT_DATA.VALOR_DEFECTO = DEFAULT_VALUE.VALUE;
                } else if (DEFAULT_VALUE.TYPE === 'TEXTAREA') {
                  COMPONENT_DATA = COMPONENT_DATA as ComponentInformationTextarea;
                  COMPONENT_DATA.VALOR_DEFECTO = DEFAULT_VALUE.VALUE;
                } 
                COMPONENT.COMPONENT = COMPONENT_DATA;
              }
              responseData.response.DATOS_FORMULARIO.COMPONENTS[index].COMPONENT = COMPONENT.COMPONENT
            }
          }

          
          this.arrComponents = responseData.response.DATOS_FORMULARIO.COMPONENTS;

          if (this.typeForm === 'R') {
            this.title = responseData.response.TITULO_REGISTRO;
          } else {
            this.title = responseData.response.TITULO_MODIFICACION;
          }
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this._getFormById();
        }
        this._dialogRef.close(false);
      }
    );
  }

  private _setFormGroup() {
    
    for (const DATA_COMPONENT of this.arrComponents) {      
      if (DATA_COMPONENT.TYPE_COMPONENT === 'INPUT') {
        const COMPONENT: ComponentInformationInput =  DATA_COMPONENT.COMPONENT as ComponentInformationInput;
        const VALIDATORS = this._setValidatorsInput(COMPONENT);
        this.formGroup.addControl(COMPONENT.COLUMNA, new FormControl(COMPONENT.VALOR_DEFECTO, VALIDATORS));
      }
      if (DATA_COMPONENT.TYPE_COMPONENT === 'SELECT') {
        const COMPONENT: ComponentInformationSelect =  DATA_COMPONENT.COMPONENT as ComponentInformationSelect;
        const VALIDATORS = this._setValidatorSelect(COMPONENT);
        this.formGroup.addControl(COMPONENT.COLUMNA, new FormControl(COMPONENT.VALOR_DEFECTO, VALIDATORS));
      }
      if (DATA_COMPONENT.TYPE_COMPONENT === 'CHECKBOX') {
        const COMPONENT: ComponentInformationCheckbox =  DATA_COMPONENT.COMPONENT as ComponentInformationCheckbox;
        const VALIDATORS = this._setValidatorCheckbox(COMPONENT);
        this.formGroup.addControl(COMPONENT.COLUMNA, new FormControl(COMPONENT.VALOR_DEFECTO, VALIDATORS));
      }
      if (DATA_COMPONENT.TYPE_COMPONENT === 'RADIO') {
        const COMPONENT: ComponentInformationRadio =  DATA_COMPONENT.COMPONENT as ComponentInformationRadio;
        const VALIDATORS = this._setValidatorRadio(COMPONENT);
        this.formGroup.addControl(COMPONENT.COLUMNA, new FormControl(null, VALIDATORS));
      }
      if (DATA_COMPONENT.TYPE_COMPONENT === 'TEXTAREA') {
        const COMPONENT: ComponentInformationTextarea =  DATA_COMPONENT.COMPONENT as ComponentInformationTextarea;
        const VALIDATORS = this._setValidatorTextarea(COMPONENT);
        this.formGroup.addControl(COMPONENT.COLUMNA, new FormControl(COMPONENT.VALOR_DEFECTO, VALIDATORS));
      }
    }
  }

  private _setValidatorsInput(componentInput: ComponentInformationInput) {
    let arrValidatos: any[] = [];

    if (componentInput.LONGITUD_CAMPO_MAXIMO !== null && componentInput.TIPO_CAMPO === 'text') {
      arrValidatos.push(Validators.maxLength(componentInput.LONGITUD_CAMPO_MAXIMO));
    }
    if (componentInput.LONGITUD_CAMPO_MINIMO !== null && componentInput.TIPO_CAMPO === 'text') {
      arrValidatos.push(Validators.minLength(componentInput.LONGITUD_CAMPO_MINIMO));
    }
    
    if (componentInput.LONGITUD_CAMPO_MAXIMO !== null && componentInput.TIPO_CAMPO === 'number') {
      arrValidatos.push(Validators.max(componentInput.LONGITUD_CAMPO_MAXIMO));
    }
    if (componentInput.LONGITUD_CAMPO_MINIMO !== null && componentInput.TIPO_CAMPO === 'number') {
      arrValidatos.push(Validators.min(componentInput.LONGITUD_CAMPO_MINIMO));
    }
    
    if (componentInput.PATRON_VALIDACION !== null) {
      arrValidatos.push(Validators.pattern(componentInput.PATRON_VALIDACION));
    }

    if (this.typeForm === 'R') {

      if (componentInput.REQUERIDO !== null) {
        componentInput.REQUERIDO.map((element: string) => {
          if (element === 'PARA_REGISTRO') {
            arrValidatos.push(Validators.required);
          }
        });
      }

    } else if (this.typeForm === 'M') {
      if (componentInput.REQUERIDO !== null) {
        componentInput.REQUERIDO.map((element: string) => {
          if (element === 'PARA_MODIFICACION') {
            arrValidatos.push(Validators.required);
          }
        });
      }
    } else {
      this.resourcesService.openSnackBar(`Opción no disponible`);
    }


    return arrValidatos;
  }
  
  private _setValidatorSelect(componentSelect: ComponentInformationSelect) {
    let arrValidatos: any[] = [];

    if (this.typeForm === 'R') {

      if (componentSelect.REQUERIDO !== null) {
        componentSelect.REQUERIDO.map((element: string) => {
          if (element === 'PARA_REGISTRO') {
            arrValidatos.push(Validators.required);
          }
        });
      }

    } else if (this.typeForm === 'M') {

      if (componentSelect.REQUERIDO !== null) {
        componentSelect.REQUERIDO.map((element: string) => {
          if (element === 'PARA_MODIFICACION') {
            arrValidatos.push(Validators.required);
          }
        });
      }

    } else {
      this.resourcesService.openSnackBar(`Opción no disponible`);
    }

    return arrValidatos;
  }
  
  private _setValidatorCheckbox(componentCheckbox: ComponentInformationCheckbox) {
    let arrValidatos: any[] = [];
    return arrValidatos;

  }
  
  private _setValidatorRadio(componentRadio: ComponentInformationRadio) {
    let arrValidatos: any[] = [];

    if (this.typeForm === 'R') {
      
      if (componentRadio.REQUERIDO !== null) {
        componentRadio.REQUERIDO.map((element: string) => {
          if (element === 'PARA_REGISTRO') {
            arrValidatos.push(Validators.required);
          }
        });
      }
    } else if (this.typeForm === 'M') {
      

      if (componentRadio.REQUERIDO !== null) {
        componentRadio.REQUERIDO.map((element: string) => {
          if (element === 'PARA_MODIFICACION') {
            arrValidatos.push(Validators.required);
          }
        });
      }
    } else {
      this.resourcesService.openSnackBar(`Opción no disponible`);
    }

    return arrValidatos;
  }
  
  private _setValidatorTextarea(componentTextarea: ComponentInformationTextarea) {
    let arrValidatos: any[] = [];

    if (componentTextarea.LONGITUD_CAMPO_MAXIMO !== null) {
      arrValidatos.push(Validators.maxLength(componentTextarea.LONGITUD_CAMPO_MAXIMO));
    }
    if (componentTextarea.LONGITUD_CAMPO_MINIMO !== null) {
      arrValidatos.push(Validators.minLength(componentTextarea.LONGITUD_CAMPO_MINIMO));
    }
    
    if (componentTextarea.LONGITUD_CAMPO_MAXIMO !== null) {
      arrValidatos.push(Validators.max(componentTextarea.LONGITUD_CAMPO_MAXIMO));
    }
    if (componentTextarea.LONGITUD_CAMPO_MINIMO !== null) {
      arrValidatos.push(Validators.min(componentTextarea.LONGITUD_CAMPO_MINIMO));
    }
    
    if (componentTextarea.PATRON_VALIDACION !== null) {
      arrValidatos.push(Validators.pattern(componentTextarea.PATRON_VALIDACION));
    }

    if (this.typeForm === 'R') {

      if (componentTextarea.REQUERIDO !== null) {
        componentTextarea.REQUERIDO.map((element: string) => {
          if (element === 'PARA_REGISTRO') {
            arrValidatos.push(Validators.required);
          }
        });
      }

    } else if (this.typeForm === 'M') {
      

      if (componentTextarea.REQUERIDO !== null) {
        componentTextarea.REQUERIDO.map((element: string) => {
          if (element === 'PARA_MODIFICACION') {
            arrValidatos.push(Validators.required);
          }
        });
      }

    } else {
      this.resourcesService.openSnackBar(`Opción no disponible`);
    }

    return arrValidatos;
  }

  public checkComponentSize(numColumn: number): string {
    const CLASS_COLUMN: string = `col-flex-${numColumn}`;
    return CLASS_COLUMN;
  }

  public async save() {
    this._dialog.open(AlertComponent, {
      data: {
        title: `Confirmación`,
        description: `¿Está seguro de guardar los datos del formulario?`,
        icon: `warning`
      }
    }).afterClosed().subscribe(async (response) => {
      if (response) {
        if (this.typeForm === 'R') {
          await this._registerDynamicForm();
        } else if (this.typeForm === 'M') {
          await this._updateDynamicForm();
        } else {
          this.resourcesService.openSnackBar(`Opción no disponible`);
        }
      }
    });
  }

  private async _registerDynamicForm() {
    const REQUEST_DATA: RequestDynamicForm = {
      IDFORM: await this._encService.encrypt(this.idForm),
      DATAFORM: this.formGroup.value,
      USUARIO: this.resourcesService.getUser(),
      NUMERO_LINEA: this.resourcesService.getLineNumber(),
    }

    await lastValueFrom(this._dynamicFormService.registerDynamicForm(REQUEST_DATA)).then(
      (responseData: ResponseData) => {
        if (!responseData.error) {
          this.resourcesService.openSnackBar(`¡Registro exitoso!`);
          this._dialogRef.close(true);
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this._registerDynamicForm();
        }
      }
    );
  }

  private async _updateDynamicForm() {
    const REQUEST_DATA: RequestDynamicForm = {
      IDFORM: await this._encService.encrypt(this.idForm),
      DATAFORM: this.formGroup.value,
      USUARIO: this.resourcesService.getUser(),
      NUMERO_LINEA: this.resourcesService.getLineNumber(),
      WHERE: this.dataDynamicForm.DEFAULT_VALUE
    }
    await lastValueFrom(this._dynamicFormService.updateDynamicForm(REQUEST_DATA)).then(
      (responseData: ResponseData) => {
        if (!responseData.error) {
          this.resourcesService.openSnackBar(`¡Modificación exitosa!`);
          this._dialogRef.close(true);
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this._updateDynamicForm();
        }
      }
    );
  }

  public checkComponentInput(componentInput: ComponentInformationInput | ComponentInformationSelect | ComponentInformationTextarea | ComponentInformationCheckbox | ComponentInformationRadio) {
    return componentInput as ComponentInformationInput;
  }

  public setControlForm(formControl: FormControl, component: ComponentInformationInput | ComponentInformationSelect | ComponentInformationTextarea | ComponentInformationCheckbox | ComponentInformationRadio) {    
    this.formGroup.removeControl(component.COLUMNA);
    this.formGroup.addControl(component.COLUMNA, formControl);
  }
  
  public checkComponentSelect(componentSelect: ComponentInformationInput | ComponentInformationSelect | ComponentInformationTextarea | ComponentInformationCheckbox | ComponentInformationRadio) {
    return componentSelect as ComponentInformationSelect;
  }

  public checkComponentCheckbox(componentCheckbox: ComponentInformationInput | ComponentInformationSelect | ComponentInformationTextarea | ComponentInformationCheckbox | ComponentInformationRadio) {
    return componentCheckbox as ComponentInformationCheckbox;
  }
  
  public checkComponentRadio(componentRadio: ComponentInformationInput | ComponentInformationSelect | ComponentInformationTextarea | ComponentInformationCheckbox | ComponentInformationRadio) {
    return componentRadio as ComponentInformationRadio;
  }
  
  public checkComponentTextarea(componentTextarea: ComponentInformationInput | ComponentInformationSelect | ComponentInformationTextarea | ComponentInformationCheckbox | ComponentInformationRadio) {
    return componentTextarea as ComponentInformationTextarea;
  }
}
