import { SelectionModel } from '@angular/cdk/collections';
import { Component, ElementRef, QueryList, ViewChild, ViewChildren } from '@angular/core';
import { FormGroup, FormBuilder, NgForm, FormsModule } from '@angular/forms';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { NgbModal, NgbDateParserFormatter, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslatePipe } from '@ngx-translate/core';
import { ToastrService } from 'ngx-toastr';
import { debounceTime, distinctUntilChanged, Observable, Subject, switchMap, takeUntil, tap } from 'rxjs';
import Swal from 'sweetalert2';
import { AdminService } from '../../../shared/services/admin/admin.service';
import { LoaderService } from '../../../shared/services/loader.service';
import { TranslationService } from '../../../shared/services/translation.service';
import { Unsub } from '../../../shared/class/unsub.class';
import { CommonModule } from '@angular/common';
import { RouterLink } from '@angular/router';
import { MaterialeModules } from '../../../material.module';
import { AdminPageHeaderComponent } from '../../../shared/common/pageheader/admin-page-header/admin-page-header.component';
import { TranslatePipes } from '../../../shared/pipes/translate/translate.pipe';
import { NgSelectModule } from '@ng-select/ng-select';

@Component({
  selector: 'app-currency',
  standalone: true,
  imports: [CommonModule, AdminPageHeaderComponent, TranslatePipes, MaterialeModules, NgbTooltipModule, FormsModule, NgSelectModule],
  templateUrl: './currency.component.html',
  styleUrl: './currency.component.scss'
})
export class CurrencyComponent extends Unsub {

  private searchTerms = new Subject<string>();
  public addladdSpace: any;
  setting;
  public refreshToken$: any;
  public sendingResponse: { [key: string]: boolean } = {};

  displayedColumns: string[] = [
    'sno',
    'select',
    'code',
    'symbol',
    'exchangerate',
    'createdat',
    'status',
    'actions',
  ];
  dataSource!: MatTableDataSource<any>;
  selection = new SelectionModel<any>(true, []);
  permission: any;
  currencies = null;
  currencyList = [];
  isloader = true;
  form: FormGroup;
  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;

  constructor(
    private adminService: AdminService,
    private toastr: ToastrService,
    private modalService: NgbModal,
    public formatter: NgbDateParserFormatter,
    private translate: TranslatePipe,
    private translationService: TranslationService,
    loaderService: LoaderService,
    public fb: FormBuilder,
  ) {
    /**
* This code calls the constructor of the parent class in a subclass. 
* The super() function is used to initialize the parent class and allows access to its properties and methods. 
* By calling  super(), the subclass can inherit and use the functionality of the parent class.
**/
    super(loaderService);
    this.form = this.fb.group({
      image: null,
    });
    this.translationService.TranslationStatus.subscribe(() => {
      setTimeout(() => {
        this.paginator._intl.itemsPerPageLabel = this.translate.transform('items per page:');
        this.paginator._intl.nextPageLabel = this.translate.transform('next');
        this.paginator._intl.previousPageLabel = this.translate.transform('previous');
        this.paginator._intl.firstPageLabel = this.translate.transform('first page');
        this.paginator._intl.lastPageLabel = this.translate.transform('last page');
        const of = this.translate.transform('of');
        this.paginator._intl.getRangeLabel = (page: number, pageSize: number, length: number) => {
          if (length == 0 || pageSize == 0) return `0 ${of} ${length}`;
          length = Math.max(length, 0);
          const startIndex = page * pageSize;
          const endIndex = startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize;

          return `${startIndex + 1} - ${endIndex} ${of} ${length}`;
        };
      }, 100);
    });
    this.translationService.setTranslationaStatus(true);
  }

