import { SelectionModel } from '@angular/cdk/collections';
import { CommonModule } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { RouterLink } from '@angular/router';
import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslatePipe } from '@ngx-translate/core';
import { ToastrService } from 'ngx-toastr';
import { Subject, takeUntil, debounceTime, distinctUntilChanged, switchMap, Observable, tap } from 'rxjs';
import { MaterialeModules } from '../../../material.module';
import { Unsub } from '../../../shared/class/unsub.class';
import { DateAgoPipe } from '../../../shared/pipes/date-ago/date-ago.pipe';
import { TranslatePipes } from '../../../shared/pipes/translate/translate.pipe';
import { AdminService } from '../../../shared/services/admin/admin.service';
import { CustomersService } from '../../../shared/services/customers/customers.service';
import { LoaderService } from '../../../shared/services/loader.service';
import { TranslationService } from '../../../shared/services/translation.service';

@Component({
  selector: 'app-transactions',
  standalone: true,
  imports: [CommonModule, DateAgoPipe, TranslatePipes, MaterialeModules, NgbTooltipModule, RouterLink],
  templateUrl: './transactions.component.html',
  styleUrl: './transactions.component.scss'
})
export class TransactionsComponent extends Unsub implements OnInit {
  dataSource!: MatTableDataSource<any>;
  private searchTerms = new Subject<string>();
  public tickets: any;
  selection = new SelectionModel<any>(true, []);
  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;
  symbol;
  usercurrency;
  setting;
  isloader = true;
  refreshToken$;
  displayedColumns: string[] = [
    'id',
    'invoiceId',
    'price', "paymentMethod",
    'paymentFor',
    'status',
    'actions',
  ];
  timezone: any;
  constructor(
    private customersService: CustomersService,
    private adminService: AdminService,
    private toastr: ToastrService,
    private translate: TranslatePipe,
    private translationService: TranslationService,
    loaderService: LoaderService
  ) {
    /**
    * 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.adminService.RefreshRquestAdmin$.pipe(
      takeUntil(this.unSubscribe$)
    ).subscribe({
      next: () => {
        this.quotationsFn();
      }
    });
    this.quotationsFn();

    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);
  }
  quotationsFn() {
    this.loaderService.showLoader();
    this.isloader = true;
    this.customersService
      .transactions(1, 10, this.filterValue)
      .pipe(takeUntil(this.unSubscribe$))
      .subscribe({
        next:
          (data) => {
            this.tickets = data.queryList;
            this.usercurrency = data.usercurrency;
            this.symbol = data.symbol;
            this.setting = data?.setting?.original;
            this.timezone = data.timezonedata;
            // Assign the data to the data source for the table to render
            this.isloader = false;
            this.dataSource = new MatTableDataSource(this.tickets.data);

            if (this.dataSource) {
              this.paginator.pageSize = this.tickets.per_page;
              setTimeout(() => {
                this.paginator.pageIndex = this.tickets.current_page - 1;
                this.paginator.length = this.tickets.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);
                }
              }
            }
            this.loaderService.hideLoader();
          }, error: () => { this.isloader = true; this.loaderService.hideLoader() }
      }
      );
  }

  ngOnInit(): void {

    this.searchTerms.pipe(
      debounceTime(300),
      distinctUntilChanged(),
      switchMap((): any => this.loadData())
    ).subscribe();
  }
  filterValue = "";
  applyFilter(event: Event) {
    this.filterValue = (event.target as HTMLInputElement).value;
    this.searchTerms.next(this.filterValue);
  }


  loadData(): Observable<any> {
    this.isloader = true;
    return this.customersService
      .transactions(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();
  }
  // 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;
  };

  getCurrencyPerTicket = (price) => {
    let final = '';
    const total = (price * this.usercurrency?.conversion_factor).toFixed(2);
    if (this.usercurrency?.position == 'Prefix') {
      final = this.symbol + '' + total;
    } else {
      final = total + '' + this.symbol;
    }
    return final;
  }
  
  getStatusElement(status: string): string | null {
    switch (status?.toLowerCase()) {
      case 'paid':
      case 'completed':
        return 'bg-success-transparent';
      case 'pending':
        return 'bg-warning-transparent';
      case 'refundpending':
        return 'bg-info-transparent';
      case 'refunded':
        return 'bg-success-transparent';
      case 'refundrejected':
        return 'bg-danger-transparent';
      case 'cancelled':
        return 'bg-danger-transparent';
      default:
        return null;
    }
  }

  getStatusText(status: string): string {
    switch (status?.toLowerCase()) {
      case 'paid':
      case 'completed':
        return 'Completed';
      case 'pending':
        return 'Payment Pending';
      case 'refundpending':
        return 'Refund Pending';
      case 'refunded':
        return 'Refunded';
      case 'refundrejected':
        return 'Refund Rejected';
      case 'cancelled':
        return 'Invoice Cancelled';
      default:
        return '';
    }
  }
  isPaymentRequired(status: string): boolean {
    return status?.toLowerCase() === 'pending';
  }
}