import { Component, Inject, OnInit, ViewChild } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { CountriesList, CountriesListResponse } from '../../../../interfaces/countries-list.interface';
import { ZipCodesList, ZipCodesListResponse } from '../../../../interfaces/zip-codes-list.interface';
import { StatesList, StatesListResponse } from '../../../../interfaces/states-list.interface';
import { CitiesList, CitiesListResponse } from '../../../../interfaces/cities-list.interface';
import { TownsList, TownsListResponse } from '../../../../interfaces/towns-list.interface';
import { SettingsList, SettingsListResponse } from '../../../../interfaces/settings-list.interface';
import { CoinsList, CoinsListResponse } from '../../../../interfaces/coins-list.interface';
import { TaxRegimeList, TaxRegimeListResponse } from '../../../../interfaces/tax-regime-list.interface';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { DOCUMENT } from '@angular/common';
import { ResourcesService } from '../../../../services/resources.service';
import { SystemAdminService } from '../../../../services/system-admin.service';
import { ActivatedRoute } from '@angular/router';
import { lastValueFrom } from 'rxjs';
import { HttpErrorResponse } from '@angular/common/http';

@Component({
    selector: 'app-catalogue-management',
    templateUrl: './catalogue-management.component.html',
    styleUrl: './catalogue-management.component.css',
    standalone: false
})
export class CatalogueManagementComponent implements OnInit {
  isLoading: boolean;
  hasError: boolean;
  errorStr: string;
  type: string;
  disableSave: boolean;
  isSaving: boolean;

  countriesDataSource: MatTableDataSource<CountriesList>;
  countriesDisplayedColumns = ['ID', 'NAME', 'LADA', 'NOME'];

  zipCodesDataSource: MatTableDataSource<ZipCodesList>;
  zipCodesDisplayedColumns = ['CP', 'ESTADO', 'MUNICIPIO', 'LOCALIDAD'];

  statesDataSource: MatTableDataSource<StatesList>;
  statesDisplayedColumns = ['ID', 'PAIS', 'NOME'];

  citiesDataSource: MatTableDataSource<CitiesList>;
  citiesDisplayedColumns = ['ID', 'ESTADO', 'NOME'];

  townsDataSource: MatTableDataSource<TownsList>;
  townsDisplayedColumns = ['ID', 'ESTADO', 'NOME'];

  settingsDataSource: MatTableDataSource<SettingsList>;
  settingsDisplayedColumns = ['ID', 'CP', 'NOME'];

  coinsDataSource: MatTableDataSource<CoinsList>;
  coinsDisplayedColumns = ['COIN', 'DESCRIPTION'];

  taxRegimeDataSource: MatTableDataSource<TaxRegimeList>;
  taxRegimeDisplayedColumns = ['ID', 'DESC', 'PHISIC', 'MORAL'];

  public btnSmall: boolean;
  public txtBuscador:string;

  @ViewChild(MatPaginator) paginator?: MatPaginator;
  @ViewChild(MatSort) sort?: MatSort;

  constructor(
    @Inject(DOCUMENT) private _document: Document,
    private _resourcesService: ResourcesService,
    private _sysAdminService: SystemAdminService,
    private _router: ActivatedRoute,
  ) {
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = "";
    this.type = "";
    this.disableSave = false;
    this.isSaving = false;

    this.countriesDataSource = new MatTableDataSource();
    this.zipCodesDataSource = new MatTableDataSource();
    this.statesDataSource = new MatTableDataSource();
    this.citiesDataSource = new MatTableDataSource();
    this.townsDataSource = new MatTableDataSource();
    this.settingsDataSource = new MatTableDataSource();
    this.coinsDataSource = new MatTableDataSource();
    this.taxRegimeDataSource = new MatTableDataSource();

    this.btnSmall = false;
    this.txtBuscador = '';
  }

