/* eslint-disable @typescript-eslint/member-ordering */
import {
  Component,
  computed,
  inject,
  input
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { Store } from '@ngrx/store';
import { lucideUserX, lucideBan } from '@ng-icons/lucide';

import {
  Room,
  RoomMember,
  RoomRole
} from '../../../../shared-kernel';
import { RoomsActions } from '../../../../store/rooms/rooms.actions';
import { UsersActions } from '../../../../store/users/users.actions';
import { selectCurrentUser, selectUsersEntities } from '../../../../store/users/users.selectors';
import { selectCurrentRoom } from '../../../../store/rooms/rooms.selectors';
import { UserAvatarComponent } from '../../../../shared';
import {
  canManageMember,
  findAssignableRoles,
  getDisplayRoleName,
  getRoleIdsForMember,
  normalizeRoomAccessControl,
  setRoleAssignmentsForMember
} from '../../../../domains/access-control';

interface ServerMemberView extends RoomMember {
  assignedRoleIds: string[];
  displayRoleName: string;
  isOnline: boolean;
}

@Component({
  selector: 'app-members-settings',
  standalone: true,
  imports: [
    CommonModule,
    FormsModule,
    NgIcon,
    UserAvatarComponent
  ],
  viewProviders: [
    provideIcons({
      lucideUserX,
      lucideBan
    })
  ],
  templateUrl: './members-settings.component.html'
})
export class MembersSettingsComponent {
  private store = inject(Store);

  /** The currently selected server, passed from the parent. */
  server = input<Room | null>(null);
  /** Whether the current user is admin of this server. */
  isAdmin = input(false);
  accessRole = input<string | null>(null);

  currentUser = this.store.selectSignal(selectCurrentUser);
  currentRoom = this.store.selectSignal(selectCurrentRoom);
  usersEntities = this.store.selectSignal(selectUsersEntities);
  normalizedServer = computed(() => {
    const room = this.server();

    return room ? normalizeRoomAccessControl(room) : null;
  });
  assignableRoles = computed<RoomRole[]>(() => findAssignableRoles(this.normalizedServer()?.roles ?? []));

  members = computed<ServerMemberView[]>(() => {
    const room = this.normalizedServer();
    const me = this.currentUser();
    const currentRoom = this.currentRoom();
    const usersEntities = this.usersEntities();

    if (!room)
      return [];

    return (room.members ?? [])
      .filter((member) => member.id !== me?.id && member.oderId !== me?.oderId)
      .map((member) => {
        const liveUser = currentRoom?.id === room.id
          ? (usersEntities[member.id]
            || Object.values(usersEntities).find((user) => !!user && user.oderId === member.oderId)
            || null)
          : null;

        return {
          ...member,
          assignedRoleIds: getRoleIdsForMember(room, member),
          displayRoleName: getDisplayRoleName(room, member),
          avatarUrl: liveUser?.avatarUrl || member.avatarUrl,
          displayName: liveUser?.displayName || member.displayName,
          isOnline: !!liveUser && (liveUser.isOnline === true || liveUser.status !== 'offline')
        };
      });
  });

  canChangeRoles(member: ServerMemberView): boolean {
    const room = this.normalizedServer();
    const currentUser = this.currentUser();

    return !!room && !!currentUser && canManageMember(room, currentUser, member, 'manageRoles');
  }

  canKickMembers(member: ServerMemberView): boolean {
    const room = this.normalizedServer();
    const currentUser = this.currentUser();

    return !!room && !!currentUser && canManageMember(room, currentUser, member, 'kickMembers');
  }

  canBanMembers(member: ServerMemberView): boolean {
    const room = this.normalizedServer();
    const currentUser = this.currentUser();

    return !!room && !!currentUser && canManageMember(room, currentUser, member, 'banMembers');
  }

  toggleRole(member: ServerMemberView, roleId: string, event: Event): void {
    const room = this.normalizedServer();

    if (!room)
      return;

    const checkbox = event.target as HTMLInputElement;
    const nextRoleIds = checkbox.checked
      ? [...member.assignedRoleIds, roleId]
      : member.assignedRoleIds.filter((candidateRoleId) => candidateRoleId !== roleId);
    const roleAssignments = setRoleAssignmentsForMember(room.roleAssignments, member, nextRoleIds);

    this.store.dispatch(RoomsActions.updateRoomAccessControl({
      roomId: room.id,
      changes: { roleAssignments }
    }));
  }

  kickMember(member: ServerMemberView): void {
    const room = this.normalizedServer();

    if (!room)
      return;

    this.store.dispatch(UsersActions.kickUser({ userId: member.id,
      roomId: room.id }));
  }

  banMember(member: ServerMemberView): void {
    const room = this.normalizedServer();

    if (!room)
      return;

    this.store.dispatch(UsersActions.banUser({ userId: member.id,
      roomId: room.id,
      displayName: member.displayName }));
  }
}
