import {Component, inject, input, OnChanges, OnInit, output} from '@angular/core';
import {HistoryService, PunishmentHistory} from '@api';
import {catchError, map, Observable, shareReplay} from 'rxjs';
import {NgOptimizedImage} from '@angular/common';
import {CookieService} from 'ngx-cookie-service';
import {RemoveTrailingPeriodPipe} from '@pipes/RemoveTrailingPeriodPipe';
import {HttpErrorResponse} from '@angular/common/http';
import {HistoryFormatService} from '../history-format.service';
import {SearchParams} from '../search-terms';
import {Router} from '@angular/router';
import {AuthService} from '@services/auth.service';
import {MatDialog} from '@angular/material/dialog';
import {EditPunishmentDialogComponent} from '../edit-punishment-dialog/edit-punishment-dialog.component';
import {MatIconModule} from '@angular/material/icon';

@Component({
  selector: 'app-history',
  imports: [
    NgOptimizedImage,
    RemoveTrailingPeriodPipe,
    MatIconModule,
  ],
  templateUrl: './history.component.html',
  styleUrl: './history.component.scss',
  providers: [
    CookieService,
  ],
})
export class HistoryComponent implements OnInit, OnChanges {

  userType = input<'player' | 'staff'>("player");
  punishmentType = input<'all' | 'ban' | 'mute' | 'kick' | 'warn'>("all");
  page = input<number>(0);
  searchTerm = input<string>('');

  pageChange = output<number>();
  selectItem = output<SearchParams>();

  private uuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;

  public history: PunishmentHistory[] = []

  private historyApi: HistoryService = inject(HistoryService)
  public historyFormat: HistoryFormatService = inject(HistoryFormatService)
  private router: Router = inject(Router)
  private authService: AuthService = inject(AuthService)
  private dialog: MatDialog = inject(MatDialog)

  ngOnChanges(): void {
    this.reloadHistory();
  }

  ngOnInit(): void {
    this.reloadHistory();
  }

  private reloadHistory(): void {
    let historyObservable: Observable<PunishmentHistory[]>;
    if (this.searchTerm().length === 0) {
      historyObservable = this.historyApi.getHistoryForAll(this.userType(), this.punishmentType(), this.page());
    } else {
      if (this.uuidRegex.test(this.searchTerm())) {
        historyObservable = this.historyApi.getHistoryForUuid(this.userType(), this.punishmentType(), this.searchTerm(), this.page());
      } else {
        historyObservable = this.historyApi.getHistoryForUsers(this.userType(), this.punishmentType(), this.searchTerm(), this.page());
      }
    }
    historyObservable.pipe(
      map(history => {
        this.history = history;
        this.pageChange.emit(this.history.length);
      }),
      catchError(err => {
        this.pageChange.emit(-1);
        let retrySeconds = 5;

        if (err instanceof HttpErrorResponse) {
          if (err.status !== 429) {
            return this.history;
          }
          const headers = err.headers;
          const retryAfterHeader = headers.get('Retry-After');
          console.warn(err.error);
          if (retryAfterHeader) {
            const retryAfter = parseInt(retryAfterHeader || '0', 10);
            if (!isNaN(retryAfter) && retryAfter > 0) {
              retrySeconds = retryAfter + 1;
            }
          }
        } else {
          console.error(err);
        }
        setTimeout(() => this.reloadHistory(), retrySeconds * 1000);
        return this.history;
      }),
      shareReplay(1)
    ).subscribe();
  }

  setSearch(name: string, userType: 'player' | 'staff') {
    let searchParams: SearchParams = {
      userType: userType,
      punishmentType: 'all',
      searchTerm: name
    }
    this.selectItem.emit(searchParams);
  }

  public showDetailedPunishment(entry: PunishmentHistory) {
    this.router.navigate([`bans/${entry.type}/${entry.id}`]).then();
  }

  public canEdit(): boolean {
    return this.authService.hasAccess(['SCOPE_head_mod']);
  }

  public openEdit(punishment: PunishmentHistory) {
    if (!this.canEdit()) return;
    const ref = this.dialog.open(EditPunishmentDialogComponent, {
      data: {punishment},
      width: '500px',
    });
    ref.afterClosed().subscribe(result => {
      if (result) {
        this.reloadHistory();
      }
    });
  }
}