  ngOnInit(): void {
    this.onResize();
    this._router.queryParams.subscribe(res => {
      let type = res['type'];
      if(type == undefined || type == null || type == ''){
        this._resourcesService.openSnackBar('No se recibió información.');
        this.goBack(1);
      }else{
        this.type = type;

        switch(type){
          case "Países": 
            this.initCountriesTable();
          break;
          case "Códigos postales":
            this.intZipCodesTable();
          break;
          case "Estados":
            this.initStatesTable();
          break;
          case "Municipios":
            this.initCitiesTable();
          break;
          case "Localidades":
            this.initTownsTable();
          break;
          case "Colonias":
            this.initSettingsTable();
          break;
          case "Monedas":
            this.initCoinsTable();
          break;
          case "Régimen fiscal":
            this.initTaxRegim();
          break;
          default: 
            this._resourcesService.openSnackBar(`Selector "${type}" no implementado.`);
            this.goBack(1);
          break;
        }
      }
    });
  }

  public onResize():void {
    this.btnSmall = window.innerWidth <= 1405;
  }

  goBack(steps: number){
    window.history.go(steps * -1);
  }

  async initCountriesTable(){
    try{
      this.isLoading = true;
      this.hasError = false;
      this.errorStr = "";
      this.disableSave = true;

      let idUser = localStorage.getItem('idusuario')!;
      let countries: CountriesListResponse = await lastValueFrom(this._sysAdminService.getCountriesList(idUser, 1));

      this.hasError = countries.error;
      this.errorStr = countries.msg;

      if(!this.hasError){
        this.countriesDataSource = new MatTableDataSource(countries.response);
        this.countriesDataSource.paginator = this.paginator!;
        this.countriesDataSource.sort = this.sort!;
      }
      
      this.isLoading = false;
      this.disableSave = false;
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
      this.disableSave = false;
    }
  }