  ngOnInit(): void {
    this.currency();
    this.adminService.RefreshRquestAdmin$.pipe(
      takeUntil(this.unSubscribe$)
    ).subscribe({
      next: () => {
        this.currency();
      },
    });
    this.searchTerms.pipe(
      debounceTime(300),
      distinctUntilChanged(),
      switchMap((): any => this.loadData())
    ).subscribe();
  }
  currency() {
    this.isloader = true;
    this.loaderService.showLoader();
    this.adminService
      .currencies(1, 10, this.filterValue)
      .pipe(takeUntil(this.unSubscribe$))
      .subscribe({
        next: (res) => {
          this.permission = res.permissions;
          this.currencies = res.currencies;
          this.currencyList = Object.entries(this.currencies).map(([name, id]) => ({ name, id }));
          this.addladdSpace = res.queryList;
          this.setting = res.setting?.original;
          // Assign the data to the data source for the table to render
          this.isloader = false;
          this.dataSource = new MatTableDataSource(this.addladdSpace.data);

          if (this.dataSource) {
            this.paginator.pageSize = this.addladdSpace.per_page;
            setTimeout(() => {
              this.paginator.pageIndex = this.addladdSpace.current_page - 1;
              this.paginator.length = this.addladdSpace.total;
            });
            this.dataSource.paginator = this.paginator;

            // this.sort.disableClear = true; // Used to disbale the original soting of data if enabled (Only ASC, DES).
            this.dataSource.sort = this.sort;
            // this.dataSource.sortingDataAccessor = (data, sortHeaderId) => {
            //   switch (sortHeaderId) {
            //     case 'user':
            //     case 'ticketdetails':
            //     case 'status':
            //       return this.nestedProperty(data, sortHeaderId);
            //     default:
            //       return this.nestedCaseInsensitive(data, sortHeaderId);
            //   }
            // }
          }
          if (!this.permission?.includes('Currencies Delete')) {
            this.displayedColumns = [
              'sno',
              'code',
              'symbol',
              'exchangerate',
              'createdat',
              'status',
              'actions',
            ];
          }
          this.loaderService.hideLoader();
        },
        error: () => {
          this.isloader = true;
          this.loaderService.hideLoader()
        }
      });

  }

  filterValue = "";
  applyFilter(event: Event) {
    this.filterValue = (event.target as HTMLInputElement).value;
    this.searchTerms.next(this.filterValue);
  }

  /** Whether the number of selected elements matches the total number of rows. */
  isAllSelected() {
    const numSelected = this.selection.selected.length;
    let numRows;
    if (this.dataSource) {
      numRows = this.dataSource.data.length;
    }
    return numSelected === numRows;
  }
  /** Selects all rows if they are not all selected; otherwise clear selection. */
  toggleAllRows() {
    if (this.isAllSelected()) {
      this.selection.clear();
      return;
    }
    this.selection.select(...this.dataSource.data);
  }

