import { Injectable, PipeTransform } from '@angular/core';
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
import { Role } from './role';
import { ROLES } from './roles';
import { DecimalPipe } from '@angular/common';
import { debounceTime, delay, switchMap, tap } from 'rxjs/operators';
import { SortColumn, SortDirection } from './sortable.directive';
import { BaseService } from 'src/app/shared/service/base.service';

interface SearchResult {
  roles: Role[];
  total: number;
}

interface State {
  page: number;
  pageSize: number;
  searchTerm: string;
  sortColumn: SortColumn;
  sortDirection: SortDirection;
}

const compare = (v1: string | number, v2: string | number) => v1 < v2 ? -1 : v1 > v2 ? 1 : 0;

function sort(roles: Role[], column: SortColumn, direction: string): Role[] {
  if (direction === '' || column === '') {
    return roles;
  } else {
    return [...roles].sort((a, b) => {
      const res = compare(a[column], b[column]);
      return direction === 'asc' ? res : -res;
    });
  }
}

function matches(role: Role, term: string) {
  return role.name.toLowerCase().includes(term.toLowerCase());
}

@Injectable({ providedIn: 'root' })
export class RoleService {
  private _loading$ = new BehaviorSubject<boolean>(true);
  private _search$ = new Subject<void>();
  private _roles$ = new BehaviorSubject<Role[]>([]);
  private _total$ = new BehaviorSubject<number>(0);
  private _tenant$ = new BehaviorSubject<any[]>([]);


  private _state: State = {
    page: 1,
    pageSize: 10,
    searchTerm: '',
    sortColumn: '',
    sortDirection: ''
  };

  constructor(private pipe: DecimalPipe, private baseService: BaseService) {
    this._search$.pipe(
      tap(() => this._loading$.next(true)),
      debounceTime(200),
      switchMap(() => this._search()),
      delay(200),
      tap(() => this._loading$.next(false))
    ).subscribe(result => {
      this._roles$.next(result.roles);
      this._total$.next(result.total);
    });

    this._search$.next();

    this.baseService.getData('tenants/getAllTenants').subscribe(
      (data: any) => {
        if (data) {
          this._tenant$.next(data.data);
        }
      },
      (err) => {
        console.log(err);
      }
    );
  }

  setRoles(roles: Role[]) {
    this._roles$.next(roles);
    this._total$.next(roles.length);
  }

  get roles$() { return this._roles$.asObservable(); }
  get total$() { return this._total$.asObservable(); }
  get loading$() { return this._loading$.asObservable(); }
  get tenant$() { return this._tenant$.asObservable(); }

  get page() { return this._state.page; }
  get pageSize() { return this._state.pageSize; }
  get searchTerm() { return this._state.searchTerm; }

  set page(page: number) { this._set({ page }); }
  set pageSize(pageSize: number) { this._set({ pageSize }); }
  set searchTerm(searchTerm: string) { this._set({ searchTerm }); }
  set sortColumn(sortColumn: SortColumn) { this._set({ sortColumn }); }
  set sortDirection(sortDirection: SortDirection) { this._set({ sortDirection }); }

  private _set(patch: Partial<State>) {
    Object.assign(this._state, patch);
    console.log("State updated:", this._state); // Debug log
    this._search$.next();
  }

  private _search(): Observable<SearchResult> {
    const { sortColumn, sortDirection, pageSize, page, searchTerm } = this._state;

    // Log the initial roles
    // console.log('Initial roles:', ROLES);

    // 1. sort
    let roles = sort(ROLES, sortColumn, sortDirection);
    // console.log('Sorted roles:', roles);

    // 2. filter
    roles = roles.filter(role => matches(role, searchTerm));
    // console.log('Filtered roles:', roles);
    const total = roles.length;

    // 3. paginate
    roles = roles.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize);
    // console.log('Paginated roles:', roles);
    return of({ roles, total });
  }
}