  async intZipCodesTable(){
    try{
      this.isLoading = true;
      this.hasError = false;
      this.errorStr = "";
      this.disableSave = true;

      let idUser = localStorage.getItem('idusuario')!;
      let zipCodes: ZipCodesListResponse = await lastValueFrom(this._sysAdminService.getZipCodes(idUser, 1));
      
      this.hasError = zipCodes.error;
      this.errorStr = zipCodes.msg;

      if(!this.hasError){
        this.zipCodesDataSource = new MatTableDataSource(zipCodes.response);
        this.zipCodesDataSource.paginator = this.paginator!;
        this.zipCodesDataSource.sort = this.sort!;
      }

      this.isLoading = false;
      this.disableSave = false;
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg ;
      }

      this.hasError = true;
      this.isLoading = false;
      this.disableSave = false;
    }
  }

  async initStatesTable(){
    try{
      this.isLoading = true;
      this.hasError = false;
      this.errorStr = "";
      this.disableSave = true;
      
      let idUser = localStorage.getItem('idusuario')!;
      let states: StatesListResponse = await lastValueFrom(this._sysAdminService.getStatesList(idUser, 1));
      
      this.hasError = states.error;
      this.errorStr = states.msg;

      if(!this.hasError){
        this.statesDataSource = new MatTableDataSource(states.response);
        this.statesDataSource.paginator = this.paginator!;
        this.statesDataSource.sort = this.sort!;
      }

      this.isLoading = false;
      this.disableSave = false;
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
      this.disableSave = false;
    }
  }

  async initCitiesTable(){
    try{
      this.isLoading = true;
      this.hasError = false;
      this.errorStr = "";
      this.disableSave = true;
      
      let idUser = localStorage.getItem('idusuario')!;
      let cities: CitiesListResponse = await lastValueFrom(this._sysAdminService.getCitiesList(idUser, 1));
      
      this.hasError = cities.error;
      this.errorStr = cities.msg;

      if(!this.hasError){
        this.citiesDataSource = new MatTableDataSource(cities.response);
        this.citiesDataSource.paginator = this.paginator!;
        this.citiesDataSource.sort = this.sort!;
      }

      this.isLoading = false;
      this.disableSave = false;
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
      this.disableSave = false;
    }
  }

  async initTownsTable(){
    try{
      this.isLoading = true;
      this.hasError = false;
      this.errorStr = "";
      this.disableSave = true;
      
      let idUser = localStorage.getItem('idusuario')!;
      let towns: TownsListResponse = await lastValueFrom(this._sysAdminService.getTownsList(idUser, 1));

      this.hasError = towns.error;
      this.errorStr = towns.msg;

      if(!this.hasError){
        this.townsDataSource = new MatTableDataSource(towns.response);
        this.townsDataSource.paginator = this.paginator!;
        this.townsDataSource.sort = this.sort!;
      }

      this.isLoading = false;
      this.disableSave = false;
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
      this.disableSave = false;
    }
  }

  async initSettingsTable(){
    try{
      this.isLoading = true;
      this.hasError = false;
      this.errorStr = "";
      this.disableSave = true;
      
      let idUser = localStorage.getItem('idusuario')!;
      let settings: SettingsListResponse = await lastValueFrom(this._sysAdminService.getSettingsList(idUser, 1));

      this.hasError = settings.error;
      this.errorStr = settings.msg;

      if(!this.hasError){
        this.settingsDataSource = new MatTableDataSource(settings.response);
        this.settingsDataSource.paginator = this.paginator!;
        this.settingsDataSource.sort = this.sort!;
      }

      this.isLoading = false;
      this.disableSave = false;
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
      this.disableSave = false;
    }
  }

  public async initCoinsTable () {
    this.isLoading = true;
    const USER: string = this._resourcesService.getUser();
    const LINE: number = this._resourcesService.getLineNumber();
    await lastValueFrom(this._sysAdminService.getCoinsList(USER, LINE)).then(
      (responseData: CoinsListResponse) => {
        if (!responseData.error) {
          this.coinsDataSource.data = responseData.response;     
          this.coinsDataSource.paginator = this.paginator!;
          this.coinsDataSource.sort = this.sort!;
        } else {
          this.hasError = true;
          this._resourcesService.openSnackBar(`${ responseData.msg }`);
        }
      }, async (httpErrorResponse: HttpErrorResponse) => {
        let response = this._resourcesService.checkErrors(httpErrorResponse)
        if (response !== null && response.reload) {
          await this.initCoinsTable();
        } else {
          this.hasError = true;
        }
      }
    );
    this.isLoading = false;
  }

  async initTaxRegim(){
    try{
      this.isLoading = true;
      this.hasError = false;
      this.errorStr = "";
      this.disableSave = true;

      let idUser = localStorage.getItem('idusuario')!;
      let taxRegime: TaxRegimeListResponse = await lastValueFrom(this._sysAdminService.getTaxRegimeList(idUser, 1));

      this.hasError = taxRegime.error;
      this.errorStr = taxRegime.msg;

      if(!this.hasError){
        this.taxRegimeDataSource = new MatTableDataSource(taxRegime.response);
        this.taxRegimeDataSource.paginator = this.paginator!;
        this.taxRegimeDataSource.sort = this.sort!;
      }

      this.isLoading = false;
      this.disableSave = false;
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }
    }
  }

  applyFilter(event: any, type: string){
    let filterValue:string;
    if (type == 'INP') {
      filterValue = (event.target as HTMLInputElement).value;
    }else{
      this.txtBuscador = event;
      filterValue = event;
    }

    switch(this.type){
      case "Países": 
        this.countriesDataSource!.filter = filterValue.trim().toLowerCase();
    
        if(this.countriesDataSource?.paginator){
          this.countriesDataSource.paginator.firstPage();
        }
      break;
      case "Códigos postales": 
        this.zipCodesDataSource!.filter = filterValue.trim().toLowerCase();
    
        if(this.zipCodesDataSource?.paginator){
          this.zipCodesDataSource.paginator.firstPage();
        }
      break;
      case "Estados": 
        this.statesDataSource!.filter = filterValue.trim().toLowerCase();
    
        if(this.statesDataSource?.paginator){
          this.statesDataSource.paginator.firstPage();
        }
      break;
      case "Municipios": 
        this.citiesDataSource!.filter = filterValue.trim().toLowerCase();
    
        if(this.citiesDataSource?.paginator){
          this.citiesDataSource.paginator.firstPage();
        }
      break;
      case "Colonias":
        this.settingsDataSource!.filter = filterValue.trim().toLowerCase();
    
        if(this.settingsDataSource?.paginator){
          this.settingsDataSource.paginator.firstPage();
        }
      break;
      case "Régimen fiscal":
        this.taxRegimeDataSource!.filter = filterValue.trim().toLowerCase();
    
        if(this.taxRegimeDataSource?.paginator){
          this.taxRegimeDataSource.paginator.firstPage();
        }
      break;
    }
  }

  async saveConfig(){
    try{
      let idUser = localStorage.getItem('idusuario');
      let data: string;
      this.disableSave = true;
      this.isSaving = true;

      switch(this.type){
        case "Países": 
          let countriesData = this.countriesDataSource.data;
          countriesData.forEach(country => {
            let id = country.COUNTRY_ID;
            let ladaInput = this._document.getElementById(`lada-${id}`) as HTMLInputElement;
            if(ladaInput != null){
              country.LADA = ladaInput.value;
            }

            let isoInput = this._document.getElementById(`iso-${id}`) as HTMLInputElement;
            if(isoInput != null){
              country.NOMECLARUTA_ISO2 = isoInput.value;
            }
          });
          data = JSON.stringify(countriesData);
        break;
        case "Códigos postales":
          let zipCodesData = this.zipCodesDataSource.data;
          data = JSON.stringify(zipCodesData);
        break;
        case "Estados":
          let statesData = this.statesDataSource.data;
          data = JSON.stringify(statesData);
        break;
        case "Municipios":
          let citiesData = this.citiesDataSource.data;
          data = JSON.stringify(citiesData);
        break;
        case "Localidades":
          let townsData = this.townsDataSource.data;
          data = JSON.stringify(townsData);
        break;
        case "Colonias":
          let settingsData = this.settingsDataSource.data;
          data = JSON.stringify(settingsData);
        break;
        case "Monedas": 
          let coinsData = this.coinsDataSource.data;
          data = JSON.stringify(coinsData);
        break;
        case "Régimen fiscal":
          let taxRegimeData = this.taxRegimeDataSource.data;
          data = JSON.stringify(taxRegimeData);
        break;
        default: data = ""; break;
      }
      
      let formData = new FormData();
      formData.append('id_user', idUser!);
      formData.append('linea', '1');
      formData.append('catalogue_type', this.type);
      formData.append('config', data);

      await lastValueFrom(this._sysAdminService.saveCatalogueConfig(formData));
      
      this.disableSave = false;
      this.isSaving = false;
      this._resourcesService.openSnackBar('La información se actualizó correctamente.');
      this.goBack(1);
    }catch(error: any){
      if(error.error == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      }else if(error.error.msg == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      }else{
        this._resourcesService.openSnackBar(error.error.msg);
      }

      this.disableSave = false;
      this.isSaving = false;
    }
  }

  verifyLada(value: string | null | undefined, id: string){
    let ladaInput = this._document.getElementById(`lada-${id}`) as HTMLInputElement;
    let validChars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "-"];
    
    if(value == null || value == undefined || value == ""){
      ladaInput.value = "0";
    }else{
      let valueArr = value.split('');
      let validVal = "";

      valueArr.forEach(char => {
        if(validChars.includes(char)){
          validVal += char;
        }
      });

      if(validVal == ""){
        ladaInput.value = "0";
      }else if(validVal.length <= 8){
        ladaInput.value = validVal;
      }else{
        let lada = validVal.substring(0, 8);
        ladaInput.value = lada;
      }
    }
  }

  verifyISO(value: string | null | undefined, id: string){
    let isoInput = this._document.getElementById(`iso-${id}`) as HTMLInputElement;
    let validChars = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "Ñ", "O", "P", "Q", "R", "S", 
    "T", "U", "V", "W", "X", "Y", "Z"];

    if(value == null || value == undefined || value == ""){
      isoInput.value = "0";
    }else{
      let valueUpper = value.toUpperCase();
      let valueArr = valueUpper.split('');
      let validVal = "";

      valueArr.forEach(char => {
        if(validChars.includes(char)){
          validVal += char;
        }
      });

      if(validVal == ""){
        isoInput.value = "0";
      }else if(validVal.length <= 2){
        isoInput.value = validVal;
      }else{
        let lada = validVal.substring(0, 2);
        isoInput.value = lada;
      }
    }
  }

  init(){
    switch(this.type){
      case "Países": 
        this.initCountriesTable();
      break;
      case "Códigos postales":
        this.intZipCodesTable();
      break;
      case "Estados":
        this.initStatesTable();
      break;
      case "Municipios":
        this.initCitiesTable();
      break;
      case "Localidades":
        this.initTownsTable();
      break;
      case "Colonias":
        this.initSettingsTable();
      break;
      case "Monedas":
        this.initCoinsTable();
      break;
      case "Régimen fiscal":
        this.initTaxRegim();
      break;
    }
  }
}
