import { Component, Inject, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { GetAreaWarehouse, GetLevelAreaWarehouse, GetWarehouse, GetZoneLevelAreaWarehouse, ResponseDataGetAreaWarehouse, ResponseDataGetLevelAreaWarehouse, ResponseDataGetWarehouse, ResponseDataGetZoneLevelAreaWarehouse } from '../../../../interfaces/inventory-management/warehouse-management.interface';
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
import { ExchangeArticles, RequestMoveStock } from '../../../../interfaces/inventory-management/exchange-articles.interface';
import { ResourcesService, ResponseData } from '../../../../services/resources.service';
import { InventoryManagementService } from '../../../../services/inventory-management/inventory-management.service';
import { EncService } from '../../../../services/enc.service';
import { lastValueFrom } from 'rxjs';
import { HttpErrorResponse } from '@angular/common/http';
import { AlertComponent } from '../../../resources/dialogs/alert/alert.component';

@Component({
    selector: 'app-move-article',
    templateUrl: './move-article.component.html',
    styleUrl: './move-article.component.css',
    standalone: false
})
export class MoveArticleComponent implements OnInit {
  public isLoading: boolean;
  public isLoadingForm: boolean;
  public formGroup: FormGroup;

  public arrWarehouse: Array<GetWarehouse>;
  public arrAreas: Array<GetAreaWarehouse>;
  public arrLevel: Array<GetLevelAreaWarehouse>;
  public arrZone: Array<GetZoneLevelAreaWarehouse>;

  public searchingArea: boolean;
  public searchingLevel: boolean;
  public searchingZone: boolean;

  public codeEquipment: string;

  constructor(
    @Inject(MAT_DIALOG_DATA) public exchangeArticles: ExchangeArticles,
    public resourcesService: ResourcesService,
    private _dialogRef: MatDialogRef<boolean>,
    private _inventoryManagementService: InventoryManagementService,
    private _encService: EncService,
    private _dialog: MatDialog,
  ) {
    this.isLoading = false;
    this.isLoadingForm = false;
    this.formGroup = this.createFormGroup();

    this.arrWarehouse = [];
    this.arrAreas = [];
    this.arrLevel = [];
    this.arrZone = [];

    this.searchingArea = false;
    this.searchingLevel = false;
    this.searchingZone = false;

    this.codeEquipment = this.exchangeArticles.CODIGO;
  }

  private createFormGroup() {
    const arrCode = this.exchangeArticles.CODIGO.split('-');
    let secuence: string = arrCode[arrCode.length -1];
    
    return new FormGroup({
      'lineControl': new FormControl('01', Validators.required),
      'warehouseIDControl': new FormControl('', Validators.required),
      'areaIDControl': new FormControl({value: '', disabled: true}, Validators.required),
      'levelIDControl': new FormControl({value: '', disabled: true}, Validators.required),
      'zoneIDControl': new FormControl({value: '', disabled: true}, Validators.required),
      'familyControl': new FormControl(this.exchangeArticles.CODIGO_FAMILIA ),
      'subfamilyControl': new FormControl(this.exchangeArticles.CODIGO_SUBFAMILIA ),
      'equipmentTypeControl': new FormControl(this.exchangeArticles.MODELO),
      'equipmentModelControl': new FormControl(this.exchangeArticles.CODIGO_MODELO),
      'equipmentIDControl': new FormControl(secuence),
      'statusControl': new FormControl('S'),
    });
  }
  
  async ngOnInit() {
    await this.getDataDialog();
  }

  private async getDataDialog() {
    this.isLoading = true;

    let almacen: string = this.exchangeArticles.NOMBRE_ALMACEN;
    if (!almacen.includes('(') || !almacen.includes(')')) {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener el nombre del almacén.`);
      return;
    }
    almacen = almacen.split('(')[1].split(')')[0];

    let area: string = this.exchangeArticles.NOMBRE_AREA;
    if (!area.includes('(') || !area.includes(')')) {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener el nombre del area.`);
      return;
    }
    area = area.split('(')[1].split(')')[0];

    let nivel: string = this.exchangeArticles.NOMBRE_NIVEL;
    if (!nivel.includes('(') || !nivel.includes(')')) {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener el nombre del nivel.`);
      return;
    }
    nivel = nivel.split('(')[1].split(')')[0];

    let zona: string = this.exchangeArticles.NOMBRE_ZONA;
    if (!zona.includes('(') || !zona.includes(')')) {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener el nombre de la zona.`);
      return;
    }
    zona = zona.split('(')[1].split(')')[0];

    await this.getWarehouseActives();

    this.formGroup.controls['warehouseIDControl'].setValue(almacen);
    await this.searchArea();
    this.formGroup.controls['areaIDControl'].setValue(area);
    await this.searchLevel();
    this.formGroup.controls['levelIDControl'].setValue(nivel);
    await this.searchZone();
    this.formGroup.controls['zoneIDControl'].setValue(zona);

    this.codeEquipment = this.exchangeArticles.CODIGO;

    this.isLoading = false;
  }

  private async getWarehouseActives() {
    const user: string = this.resourcesService.getUser();
    const line: number = this.resourcesService.getLineNumber();
    await lastValueFrom(this._inventoryManagementService.getWarehouseActives(user, line)).then(
      async (responseData: ResponseDataGetWarehouse) => {
        if (!responseData.error) {
          for(const item of responseData.response){
            let codeEnc = await this._encService.isEncrypted(item.CODIGO_ALMACEN);
            if(codeEnc){
              item.CODIGO_ALMACEN = await this._encService.decrypt(item.CODIGO_ALMACEN);
            }
          }
          
          this.arrWarehouse = responseData.response;
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.getWarehouseActives();
        }
      }
    );
  }

  public async searchArea() {
    this.searchingArea = true;
    this.isLoadingForm = true;
    const warehouse = this.formGroup.controls['warehouseIDControl'].value;
    const encWarehouse: string = await this._encService.encrypt(warehouse); 
    const user: string = this.resourcesService.getUser();
    const line: number = this.resourcesService.getLineNumber();
    await lastValueFrom(this._inventoryManagementService.getAreaByWarehouse(encWarehouse, user, line)).then(
      async (responseData: ResponseDataGetAreaWarehouse) => {
        if (!responseData.error && responseData.response.length > 0) {
          this.arrAreas = responseData.response;
          this.formGroup.controls['areaIDControl'].enable();
          this.buildPreviewTag();
        } else if (!responseData.error && responseData.response.length === 0) {
          this.resourcesService.openSnackBar(`No existen áreas registradas para este almacén.`);
          this.formGroup.controls['areaIDControl'].disable();
          this.formGroup.controls['areaIDControl'].setValue('');
          this.formGroup.controls['levelIDControl'].disable();
          this.formGroup.controls['levelIDControl'].setValue('');
          this.formGroup.controls['zoneIDControl'].disable();
          this.formGroup.controls['zoneIDControl'].setValue('');
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.searchArea();
        }
      }
    );
    this.searchingArea = false;
    this.isLoadingForm = false;
  }

  public async searchLevel() {
    this.searchingLevel = true;
    this.isLoadingForm = true;
    const warehouse = this.formGroup.controls['warehouseIDControl'].value;
    const encWarehouse: string = await this._encService.encrypt(warehouse); 

    const area = this.formGroup.controls['areaIDControl'].value;
    const encArea: string = await this._encService.encrypt(area); 
    const user: string = this.resourcesService.getUser();
    const line: number = this.resourcesService.getLineNumber();

    await lastValueFrom(this._inventoryManagementService.getLevelByAreaWarehouse(encWarehouse, encArea, user, line)).then(
      async (responseData: ResponseDataGetLevelAreaWarehouse) => {
        if (!responseData.error && responseData.response.length > 0) {
          this.arrLevel = responseData.response;
          this.formGroup.controls['levelIDControl'].enable();
          this.buildPreviewTag();
        } else if (!responseData.error && responseData.response.length === 0) {
          this.resourcesService.openSnackBar(`No existen niveles registrados para esta área.`);
          this.formGroup.controls['levelIDControl'].disable();
          this.formGroup.controls['levelIDControl'].setValue('');
          this.formGroup.controls['zoneIDControl'].disable();
          this.formGroup.controls['zoneIDControl'].setValue('');
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.searchLevel();
        }
      }
    );
    this.searchingLevel = false;
    this.isLoadingForm = false;
  }

  public async searchZone() {
    this.searchingZone = true;
    this.isLoadingForm = true;
    const warehouse = this.formGroup.controls['warehouseIDControl'].value;
    const encWarehouse: string = await this._encService.encrypt(warehouse); 

    const area = this.formGroup.controls['areaIDControl'].value;
    const encArea: string = await this._encService.encrypt(area); 

    const level = this.formGroup.controls['levelIDControl'].value;
    const encLevel: string = await this._encService.encrypt(level);

    const user: string = this.resourcesService.getUser();
    const line: number = this.resourcesService.getLineNumber();
    await lastValueFrom(this._inventoryManagementService.getZoneByLevelAreaWarehouse(encWarehouse, encArea, encLevel, user, line)).then(
      async (responseData: ResponseDataGetZoneLevelAreaWarehouse) => {
        if (!responseData.error && responseData.response.length > 0) {
          this.arrZone = responseData.response;
          this.formGroup.controls['zoneIDControl'].enable();
          this.buildPreviewTag();
        } else if (!responseData.error && responseData.response.length === 0) {
          this.resourcesService.openSnackBar(`No existen zonas registradas para este nivel.`);
          this.formGroup.controls['zoneIDControl'].disable();
          this.formGroup.controls['zoneIDControl'].setValue('');
        } else {
          this.resourcesService.openSnackBar(`${responseData.msg}`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this.resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.searchZone();
        }
      }
    );
    this.searchingZone = false;
    this.isLoadingForm = false;
  }

  private buildPreviewTag() {
    this.codeEquipment = '';

    let siteTag: string = '';
    let siteControls: Array<string> = ['lineControl', 'areaIDControl', 'levelIDControl'];
    for(const key of siteControls){
      let val = this.formGroup.controls[key].value;
      let codePart = 'N/D';

      if(val != null && val != undefined && val != ''){
        codePart = val;
      }

      siteTag += `${codePart}.`;            
    }
    siteTag = siteTag.substring(0, siteTag.length - 1);

    let areaTag: string = '';
    let areaControls: Array<string> = ['warehouseIDControl', 'zoneIDControl'];
    for(const key of areaControls){
      let val = this.formGroup.controls[key].value;
      let codePart = 'N/D';

      if(val != null && val != undefined && val != ''){
        codePart = val;
      }

      areaTag += `${codePart}.`;  
    }
    areaTag = areaTag.substring(0, areaTag.length - 1);

    let technicalSpecificationTag: string = '';
    let technicalSpecificationControls: Array<string> = ['familyControl', 'subfamilyControl', 'statusControl'];
    for(const key of technicalSpecificationControls){
      let val = this.formGroup.controls[key].value;
      let codePart = 'N/D';

      if(val != null && val != undefined && val != ''){
        codePart = val;
      }

      technicalSpecificationTag += `${codePart}.`;  
    }
    technicalSpecificationTag = technicalSpecificationTag.substring(0, technicalSpecificationTag.length - 1);

    let equipmentIdentufierTag: string = '';
    let equipmentIdentufierControls: Array<string> = ['equipmentTypeControl', 'equipmentModelControl', 'equipmentIDControl'];
    for(const key of equipmentIdentufierControls){
      let val = this.formGroup.controls[key].value;
      let codePart = 'N/D';

      if(val != null && val != undefined && val != '' && key !== 'equipmentIDControl'){
        let type = key == 'equipmentModelControl' ? 'model' : 'element';
        codePart = this.processElement(val, type);
      } else if (key === 'equipmentIDControl') {
        codePart = val;
      }
      
      equipmentIdentufierTag += `${codePart}-`;
    }
    equipmentIdentufierTag = equipmentIdentufierTag.substring(0, equipmentIdentufierTag.length - 1);
    
    this.codeEquipment = `${siteTag}-${areaTag}_${technicalSpecificationTag}.${equipmentIdentufierTag}`;
  }

  private processElement(value: string, type: string): string{
    //PASO 1: Conertir la cadena en mayúsculas
    value = value.toUpperCase();

    //PASO 2: Eliminar acentos
    let valueArr0 = value.split('');
    let validVal0 = "";
    valueArr0.forEach(char => {
      switch(char){
        case "Á": validVal0 += 'A'; break;
        case "É": validVal0 += 'E'; break;
        case "Í": validVal0 += 'I'; break;
        case "Ó": validVal0 += 'O'; break;
        case "Ú": validVal0 += 'U'; break;
        default: validVal0 += char; break;
      }
    });

    //PASO 3: Eliminar conectores
    const CONNECTORS = ['DE', 'PARA', 'Y', 'O', 'DEL', 'EL', 'LA', 'LOS', 'POR', 'EN'];
    let valueArr1 = validVal0.split(' ');
    let validVal1: string[] = [];
    valueArr1.forEach(word => {
      if(!CONNECTORS.includes(word) && word != ""){
        validVal1.push(word);
      }
    });

    //PASO 4: Obtener la longitud del arreglo de palabras válidas
    let validLength = validVal1.length;

    //PASO 5: Obtener el código del elemento según la longitud
    let validVal2 = "";
    if(validLength == 1){
      if(validVal1[0].length < 5){
        validVal2 = validVal1[0];
        for(let i = validVal1[0].length; i < 5; i++){
          if(type == 'model'){
            validVal2 = `X${validVal2}`;
          }else{
            validVal2 = `${validVal2}X`;
          }
        }
      }else{
        validVal2 = validVal1[0].substring(0, 5);
      }
    }else if(validLength == 2){
      let word1 = "";
      if(validVal1[0].length < 2){
        if(type == 'model'){
          word1 = `X${validVal1[0]}`;
        }else{
          word1 = `${validVal1[0]}X`;
        }
      }else{
        word1 = validVal1[0].substring(0, 2);
      }

      let word2 = "";
      if(validVal1[1].length < 3){
        word2 = validVal1[1];
        for(let i = validVal1[1].length; i < 3; i++){
          if(type == 'model'){
            word2 = `X${word2}`;
          }else{
            word2 = `${word2}X`;
          }
        }
      }else{
        word2 = validVal1[1].substring(0, 3);
      }

      validVal2 = `${word1}${word2}`;
    }else if(validLength == 3){
      let word1 = "";
      if(validVal1[0].length < 2){
        if(type == 'model'){
          word1 = `X${validVal1[0]}`;
        }else{
          word1 = `${validVal1[0]}X`;
        }
      }else{
        word1 = validVal1[0].substring(0, 2);
      }

      let word2 = validVal1[1].substring(0, 1);
      
      let word3 = "";
      if(validVal1[2].length < 2){
        if(type == 'model'){
          word3 = `X${validVal1[2]}`;
        }else{
          word3 = `${validVal1[2]}X`;
        }
      }else{
        word3 = validVal1[2].substring(0, 2);
      }

      validVal2 = `${word1}${word2}${word3}`;
    }else if(validLength == 4){
      let word1 = "";
      if(validVal1[0].length < 2){
        if(type == 'model'){
          word1 = `X${validVal1[0]}`;
        }else{
          word1 = `${validVal1[0]}X`;
        }
      }else{
        word1 = validVal1[0].substring(0, 2);
      }

      let word2 = validVal1[1].substring(0, 1);
      let word3 = validVal1[2].substring(0, 1);
      let word4 = validVal1[3].substring(0, 1);

      validVal2 = `${word1}${word2}${word3}${word4}`;
    }else if(validLength >= 5){
      let word1 = validVal1[0].substring(0, 1);
      let word2 = validVal1[1].substring(0, 1);
      let word3 = validVal1[2].substring(0, 1);
      let word4 = validVal1[3].substring(0, 1);
      let word5 = validVal1[4].substring(0, 1);

      validVal2 = `${word1}${word2}${word3}${word4}${word5}`;
    }
    
    return validVal2;
  }

  public async setZone() {
    const level = this.formGroup.controls['levelIDControl'].value;
    this.buildPreviewTag();
  }

  public save() {
    this._dialog.open(AlertComponent, {
      disableClose: true,
      data: {
        icon: `warning`,
        title: `Confirmación`,
        description: `¿Está seguro de mover el artículo ${this.codeEquipment} de dirección?`
      }
    }).afterClosed().subscribe((result) => {
      if (result) {
        this.moveToStock();
      }
    });
  }

  private async moveToStock() {
    const objectRequest:RequestMoveStock = await this.createObjectRequest();
    const idStock: string = await this._encService.encrypt(this.exchangeArticles.ID_STOCK);
    await lastValueFrom(this._inventoryManagementService.moveToStock(objectRequest, idStock)).then(
      (responseData: ResponseData) => {
        if (!responseData.error) {
          this.resourcesService.openSnackBar(`¡Stock Intercambiado Exitosamente!`);
          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.moveToStock();
        }
      }
    );
  }

  private async createObjectRequest(): Promise<RequestMoveStock> {

    let warehouse = this.formGroup.controls['warehouseIDControl'].value;
    warehouse = await this._encService.encrypt(warehouse);

    let area = this.formGroup.controls['areaIDControl'].value;
    area = await this._encService.encrypt(area);

    let level = this.formGroup.controls['levelIDControl'].value;
    level = await this._encService.encrypt(level);

    let zone = this.formGroup.controls['zoneIDControl'].value;
    zone = await this._encService.encrypt(zone);

    let family = this.formGroup.controls['familyControl'].value;
    
    let subfamily = this.formGroup.controls['subfamilyControl'].value;

    let line = this.formGroup.controls['lineControl'].value;

    let typeEquipment = this.formGroup.controls['equipmentTypeControl'].value;

    let model = this.formGroup.controls['equipmentModelControl'].value;

    let idEquipment = this.formGroup.controls['equipmentIDControl'].value;

    let status = this.formGroup.controls['statusControl'].value;


    const requestMoveStock: RequestMoveStock = {
      ALMACEN: warehouse,
      AREA: area,
      NIVEL: level,
      ZONA: zone,
      FAMILIA: family,
      SUBFAMILIA: subfamily,
      LINEA: line,
      TIPO: typeEquipment,
      MODELO: model,
      ID_EQUIPMENTO: idEquipment,
      STATUS: status,
      CODIGO_EQUIPAMIENTO: this.codeEquipment,
      ANTERIOR_CODIGO_EQUIPAMIENTO: this.exchangeArticles.CODIGO,
      USUARIO: this.resourcesService.getUser(),
      NUMERO_LINEA: this.resourcesService.getLineNumber(),
    }
    return requestMoveStock;
  }

  public validateRepeatedValues(): boolean {
    let almacen: string = this.exchangeArticles.NOMBRE_ALMACEN;
    if (!almacen.includes('(') || !almacen.includes(')')) {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener el nombre del almacén.`);
      return true;
    }
    almacen = almacen.split('(')[1].split(')')[0];

    let area: string = this.exchangeArticles.NOMBRE_AREA;
    if (!area.includes('(') || !area.includes(')')) {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener el nombre del area.`);
      return true;
    }
    area = area.split('(')[1].split(')')[0];

    let nivel: string = this.exchangeArticles.NOMBRE_NIVEL;
    if (!nivel.includes('(') || !nivel.includes(')')) {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener el nombre del nivel.`);
      return true;
    }
    nivel = nivel.split('(')[1].split(')')[0];

    let zona: string = this.exchangeArticles.NOMBRE_ZONA;
    if (!zona.includes('(') || !zona.includes(')')) {
      this.resourcesService.openSnackBar(`Ocurrió un error al obtener el nombre de la zona.`);
      return true;
    }
    zona = zona.split('(')[1].split(')')[0];

    const almacenForm: string = this.formGroup.controls['warehouseIDControl'].value;
    const areaForm: string = this.formGroup.controls['areaIDControl'].value;
    const nivelForm: string = this.formGroup.controls['levelIDControl'].value;
    const zonaForm: string = this.formGroup.controls['zoneIDControl'].value;


    return almacenForm === almacen && areaForm === area && nivelForm === nivel && zonaForm === zona;
  }
}
