import { HttpErrorResponse } from '@angular/common/http';
import { CurrencyPipe, DatePipe, registerLocaleData } from '@angular/common';
import localeDe from '@angular/common/locales/de';
import { Component, LOCALE_ID, computed, effect, inject, signal } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatDialog } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
import { filter, finalize, take } from 'rxjs';
import { AuthStore } from '../../../core/auth/auth-store';
import { TeamStore } from '../../../core/team/team-store';
import { TeamsApi } from '../../../core/team/teams-api';
import { PlayerTransaction } from '../../../models/transaction.model';
import { ConfirmDialog } from '../../../shared/confirm-dialog/confirm-dialog';
import { TransactionAmount } from '../../../shared/transaction-amount/transaction-amount';

registerLocaleData(localeDe);

@Component({
  selector: 'app-player-detail',
  imports: [
    CurrencyPipe,
    DatePipe,
    RouterLink,
    MatButtonModule,
    MatCardModule,
    MatFormFieldModule,
    MatIconModule,
    MatProgressSpinnerModule,
    MatSelectModule,
    TransactionAmount,
  ],
  providers: [{ provide: LOCALE_ID, useValue: 'de-DE' }],
  templateUrl: './player-detail.html',
  styleUrl: './player-detail.scss',
})
export class PlayerDetail {
  private readonly route = inject(ActivatedRoute);
  private readonly teamsApi = inject(TeamsApi);
  private readonly teamStore = inject(TeamStore);
  private readonly authStore = inject(AuthStore);
  private readonly dialog = inject(MatDialog);
  private readonly playerId = Number(this.route.snapshot.paramMap.get('playerId'));
  private readonly loadedKey = signal<string | null>(null);
  protected readonly team = this.teamStore.team;
  protected readonly player = computed(
    () => this.team()?.players?.find((player) => player.id === this.playerId) ?? null,
  );
  protected readonly transactions = signal<PlayerTransaction[]>([]);
  protected readonly loading = signal(true);
  protected readonly savingActive = signal(false);
  protected readonly savingRole = signal(false);
  protected readonly mutationError = signal<string | null>(null);

  protected readonly canManage = computed(() => {
    const user = this.authStore.currentUser();
    if (user?.role?.id === 1) return true;
    return (
      this.team()?.players?.some(
        (player) => player.user?.id === user?.id && (player.teamRole?.id ?? 0) >= 3,
      ) ?? false
    );
  });

  constructor() {
    effect(() => {
      const team = this.team();
      if (!team || !Number.isInteger(this.playerId)) return;
      const key = `${team.id}:${this.playerId}`;
      if (this.loadedKey() === key) return;
      this.loadedKey.set(key);
      this.teamsApi.loadPlayerTransactions(team.id, this.playerId).subscribe({
        next: (transactions) => {
          this.transactions.set(transactions);
          this.loading.set(false);
        },
        error: () => this.loading.set(false),
      });
    });
  }

  protected typeName(transaction: PlayerTransaction): string {
    return typeof transaction.type === 'string'
      ? transaction.type
      : (transaction.type?.name ?? 'Buchung');
  }

  protected changeActive(): void {
    const team = this.team();
    const player = this.player();
    if (!team || !player || this.savingActive()) return;
    const isActive = player.active;
    this.dialog
      .open(ConfirmDialog, {
        data: {
          title: isActive ? 'Spieler deaktivieren?' : 'Spieler aktivieren?',
          message: `${player.firstName} ${player.lastName} wird ${isActive ? 'deaktiviert' : 'aktiviert'}.`,
          confirmLabel: isActive ? 'Deaktivieren' : 'Aktivieren',
        },
        restoreFocus: true,
      })
      .afterClosed()
      .pipe(filter(Boolean), take(1))
      .subscribe(() => {
        this.savingActive.set(true);
        this.mutationError.set(null);
        this.teamsApi
          .setPlayerActive(team.id, player.id, !isActive)
          .pipe(finalize(() => this.savingActive.set(false)))
          .subscribe({
            next: () => this.teamStore.refreshTeam(),
            error: (error: HttpErrorResponse) =>
              this.mutationError.set(
                this.errorMessage(error, 'Status konnte nicht geändert werden.'),
              ),
          });
      });
  }

  protected changeTeamRole(teamRoleId: number): void {
    const team = this.team();
    const player = this.player();
    if (!team || !player || this.savingRole() || player.teamRole?.id === teamRoleId) return;
    this.savingRole.set(true);
    this.mutationError.set(null);
    this.teamsApi
      .setPlayerTeamRole(team.id, player.id, teamRoleId)
      .pipe(finalize(() => this.savingRole.set(false)))
      .subscribe({
        next: () => this.teamStore.refreshTeam(),
        error: (error: HttpErrorResponse) =>
          this.mutationError.set(this.errorMessage(error, 'Rolle konnte nicht geändert werden.')),
      });
  }

  private errorMessage(error: HttpErrorResponse, fallback: string): string {
    const detail = typeof error.error?.message === 'string' ? error.error.message : '';
    if (error.status === 403) return `Keine Berechtigung. ${detail}`.trim();
    if (error.status === 409) return detail || fallback;
    return detail ? `${fallback} ${detail}` : fallback;
  }
}
