import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

export interface PaginationState {
  page: number;
  size: number;
  totalRecords: number;
  totalFiltered: number;
  totalPages: number;
  hasNextPage: boolean;
  hasPreviousPage: boolean;
  filters: any;
  search: string;
}

@Injectable({
  providedIn: 'root'
})
export class PaginationService {
  private currentPage = 1;
  private pageSize = 100;
  private totalRecords = 0;
  private totalFiltered = 0;
  private totalPages = 0;
  private hasNextPage = false;
  private hasPreviousPage = false;
  private filters: any = {};
  private searchTerm = '';
  
  private paginationState$ = new BehaviorSubject<PaginationState>({
    page: this.currentPage,
    size: this.pageSize,
    totalRecords: this.totalRecords,
    totalFiltered: this.totalFiltered,
    totalPages: this.totalPages,
    hasNextPage: this.hasNextPage,
    hasPreviousPage: this.hasPreviousPage,
    filters: this.filters,
    search: this.searchTerm
  });

  constructor() { }

  setPage(page: number): void {
    if (page >= 1 && page <= this.totalPages) {
      this.currentPage = page;
      this.updatePaginationFlags();
      this.emitState();
    }
  }

  setPageSize(size: number): void {
    this.pageSize = Math.min(Math.max(size, 10), 100);
    this.currentPage = 1;
    this.updatePaginationFlags();
    this.emitState();
  }

  setFilters(filters: any): void {
    this.filters = { ...filters };
    this.currentPage = 1;
    this.emitState();
  }

  setSearch(term: string): void {
    this.searchTerm = term || '';
    this.currentPage = 1;
    this.emitState();
  }

  updatePaginationInfo(paginationResponse: any): void {
    if (paginationResponse) {
      this.currentPage = paginationResponse.currentPage || 1;
      this.pageSize = paginationResponse.pageSize || 100;
      this.totalRecords = paginationResponse.totalRecords || 0;
      this.totalFiltered = paginationResponse.totalFiltered || 0;
      this.totalPages = paginationResponse.totalPages || 0;
      this.hasNextPage = paginationResponse.hasNextPage || false;
      this.hasPreviousPage = paginationResponse.hasPreviousPage || false;
      
      this.emitState();
    }
  }

  nextPage(): void {
    if (this.hasNextPage) {
      this.setPage(this.currentPage + 1);
    }
  }

  previousPage(): void {
    if (this.hasPreviousPage) {
      this.setPage(this.currentPage - 1);
    }
  }

  firstPage(): void {
    this.setPage(1);
  }

  lastPage(): void {
    this.setPage(this.totalPages);
  }

  getState(): Observable<PaginationState> {
    return this.paginationState$.asObservable();
  }

  getCurrentState(): PaginationState {
    return this.paginationState$.value;
  }

  getApiParams(): any {
    return {
      page: this.currentPage,
      size: this.pageSize,
      filters: this.filters,
      search: this.searchTerm
    };
  }

  reset(): void {
    this.currentPage = 1;
    this.pageSize = 100;
    this.totalRecords = 0;
    this.totalFiltered = 0;
    this.totalPages = 0;
    this.hasNextPage = false;
    this.hasPreviousPage = false;
    this.filters = {};
    this.searchTerm = '';
    this.emitState();
  }

  private updatePaginationFlags(): void {
    this.totalPages = Math.ceil(this.totalFiltered / this.pageSize);
    this.hasNextPage = this.currentPage < this.totalPages;
    this.hasPreviousPage = this.currentPage > 1;
  }

  private emitState(): void {
    const state: PaginationState = {
      page: this.currentPage,
      size: this.pageSize,
      totalRecords: this.totalRecords,
      totalFiltered: this.totalFiltered,
      totalPages: this.totalPages,
      hasNextPage: this.hasNextPage,
      hasPreviousPage: this.hasPreviousPage,
      filters: { ...this.filters },
      search: this.searchTerm
    };
    
    this.paginationState$.next(state);
  }

  get page(): number { return this.currentPage; }
  get size(): number { return this.pageSize; }
  get total(): number { return this.totalRecords; }
  get filtered(): number { return this.totalFiltered; }
  get pages(): number { return this.totalPages; }
  get canGoNext(): boolean { return this.hasNextPage; }
  get canGoPrevious(): boolean { return this.hasPreviousPage; }
  get currentFilters(): any { return { ...this.filters }; }
  get currentSearch(): string { return this.searchTerm; }
}