import { CommonModule } from '@angular/common';
import { Component, DestroyRef, OnDestroy, OnInit, inject } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { Router } from '@angular/router';
import { finalize } from 'rxjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { getErrorMessage } from '../../core/http/error-message.util';
import { CurrentUser } from '../../models/auth.models';
import { AuthDialogService } from '../../services/auth-dialog.service';
import { AuthService } from '../../services/auth.service';
import { GameApiService } from '../../services/game-api.service';
import { ThemeService } from '../../services/theme.service';
import { ChallengeCreateDialogComponent } from '../../components/challenge-create-dialog/challenge-create-dialog.component';

type Difficulty = 'easy' | 'medium' | 'hard';
type ImportMode = 'fen' | 'pgn';

interface Star {
  style: Record<string, string>;
}

interface BackgroundBuilding {
  style: Record<string, string>;
}

interface WindowCell {
  state: 'off' | 'on';
  color?: string;
  glowColor?: string;
  style: Record<string, string>;
}

interface Star {
  style: Record<string, string>;
}

interface BackgroundBuilding {
  style: Record<string, string>;
}

interface WindowCell {
  state: 'off' | 'on';
  color?: string;
  glowColor?: string;
  style: Record<string, string>;
}

@Component({
  selector: 'app-welcome',
  standalone: true,
  imports: [CommonModule, FormsModule, ChallengeCreateDialogComponent],
  templateUrl: './welcome.component.html',
  styleUrls: ['./welcome.component.css']
})
export class WelcomeComponent implements OnInit, OnDestroy {
  private readonly destroyRef = inject(DestroyRef);
  private readonly authService = inject(AuthService);
  private readonly authDialogService = inject(AuthDialogService);
  private readonly themeService = inject(ThemeService);

  creating = false;
  joiningGame = false;
  importing = false;
  errorMessage = '';

  showDifficultyDialog = false;
  showOptionsDialog = false;
  showJoinDialog = false;
  showImportDialog = false;
  showChallengeDialog = false;

  gameIdInput = '';
  importMode: ImportMode = 'fen';
  importText = '';

  isSunsetMode = false;
  modeBadge = 'NIGHT MODE';
  currentUser: CurrentUser | null = null;
  private authDialogState: 'login' | 'register' | null = null;
  private pendingAction: (() => void) | null = null;

  stars: Star[] = [];
  bgBuildings: BackgroundBuilding[] = [];
  windows: Record<string, WindowCell[]> = {};

  private flickerIntervalId: ReturnType<typeof setInterval> | undefined;

  private coolColors = ['#7de8ff', '#00d5ff', '#5bc0de', '#31b0d5', '#4fc3f7', '#29b6f6'];
  private coolGlowColors = ['#00d5ff', '#00d5ff', '#31b0d5', '#31b0d5', '#03a9f4', '#0288d1'];

  private warmColors = ['#ffe88a', '#ffcc30', '#f0ad4e', '#ec971f', '#ffb74d', '#ffa726'];
  private warmGlowColors = ['#ffcc30', '#ffcc30', '#ec971f', '#ec971f', '#ff9800', '#fb8c00'];

  constructor(
    private readonly router: Router,
    private readonly gameApi: GameApiService
  ) {
  }

  ngOnInit(): void {
    this.themeService.darkMode$
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe((isDarkMode) => {
        this.isSunsetMode = !isDarkMode;
        this.modeBadge = this.isSunsetMode ? 'SUNSET MODE' : 'NIGHT MODE';
      });

    this.authService.currentUser$
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe((user) => {
        this.currentUser = user;
        this.maybeRunPendingAction();
      });

    this.authDialogService.dialogState$
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe((state) => {
        this.authDialogState = state;
        this.maybeRunPendingAction();
      });

    this.generateStars(220);
    this.generateBackgroundBuildings();
    this.generateWindowsForAllBuildings();
    this.startWindowFlicker();
  }

  ngOnDestroy(): void {
    this.stopWindowFlicker();
  }

  openDifficultyDialog(): void {
    if (!this.requireAuth(() => this.showDifficultyDialog = true)) {
      return;
    }

    this.closeAllDialogs();
    this.showDifficultyDialog = true;
  }

  closeDifficultyDialog(): void {
    this.showDifficultyDialog = false;
    this.errorMessage = '';
  }

  openOptionsDialog(): void {
    this.closeAllDialogs();
    this.showOptionsDialog = true;
  }

  closeOptionsDialog(): void {
    this.showOptionsDialog = false;
    this.errorMessage = '';
  }

  openJoinDialog(): void {
    if (!this.requireAuth(() => this.showJoinDialog = true)) {
      return;
    }

    this.closeAllDialogs();
    this.showJoinDialog = true;
  }

  closeJoinDialog(): void {
    if (this.joiningGame) {
      return;
    }
    this.showJoinDialog = false;
    this.gameIdInput = '';
    this.errorMessage = '';
  }

  openImportDialog(): void {
    if (!this.requireAuth(() => this.showImportDialog = true)) {
      return;
    }

    this.closeAllDialogs();
    this.showImportDialog = true;
  }

