import {Component, OnDestroy, OnInit} from '@angular/core';
import {environment} from "../../environments/environment";
import {SuspiciousScore} from "../replays";
import {Observable, Subscription, timer} from 'rxjs';
import {LocalCacheService} from "../../corelib/service/local-cache.service";
import {ActivatedRoute, Router, RouterLink} from "@angular/router";
import {FilterManagerService} from "../filter-manager.service";
import {FormsModule} from "@angular/forms";
import {DecimalPipe, NgForOf, NgIf, NgOptimizedImage} from "@angular/common";

export interface SuspiciousScoresFilter {
  sorting?: string;

  minPP?: number;
  maxPP?: number;

  minUR?: number;
  maxUR?: number;

  searchUsername?: string;
  searchBeatmap?: string;
}

@Component({
  selector: 'app-view-suspicious-scores',
  standalone: true,
  templateUrl: './view-suspicious-scores.component.html',
  imports: [
    FormsModule,
    RouterLink,
    NgForOf,
    DecimalPipe,
    NgOptimizedImage,
    NgIf
  ],
  styleUrls: ['./view-suspicious-scores.component.css']
})
export class ViewSuspiciousScoresComponent implements OnInit, OnDestroy {

  filterManager = new FilterManagerService<SuspiciousScoresFilter>("suspiciousScoreFilters");

  isUrlFilters = false;

  originalScores: SuspiciousScore[] = [];
  filteredScores: SuspiciousScore[] = [];

  currentPage = 1;
  itemsPerPage = 150;

  autoUpdateInterval: number = 3600000;
  isLoading: boolean = true;
  private updateSubscription: Subscription | null = null;

  constructor(
    private localCacheService: LocalCacheService,
    private router: Router,
    private activatedRoute: ActivatedRoute
  ) {
  }

  ngOnInit(): void {
    this.activatedRoute.params.subscribe(params => {
      let filters = params['f'];
      if (filters) {
        this.filterManager.setFiltersFromUrl(filters);
        this.isUrlFilters = true;
      } else {
        this.filterManager.setFiltersFromLocal();
      }
    });

    this.startAutoUpdateTimer();
  }

  getTotalPages(): number {
    return Math.ceil(this.filteredScores.length / this.itemsPerPage);
  }

  getCurrentPage(): SuspiciousScore[] {
    const start = (this.currentPage - 1) * this.itemsPerPage;
    const end = start + this.itemsPerPage;
    return this.filteredScores.slice(start, end);
  }

  getFiltersUrl(): void {
    let targetUrl = '/sus/' + this.filterManager.getFiltersUrl();
    this.router.navigate([targetUrl]).then(() => {
      navigator.clipboard.writeText(targetUrl).then(() => {
        console.debug('Loaded filters!')
      });
    });
  }

  ngOnDestroy(): void {
    if (this.updateSubscription) {
      this.updateSubscription.unsubscribe();
    }
  }

  startAutoUpdateTimer(): void {
    this.updateSubscription = timer(0, this.autoUpdateInterval).subscribe(() => {
      this.isLoading = true;
      this.getSuspiciousScores().subscribe(scores => {
        this.originalScores = scores;
        this.filterScores();
        this.isLoading = false;
      });
    });
  }

  resetValues(): void {
    this.filterManager.resetValues();
    this.filterScores();
    this.router.navigate(['/sus']).then(() => {
        this.isUrlFilters = false;
    });
  }

  getSuspiciousScores(): Observable<SuspiciousScore[]> {
    this.currentPage = 1;
    return this.localCacheService.fetchData<SuspiciousScore[]>(
      'suspiciousScores',
      `${environment.apiUrl}/suspicious-scores`,
      15
    );
  }

  filterScores(): void {
    // Access the filters from the filterManager
    const filters = this.filterManager.filters;

    // Trim and convert to lowercase for case-insensitive comparison
    const searchUsername = filters.searchUsername?.trim().toLowerCase();
    const searchBeatmap = filters.searchBeatmap?.trim().toLowerCase();

    this.filteredScores = this.originalScores.filter((score) => {
      // Apply username filter if specified, case-insensitive
      const usernameMatch = searchUsername ?
        score.username.toLowerCase().includes(searchUsername) :
        true;

      // Apply beatmap filter if specified, case-insensitive
      const beatmapMatch = searchBeatmap ?
        score.beatmap_title.toLowerCase().includes(searchBeatmap) :
        true;

      // Apply PP filter if specified
      const ppMatch = (filters.minPP == null || score.pp >= filters.minPP) &&
        (filters.maxPP == null || score.pp <= filters.maxPP);

      // Apply UR filter if specified
      const urMatch = (filters.minUR == null || score.ur >= filters.minUR) &&
        (filters.maxUR == null || score.ur <= filters.maxUR);

      return usernameMatch && beatmapMatch && ppMatch && urMatch;
    });

    // Presumably persists the current state of filters for future sessions
    this.filterManager.persistToLocalStorage();

    if(this.filterManager.filters.sorting) {
      let field = this.filterManager.filters.sorting.split("-")[0];
      let order = this.filterManager.filters.sorting.split("-")[1];
      //@ts-ignore
      this.sortScores(field, order);
    }
  }

  sortScores(field: 'pp' | 'ur' | 'beatmap_star_rating' | 'date', order: 'asc' | 'desc'): void {
    if(this.isUrlFilters && this.filterManager.filters.sorting != `${field}-${order}`) {
      return;
    }

    this.filterManager.filters.sorting = `${field}-${order}`
    this.filterManager.persistToLocalStorage();
    this.currentPage = 1;

    this.filteredScores.sort((a: SuspiciousScore, b: SuspiciousScore): number => {
      let compareValue = 0;

      if (field === 'pp' || field === 'ur' || field === 'beatmap_star_rating') {
        compareValue = a[field] - b[field];
      } else if (field === 'date') {
        compareValue = a[field] < b[field] ? -1 : a[field] > b[field] ? 1 : 0;
      }

      return order === 'asc' ? compareValue : -compareValue;
    });
  }



}
