/* eslint-disable @typescript-eslint/member-ordering */
import {
  Component,
  effect,
  inject,
  input,
  signal
} 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 {
  lucideCheck,
  lucideImage,
  lucideTrash2,
  lucideLock,
  lucideUnlock,
  lucideUpload,
  lucideX
} from '@ng-icons/lucide';

import { Room } from '../../../../shared-kernel';
import { RoomsActions } from '../../../../store/rooms/rooms.actions';
import { ConfirmDialogComponent } from '../../../../shared';
import { SettingsModalService } from '../../../../core/services/settings-modal.service';
import { ServerIconImageService } from '../../../../domains/server-directory/infrastructure/services/server-icon-image.service';
import { APP_TRANSLATE_IMPORTS, AppI18nService } from '../../../../core/i18n';
import { SelectOnFocusDirective, SubmitOnEnterDirective } from '../../../../shared/directives';

@Component({
  selector: 'app-server-settings',
  standalone: true,
  imports: [
    CommonModule,
    FormsModule,
    NgIcon,
    ConfirmDialogComponent,
    SelectOnFocusDirective,
    SubmitOnEnterDirective,
    ...APP_TRANSLATE_IMPORTS
  ],
  viewProviders: [
    provideIcons({
      lucideCheck,
      lucideImage,
      lucideTrash2,
      lucideLock,
      lucideUnlock,
      lucideUpload,
      lucideX
    })
  ],
  templateUrl: './server-settings.component.html'
})
export class ServerSettingsComponent {
  private store = inject(Store);
  private modal = inject(SettingsModalService);
  private serverIconImages = inject(ServerIconImageService);
  private readonly appI18n = inject(AppI18nService);

  /** 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);
  /** Whether the current user can manage this server's icon. */
  canManageIcon = input(false);
  /** Whether the current user can delete this server. */
  canDeleteServer = input(false);

  roomName = '';
  roomDescription = '';
  isPrivate = signal(false);
  hasPassword = signal(false);
  passwordAction = signal<'keep' | 'update' | 'remove'>('keep');
  passwordError = signal<string | null>(null);
  roomPassword = '';
  maxUsers = 0;
  showDeleteConfirm = signal(false);
  iconError = signal<string | null>(null);

  saveSuccess = signal<string | null>(null);
  private saveTimeout: ReturnType<typeof setTimeout> | null = null;

  /** Reload form fields whenever the server input changes. */
  readonly serverData = this.server;

  constructor() {
    effect(() => {
      const room = this.server();

      if (!room)
        return;

      this.roomName = room.name;
      this.roomDescription = room.description || '';
      this.isPrivate.set(room.isPrivate);
      this.hasPassword.set(typeof room.hasPassword === 'boolean' ? room.hasPassword : !!room.password);
      this.passwordAction.set('keep');
      this.passwordError.set(null);
      this.roomPassword = '';
      this.maxUsers = room.maxUsers || 0;
    });
  }

  togglePrivate(): void {
    this.isPrivate.update((currentValue) => !currentValue);
  }

  saveServerSettings(): void {
    const room = this.server();

    if (!room)
      return;

    const normalizedPassword = this.roomPassword.trim();
    const settings: {
      description: string;
      hasPassword?: boolean;
      isPrivate: boolean;
      maxUsers: number;
      name: string;
      password?: string;
    } = {
      name: this.roomName,
      description: this.roomDescription,
      isPrivate: this.isPrivate(),
      maxUsers: this.maxUsers
    };

    if (this.passwordAction() === 'remove') {
      settings.password = '';
      settings.hasPassword = false;
    } else if (normalizedPassword) {
      settings.password = normalizedPassword;
      settings.hasPassword = true;
    }

    this.store.dispatch(
      RoomsActions.updateRoomSettings({
        roomId: room.id,
        settings
      })
    );

    this.hasPassword.set(settings.hasPassword ?? this.hasPassword());
    this.passwordAction.set('keep');
    this.passwordError.set(null);
    this.roomPassword = '';
    this.showSaveSuccess('server');
  }

  markPasswordForRemoval(): void {
    this.passwordAction.set('remove');
    this.passwordError.set(null);
    this.roomPassword = '';
  }

  keepCurrentPassword(): void {
    this.passwordAction.set('keep');
    this.passwordError.set(null);
    this.roomPassword = '';
  }

  onPasswordInput(value: string): void {
    this.roomPassword = value;
    this.passwordError.set(null);

    if (value.trim().length > 0) {
      this.passwordAction.set('update');
      return;
    }

    this.passwordAction.set('keep');
  }

  confirmDeleteRoom(): void {
    this.showDeleteConfirm.set(true);
  }

  deleteRoom(): void {
    const room = this.server();

    if (!room)
      return;

    this.store.dispatch(RoomsActions.deleteRoom({ roomId: room.id }));
    this.showDeleteConfirm.set(false);
    this.modal.navigate('network');
  }

  async onServerIconSelected(event: Event): Promise<void> {
    const inputElement = event.target as HTMLInputElement;
    const file = inputElement.files?.[0];

    inputElement.value = '';

    if (!file || !this.canManageIcon()) {
      return;
    }

    try {
      const room = this.server();
      const icon = await this.serverIconImages.process(file);

      if (!room) {
        return;
      }

      this.iconError.set(null);
      this.store.dispatch(RoomsActions.updateServerIcon({
        roomId: room.id,
        icon: icon.dataUrl
      }));

      this.showSaveSuccess('icon');
    } catch (error) {
      this.iconError.set(error instanceof Error ? error.message : this.appI18n.instant('settings.server.image.readError'));
    }
  }

  removeServerIcon(): void {
    const room = this.server();

    if (!room || !this.canManageIcon()) {
      return;
    }

    this.iconError.set(null);
    this.store.dispatch(RoomsActions.updateServerIcon({
      roomId: room.id,
      icon: ''
    }));

    this.showSaveSuccess('icon');
  }

  private showSaveSuccess(key: string): void {
    this.saveSuccess.set(key);

    if (this.saveTimeout)
      clearTimeout(this.saveTimeout);

    this.saveTimeout = setTimeout(() => this.saveSuccess.set(null), 2000);
  }
}