  closeImportDialog(): void {
    if (this.importing) {
      return;
    }
    this.showImportDialog = false;
    this.importText = '';
    this.importMode = 'fen';
    this.errorMessage = '';
  }

  setImportMode(mode: ImportMode): void {
    this.importMode = mode;
    this.errorMessage = '';
  }

  startOneVsOne(): void {
    if (!this.requireAuth(() => this.openChallengeDialog())) {
      return;
    }

    this.openChallengeDialog();
  }

  openChallengeDialog(): void {
    this.closeAllDialogs();
    this.showChallengeDialog = true;
  }

  closeChallengeDialog(): void {
    this.showChallengeDialog = false;
    this.errorMessage = '';
  }

  startVsBot(difficulty: Difficulty): void {
    if (!this.requireAuth(() => this.performStartVsBot(difficulty))) {
      return;
    }

    this.performStartVsBot(difficulty);
  }

  submitJoinGame(): void {
    if (!this.requireAuth(() => this.performSubmitJoinGame())) {
      return;
    }

    this.performSubmitJoinGame();
  }

  submitImportGame(): void {
    if (!this.requireAuth(() => this.performSubmitImportGame())) {
      return;
    }

    this.performSubmitImportGame();
  }

  private requireAuth(action: () => void): boolean {
    if (this.authService.isLoggedIn()) {
      return true;
    }

    this.pendingAction = action;
    this.authDialogService.openLogin();
    return false;
  }

  private maybeRunPendingAction(): void {
    if (!this.currentUser || this.authDialogState !== null || !this.pendingAction) {
      return;
    }

    const action = this.pendingAction;
    this.pendingAction = null;
    action();
  }


  private performStartVsBot(difficulty: Difficulty): void {
    if (this.creating) {
      return;
    }

    this.errorMessage = '';
    this.creating = true;
    this.showDifficultyDialog = false;

    this.gameApi
      .createGameVsBot(difficulty)
      .pipe(finalize(() => (this.creating = false)))
      .subscribe({
        next: (game) => {
          void this.router.navigate(['/game', game.gameId], {
            state: { theme: this.isSunsetMode ? 'light' : 'dark' }
          });
        },
        error: (error) => {
          this.errorMessage = getErrorMessage(error, 'Unable to create a game against bot.');
        }
      });
  }

  private performSubmitJoinGame(): void {
    const gameId = this.gameIdInput.trim();
    if (this.joiningGame || !gameId) {
      return;
    }

    this.errorMessage = '';
    this.joiningGame = true;

    this.gameApi
      .getGame(gameId)
      .pipe(finalize(() => (this.joiningGame = false)))
      .subscribe({
        next: (game) => {
          this.closeJoinDialog();
          void this.router.navigate(['/game', game.gameId], {
            state: { theme: this.isSunsetMode ? 'light' : 'dark' }
          });
        },
        error: (error) => {
          this.errorMessage = getErrorMessage(error, 'Unable to find or join the game.');
        }
      });
  }

  private performSubmitImportGame(): void {
    const trimmedImport = this.importText.trim();
    if (this.importing || !trimmedImport) {
      return;
    }

    this.errorMessage = '';
    this.importing = true;

    const importRequest =
      this.importMode === 'fen' ? this.gameApi.importFen(trimmedImport) : this.gameApi.importPgn(trimmedImport);

    importRequest.pipe(finalize(() => (this.importing = false))).subscribe({
      next: (game) => {
        this.closeImportDialog();
        void this.router.navigate(['/game', game.gameId], {
          state: { theme: this.isSunsetMode ? 'light' : 'dark' }
        });
      },
      error: (error) => {
        const defaultMessage = this.importMode === 'fen' ? 'Unable to import FEN.' : 'Unable to import PGN.';
        this.errorMessage = getErrorMessage(error, defaultMessage);
      }
    });
  }

  private closeAllDialogs(): void {
    this.showDifficultyDialog = false;
    this.showOptionsDialog = false;
    this.showJoinDialog = false;
    this.showImportDialog = false;
    this.errorMessage = '';
  }

  private generateStars(count: number): void {
    this.stars = Array.from({ length: count }, () => {
      const size = Math.random() * 2 + 0.5;
      return {
        style: {
          width: `${size}px`,
          height: `${size}px`,
          left: `${Math.random() * 100}%`,
          top: `${Math.random() * 62}%`,
          '--d': `${(Math.random() * 3 + 1.5).toFixed(1)}s`,
          '--dl': `${-(Math.random() * 6).toFixed(1)}s`
        }
      };
    });
  }