  /** The label for the checkbox on the passed row */
  checkboxLabel(row?: any): string {
    if (!row) {
      return `${this.isAllSelected() ? 'deselect' : 'select'} all`;
    }
    return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row?.id + 1
      }`;
  }
  createAddspaceModel(createAddspace) {
    const modalRef = this.modalService.open(createAddspace, {
      size: 'lg',
      backdrop: 'static', keyboard: false
    });
    modalRef.result.then(
      () => {
        this.addspaceObj = {
          id: null,
          status: null,
          position: null,
          decimal: '',
          conversion_factor: "",
          code: null,
        };
        this.updatedCode = "";
      },
      () => {
        this.addspaceObj = {
          id: null,
          status: null,
          position: null,
          decimal: '',
          conversion_factor: "",
          code: null,
        };
        this.updatedCode = "";
      }
    );
  }
  editAddspaceDetails(editAddspace, row) {
    this.addspaceObj = {
      id: row.id,
      status: row.status,
      position: row.position,
      decimal: row.decimal,
      conversion_factor: row.conversion_factor,
      code: row.code,
    };

    this.updatedCode = this.currencies[row.code];

    const modalRef = this.modalService.open(editAddspace, {
      size: 'lg', backdrop: 'static', keyboard: false
    });
    modalRef.result.then(
      () => {
        this.addspaceObj = {
          id: null,
          status: null,
          position: null,
          decimal: '',
          conversion_factor: "",
          code: null,
        };
        this.updatedCode = "";
      },
      () => {
        this.addspaceObj = {
          id: null,
          status: null,
          position: null,
          decimal: '',
          conversion_factor: "",
          code: null,
        };
        this.updatedCode = "";
      }
    );
  }
  addspaceObj: any = {
    id: null,
    status: null,
    position: null,
    decimal: "",
    conversion_factor: "",
    code: null,
  };
  positionArray = [
    {
      id: 'Prefix',
      name: 'Prefix'
    },
    {
      id: 'Sufix',
      name: 'Sufix'
    }
  ];
  updatedCode = '';
  updateCode(event: any) {
    this.updatedCode = event?.id;
  }
  createAddspace(ngForm: NgForm, buttonId) {
    if (ngForm.valid) {
      this.sendingResponse[buttonId] = true;
      const data = ngForm.value;

      this.adminService
        .currencyStore(data)
        .pipe(takeUntil(this.unSubscribe$))
        .subscribe({
          next: (res) => {
            this.sendingResponse[buttonId] = false;
            if (res?.success) {
              this.toastr.success(this.translate.transform(res.success));
              this.modalService.dismissAll();
            }
            else if (res?.errors) {
              const errors = res.errors;
              for (let key in errors) {
                if (errors.hasOwnProperty(key)) {
                  errors[key].forEach((msg: string) => {
                    this.toastr.error(msg);
                  });
                }
              }
            } 
          },
          error: () => {
            this.sendingResponse[buttonId] = false;
          },
        });
    }
  }
  numberFormat = (num, decimals = 0, decimalSeparator = '.', thousandsSeparator = ',') => {
    // Ensure the number is a valid number
    num = parseFloat(num);
    if (isNaN(num)) return '';

    // Convert the number to a string with fixed decimal places
    let parts = num.toFixed(decimals).split('.');

    // Format the integer part with thousands separator
    let integerPart = parts[0];
    let decimalPart = parts[1] || '';

    let formattedIntegerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator);

    // Combine integer and decimal parts
    return decimalPart ? formattedIntegerPart + decimalSeparator + decimalPart : formattedIntegerPart;
  }
  editAddspace(ngForm: NgForm, buttonId) {
    if (ngForm.valid) {
      this.sendingResponse[buttonId] = true;
      const data = ngForm.value;
      this.adminService
        .currencyStore(data)
        .pipe(takeUntil(this.unSubscribe$))
        .subscribe({
          next: (res) => {
            this.sendingResponse[buttonId] = false;
            if (res?.success) {
              this.toastr.success(this.translate.transform(res.success));
              this.modalService.dismissAll();
            }
            else if (res?.errors) {
              const errors = res.errors;
              for (let key in errors) {
                if (errors.hasOwnProperty(key)) {
                  errors[key].forEach((msg: string) => {
                    this.toastr.error(msg);
                  });
                }
              }
            } 
          },
          error: () => {
            this.sendingResponse[buttonId] = false;
          },
        });
    }
  }
  AddspaceStatusChange(event, row, buttonId) {
    const val = event.checked ? '1' : '0';
    this.sendingResponse[buttonId] = true;
    const data = {
      id: row?.id,
      status: val,
    };
    this.adminService
      .currencyStatus(row?.id, data)
      .pipe(takeUntil(this.unSubscribe$))
      .subscribe({
        next: (res) => {
          this.sendingResponse[buttonId] = false;
          if (res?.success) {
            this.toastr.success(this.translate.transform(res.success));
          }
        },
        error: () => {
          this.sendingResponse[buttonId] = false;
        },
      });
  }

  deleteAddspace(row: any, buttonId) {
    const data = {

    };

    Swal.fire({
      icon: 'warning',
      title: this.translate.transform('Are you sure ?'),
      text: this.translate.transform('Your will not be able to recover!'),
      showCancelButton: true,
      confirmButtonColor: '#6259ca',
      cancelButtonColor: '#f11541',
      confirmButtonText: this.translate.transform('Yes, delete it!'),
      cancelButtonText: this.translate.transform('Close'),
      reverseButtons: true,
    }).then((result: any) => {
      if (result.isConfirmed) {
        this.sendingResponse[buttonId] = true;
        this.adminService
          .deletecurrency(data, row?.id)
          .pipe(takeUntil(this.unSubscribe$))
          .subscribe({
            next: (res) => {
              this.sendingResponse[buttonId] = false;
              if (res?.success) {
                this.toastr.success(this.translate.transform(res.success));
              }
            },
            error: () => {
              this.sendingResponse[buttonId] = false;
            },
          });
      }
    });
  }
  massDeleteAddspaces(buttonId) {
    if (!this.selection.selected?.length) {
      this.toastr.error(this.translate.transform('Please select atleast one Currencie'));
      return;
    }
    const id: any = [];
    this.selection.selected.map(function (ele) {
      id.push(ele.id);
    });
    const data = {

      id: id,
    };

    Swal.fire({
      icon: 'warning',
      title: this.translate.transform('Are you sure ?'),
      text: this.translate.transform('Your will not be able to recover!'),
      showCancelButton: true,
      confirmButtonColor: '#6259ca',
      cancelButtonColor: '#f11541',
      confirmButtonText: this.translate.transform('Yes, delete it!'),
      cancelButtonText: this.translate.transform('Close'),
      reverseButtons: true,
    }).then((result: any) => {
      if (result.isConfirmed) {
        this.sendingResponse[buttonId] = true;
        this.adminService.MassDeletecurrency(data)
          .pipe(takeUntil(this.unSubscribe$))
          .subscribe({
            next: (res) => {
              this.sendingResponse[buttonId] = false;
              this.selection.clear();
              if (res.success) {
                this.toastr.success(this.translate.transform(res.success));
              }
            },
            error: () => {
              this.sendingResponse[buttonId] = false;
            },
          });
      }
    });
  }

  loadData(): Observable<any> {
    this.isloader = true;
    return this.adminService.currencies(this.paginator.pageIndex + 1, this.paginator.pageSize, this.filterValue).pipe(
      tap((data: any) => {
        this.isloader = false;
        this.dataSource.data = data.queryList.data;
        setTimeout(() => {
          this.paginator.pageIndex = data.queryList.current_page - 1;
          this.paginator.length = data.queryList.total;
          this.paginator.pageSize = data.queryList.per_page;
        });
      }));
  }

  onPaginateTable() {
    this.selection.clear();
    this.loadData().subscribe();
  }


  @ViewChildren('filterInput') filterInput!: QueryList<ElementRef>;
  dropdownSearch() {
    this.filterInput.changes.subscribe(res => {
      if (this.filterInput?.first) {
        this.filterInput.first.nativeElement.focus()
      }
    })
  }

  // this is needed to allow sorting on nested properties
  nestedProperty = (data: any, sortHeaderId: string): string | number => {
    return sortHeaderId
      ?.split('.')
      .reduce((accumulator, key) => accumulator && accumulator[key], data) as
      | string
      | number;
  };
  // this is needed to have caseInsensitive sorting
  caseInsensitive = (data: any, sortHeaderId: string): string | number => {
    const value = data[sortHeaderId];
    return typeof value === 'string' ? value.toUpperCase() :
      value;
  };
  nestedCaseInsensitive = (data: any, sortHeaderId: string): string | number => {
    const value = sortHeaderId
      ?.split('.')
      .reduce((accumulator, key) => accumulator && accumulator[key], data) as
      | string
      | number;
    return typeof value === 'string' ? value.toUpperCase() : value;
  };


  image(event: any) {
    const file = (event.target as HTMLInputElement)?.files?.[0];
    this.form.patchValue({
      image: file,
    });
  }

  imageremove = () => {
    let data = { ...this.addspaceObj, "addspaceImage": null }
    Swal.fire({
      icon: 'warning',
      title: this.translate.transform('Are you sure ?'),
      text: this.translate.transform('Your will not be able to recover!'),
      showCancelButton: true,
      confirmButtonColor: '#6259ca',
      cancelButtonColor: '#f11541',
      confirmButtonText: this.translate.transform('Yes, delete it!'),
      cancelButtonText: this.translate.transform('Close'),
      reverseButtons: true,
    }).then((result: any) => {
      if (result.isConfirmed) {
        this.adminService
          .MassDeleteaddspace(data)
          .pipe(takeUntil(this.unSubscribe$))
          .subscribe({
            next: (res) => {
              this.selection.clear();
              if (res.success) {
                this.toastr.success(this.translate.transform(res.success));
              }
            },
            error: () => {
            },
          });
      }
    });

  }
}
