import {
  ChangeDetectionStrategy,
  Component,
  inject,
  OnDestroy,
  OnInit,
  signal,
} from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { CommonModule, CurrencyPipe, KeyValuePipe, NgClass } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { UserService } from '@service/user.service';
import { Subscription } from 'rxjs';
import { AnimatedNumberComponent } from '@blackjack/components/animated-number/animated-number.component';
import { AuthService } from '@service/auth.service';

interface SlotResult {
  status: 'win' | 'lose' | 'blank' | 'start';
  amount: number;
  resultMatrix: string[][];
}

@Component({
  selector: 'app-slots',
  standalone: true,
  imports: [
    CommonModule,
    KeyValuePipe,
    NgClass,
    FormsModule,
    CurrencyPipe,
    AnimatedNumberComponent,
  ],
  templateUrl: './slots.component.html',
  styleUrl: './slots.component.css',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export default class SlotsComponent implements OnInit, OnDestroy {
  private httpClient: HttpClient = inject(HttpClient);
  private userService = inject(UserService);
  private authService = inject(AuthService);
  private userSubscription: Subscription | undefined;
  private winSound: HTMLAudioElement;

  slotInfo = signal<Record<string, number> | null>(null);
  slotResult = signal<SlotResult>({
    status: 'start',
    amount: 0,
    resultMatrix: [
      ['BAR', 'BAR', 'BAR'],
      ['SEVEN', 'SEVEN', 'SEVEN'],
      ['BELL', 'BELL', 'BELL'],
    ],
  });

  balance = signal<number>(0);
  betAmount = signal<number>(1);
  isSpinning = false;

  constructor() {
    this.winSound = new Audio('/sounds/win.mp3');
  }

  ngOnInit(): void {
    this.httpClient.get<Record<string, number>>('/backend/slots/info').subscribe((data) => {
      this.slotInfo.set(data);
    });

    this.userSubscription = this.authService.userSubject.subscribe((user) => {
      this.balance.set(user?.balance ?? 0);
    });

    this.userService.refreshCurrentUser();
  }

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

  getSymbolClass(symbol: string): string {
    return `symbol-${symbol}`;
  }

  hasEnoughBalance(): boolean {
    return this.balance() >= this.betAmount();
  }

  setBetAmount(percentage: number): void {
    const calculatedBet = Math.floor(this.balance() * percentage * 100) / 100;
    const minimumBet = 0.01;

    const newBet = Math.max(minimumBet, Math.min(calculatedBet, this.balance()));

    this.betAmount.set(newBet);
  }

  spin(): void {
    if (!this.hasEnoughBalance()) {
      return;
    }

    this.isSpinning = true;
    const betAmount = this.betAmount();

    this.userService.updateLocalBalance(-betAmount);

    const payload = {
      betAmount: betAmount,
    };

    this.httpClient.post<SlotResult>('/backend/slots/spin', payload).subscribe({
      next: (result) => {
        setTimeout(() => {
          this.slotResult.set(result);

          if (result.status === 'win') {
            this.winSound.play();
            this.userService.updateLocalBalance(result.amount);
          }

          this.userService.refreshCurrentUser();

          this.isSpinning = false;
        }, 100);
      },
      error: (err) => {
        console.error('Error spinning slot machine:', err);
        this.userService.updateLocalBalance(betAmount);
        this.userService.refreshCurrentUser();
        this.isSpinning = false;
      },
    });
  }
}