  private generateBackgroundBuildings(): void {
    const specs = [
      { l: '0%', w: '7%', h: '30vh' },
      { l: '3%', w: '4%', h: '18vh' }, // New building
      { l: '7%', w: '5%', h: '22vh' },
      { l: '11%', w: '8%', h: '28vh' },
      { l: '15%', w: '6%', h: '20vh' },
      { l: '18.5%', w: '4%', h: '18vh' },
      { l: '22.5%', w: '6%', h: '26vh' },
      { l: '28%', w: '5%', h: '25vh' },
      { l: '32%', w: '4%', h: '15vh' },
      { l: '35.5%', w: '4.5%', h: '20vh' },
      { l: '42%', w: '5%', h: '28vh' },
      { l: '47%', w: '5%', h: '22vh' }, // New building
      { l: '50%', w: '7%', h: '30vh' },
      { l: '55%', w: '6%', h: '27vh' },
      { l: '60.5%', w: '5%', h: '24vh' },
      { l: '64.5%', w: '3.5%', h: '17vh' },
      { l: '70%', w: '6%', h: '23vh' },
      { l: '75%', w: '4%', h: '19vh' },
      { l: '80.5%', w: '4%', h: '21vh' },
      { l: '85.5%', w: '9%', h: '32vh' },
      { l: '88%', w: '5%', h: '20vh' },
      { l: '91%', w: '3%', h: '16vh' }, // New building
      { l: '94%', w: '6%', h: '27vh' }
    ];

    this.bgBuildings = specs.map((spec) => ({
      style: { left: spec.l, width: spec.w, height: spec.h }
    }));
  }

  private generateWindowsForAllBuildings(): void {
    this.windows = {
      wA1: this.generateWindows(3, 4, 0.6),
      wA2: this.generateWindows(4, 5, 0.55),
      wA3: this.generateWindows(5, 18, 0.5),
      wB1: this.generateWindows(4, 3, 0.6),
      wB2: this.generateWindows(5, 20, 0.55),
      wC1: this.generateWindows(5, 3, 0.7),
      wC2: this.generateWindows(6, 5, 0.65),
      wC3: this.generateWindows(7, 24, 0.6),
      wD1: this.generateWindows(6, 3, 0.6),
      wD2: this.generateWindows(6, 20, 0.5),
      wE1: this.generateWindows(3, 16, 0.45)
    };
  }

  private generateWindows(cols: number, rows: number, litRate: number): WindowCell[] {
    const total = cols * rows;
    return Array.from({ length: total }, () => this.createWindowCell(litRate));
  }

  private createWindowCell(litRate: number): WindowCell {
    const random = Math.random();
    let state: WindowCell['state'] = 'off';
    let color: string | undefined;
    let glowColor: string | undefined;

    if (random < litRate * 0.58) { // Cool color
      state = 'on';
      const coolIndex = Math.floor(Math.random() * this.coolColors.length);
      color = this.coolColors[coolIndex];
      glowColor = this.coolGlowColors[coolIndex];
    } else if (random < litRate) { // Warm color
      state = 'on';
      const warmIndex = Math.floor(Math.random() * this.warmColors.length);
      color = this.warmColors[warmIndex];
      glowColor = this.warmGlowColors[warmIndex];
    }

    if (state === 'off') {
      return { state, style: {} };
    }

    const baseDuration = (color && this.coolColors.includes(color)) ? 3 : 4;
    return {
      state,
      color,
      glowColor,
      style: {
        'background-color': color || '',
        'box-shadow': glowColor ? `0 0 6px ${glowColor}, 0 0 16px ${glowColor}35` : '',
        '--wd': `${(Math.random() * 4 + baseDuration).toFixed(1)}s`,
        '--wdl': `${-(Math.random() * 8).toFixed(1)}s`
      }
    };
  }

  private startWindowFlicker(): void {
    this.flickerIntervalId = setInterval(() => {
      this.randomFlicker();
    }, 2800);
  }

  private stopWindowFlicker(): void {
    if (this.flickerIntervalId === undefined) {
      return;
    }
    clearInterval(this.flickerIntervalId);
    this.flickerIntervalId = undefined;
  }

  private randomFlicker(): void {
    const allWindows = Object.values(this.windows).flat();
    if (allWindows.length === 0) {
      return;
    }

    const pickCount = Math.floor(Math.random() * 6) + 1;
    for (let i = 0; i < pickCount; i += 1) {
      const target = allWindows[Math.floor(Math.random() * allWindows.length)];
      if (!target) {
        continue;
      }

      if (target.state === 'off') {
        target.state = 'on';
        const isCool = Math.random() < 0.5;
        const colors = isCool ? this.coolColors : this.warmColors;
        const glowColors = isCool ? this.coolGlowColors : this.warmGlowColors;
        const index = Math.floor(Math.random() * colors.length);

        target.color = colors[index];
        target.glowColor = glowColors[index];
        target.style = {
          'background-color': target.color || '',
          'box-shadow': target.glowColor ? `0 0 6px ${target.glowColor}, 0 0 16px ${target.glowColor}35` : '',
          '--wd': `${(Math.random() * 4 + (isCool ? 3 : 4)).toFixed(1)}s`,
          '--wdl': `${-(Math.random() * 8).toFixed(1)}s`
        };
      } else {
        target.state = 'off';
        target.color = undefined;
        target.glowColor = undefined;
        target.style = {};
      }
    }
  }
}
