/* eslint-disable @typescript-eslint/member-ordering */
import {
  Component,
  inject,
  signal,
  computed
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Store } from '@ngrx/store';
import { Router } from '@angular/router';
import { NgIcon, provideIcons } from '@ng-icons/core';
import {
  lucideMic,
  lucideMicOff,
  lucideMonitor,
  lucideShield,
  lucideCrown,
  lucideMoreVertical,
  lucideBan,
  lucideUserX,
  lucideVolume2,
  lucideVolumeX,
  lucideMessageCircle
} from '@ng-icons/lucide';

import { UsersActions } from '../../../../store/users/users.actions';
import {
  selectOnlineUsers,
  selectCurrentUser,
  selectIsCurrentUserAdmin
} from '../../../../store/users/users.selectors';
import { User } from '../../../../shared-kernel';
import { UserAvatarComponent, ConfirmDialogComponent } from '../../../../shared';
import { DirectMessageService } from '../../../direct-message';

@Component({
  selector: 'app-user-list',
  standalone: true,
  imports: [
    CommonModule,
    FormsModule,
    NgIcon,
    UserAvatarComponent,
    ConfirmDialogComponent
  ],
  viewProviders: [
    provideIcons({
      lucideMic,
      lucideMicOff,
      lucideMonitor,
      lucideShield,
      lucideCrown,
      lucideMoreVertical,
      lucideBan,
      lucideUserX,
      lucideVolume2,
      lucideVolumeX,
      lucideMessageCircle
    })
  ],
  templateUrl: './user-list.component.html'
})
/**
 * Displays the list of online users with voice state indicators and admin actions.
 */
export class UserListComponent {
  private store = inject(Store);
  private router = inject(Router);
  private directMessages = inject(DirectMessageService);

  onlineUsers = this.store.selectSignal(selectOnlineUsers) as import('@angular/core').Signal<User[]>;
  voiceUsers = computed(() => this.onlineUsers().filter((user: User) => !!user.voiceState?.isConnected));
  currentUser = this.store.selectSignal(selectCurrentUser) as import('@angular/core').Signal<User | undefined | null>;
  isAdmin = this.store.selectSignal(selectIsCurrentUserAdmin);

  showUserMenu = signal<string | null>(null);
  showBanDialog = signal(false);
  userToBan = signal<User | null>(null);
  banReason = '';
  banDuration = '86400000'; // Default 1 day

  /** Toggle the context menu for a specific user. */
  toggleUserMenu(userId: string): void {
    this.showUserMenu.update((current) => (current === userId ? null : userId));
  }

  /** Check whether the given user is the currently authenticated user. */
  isCurrentUser(user: User): boolean {
    return user.id === this.currentUser()?.id;
  }

  async openDirectMessage(user: User): Promise<void> {
    if (this.isCurrentUser(user)) {
      return;
    }

    const conversation = await this.directMessages.createConversation(user);

    await this.router.navigate(['/dm', conversation.id]);
  }

  /** Toggle server-side mute on a user (admin action). */
  muteUser(user: User): void {
    if (user.voiceState?.isMutedByAdmin) {
      this.store.dispatch(UsersActions.adminUnmuteUser({ userId: user.id }));
    } else {
      this.store.dispatch(UsersActions.adminMuteUser({ userId: user.id }));
    }

    this.showUserMenu.set(null);
  }

  /** Kick a user from the server (admin action). */
  kickUser(user: User): void {
    this.store.dispatch(UsersActions.kickUser({ userId: user.id }));
    this.showUserMenu.set(null);
  }

  /** Open the ban confirmation dialog for a user (admin action). */
  banUser(user: User): void {
    this.userToBan.set(user);
    this.showBanDialog.set(true);
    this.showUserMenu.set(null);
  }

  /** Close the ban dialog and reset its form fields. */
  closeBanDialog(): void {
    this.showBanDialog.set(false);
    this.userToBan.set(null);
    this.banReason = '';
    this.banDuration = '86400000';
  }

  /** Confirm the ban, dispatch the action with duration, and close the dialog. */
  confirmBan(): void {
    const user = this.userToBan();

    if (!user)
      return;

    const duration = parseInt(this.banDuration, 10);
    const expiresAt = duration === 0 ? undefined : Date.now() + duration;

    this.store.dispatch(
      UsersActions.banUser({
        userId: user.id,
        reason: this.banReason || undefined,
        expiresAt
      })
    );

    this.closeBanDialog();
  }
}
