/* 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 { NgIcon, provideIcons } from '@ng-icons/core';
import {
  lucideGlobe,
  lucideServer,
  lucideRefreshCw,
  lucidePlus,
  lucideTrash2,
  lucideCheck,
  lucideX
} from '@ng-icons/lucide';

import { ServerDirectoryFacade } from '../../../../domains/server-directory';
import { SignalServerAuthService } from '../../../../domains/authentication/application/services/signal-server-auth.service';
import { SignalServerProvisionNoticeService } from '../../../../domains/authentication/application/services/signal-server-provision-notice.service';
import { SignalServerAuthorizeService } from '../../../../domains/authentication/application/services/signal-server-authorize.service';
import { STORAGE_KEY_CONNECTION_SETTINGS } from '../../../../core/constants';
import { IceServerSettingsComponent } from '../ice-server-settings/ice-server-settings.component';
import { APP_TRANSLATE_IMPORTS, AppI18nService } from '../../../../core/i18n';
import { SelectOnFocusDirective, SubmitOnEnterDirective } from '../../../../shared/directives';

@Component({
  selector: 'app-network-settings',
  standalone: true,
  imports: [
    CommonModule,
    FormsModule,
    NgIcon,
    IceServerSettingsComponent,
    SelectOnFocusDirective,
    SubmitOnEnterDirective,
    ...APP_TRANSLATE_IMPORTS
  ],
  viewProviders: [
    provideIcons({
      lucideGlobe,
      lucideServer,
      lucideRefreshCw,
      lucidePlus,
      lucideTrash2,
      lucideCheck,
      lucideX
    })
  ],
  templateUrl: './network-settings.component.html'
})
export class NetworkSettingsComponent {
  private serverDirectory = inject(ServerDirectoryFacade);
  private readonly appI18n = inject(AppI18nService);
  readonly signalServerAuth = inject(SignalServerAuthService);
  private readonly signalServerAuthorize = inject(SignalServerAuthorizeService);
  private readonly provisionNoticeService = inject(SignalServerProvisionNoticeService);
  readonly provisionNotice = this.provisionNoticeService.notice;

  servers = this.serverDirectory.servers;
  activeServers = this.serverDirectory.activeServers;
  hasMissingDefaultServers = this.serverDirectory.hasMissingDefaultServers;
  hasMultipleServers = computed(() => this.servers().length > 1);
  hasMultipleActiveServers = computed(() => this.activeServers().length > 1);
  isTesting = signal(false);
  addError = signal<string | null>(null);
  newServerName = '';
  newServerUrl = '';
  autoReconnect = true;
  searchAllServers = true;

  constructor() {
    this.loadConnectionSettings();
  }

  addServer(): void {
    this.addError.set(null);

    try {
      new URL(this.newServerUrl);
    } catch {
      this.addError.set(this.appI18n.instant('settings.network.serverEndpoints.errors.invalidUrl'));
      return;
    }

    if (this.servers().some((serverEntry) => serverEntry.url === this.newServerUrl)) {
      this.addError.set(this.appI18n.instant('settings.network.serverEndpoints.errors.duplicateUrl'));
      return;
    }

    this.serverDirectory.addServer({
      name: this.newServerName.trim(),
      url: this.newServerUrl.trim().replace(/\/$/, '')
    });

    this.newServerName = '';
    this.newServerUrl = '';
    const servers = this.servers();
    const newServer = servers[servers.length - 1];

    if (newServer)
      this.serverDirectory.testServer(newServer.id);
  }

  removeServer(id: string): void {
    this.serverDirectory.removeServer(id);
  }

  setActiveServer(id: string): void {
    this.serverDirectory.setActiveServer(id);
  }

  deactivateServer(id: string): void {
    this.serverDirectory.deactivateServer(id);
  }

  restoreDefaultServers(): void {
    this.serverDirectory.restoreDefaultServers();
  }

  async testAllServers(): Promise<void> {
    this.isTesting.set(true);
    await this.serverDirectory.testAllServers();
    this.isTesting.set(false);
  }

  loadConnectionSettings(): void {
    const raw = localStorage.getItem(STORAGE_KEY_CONNECTION_SETTINGS);

    if (raw) {
      const parsed = JSON.parse(raw);

      this.autoReconnect = parsed.autoReconnect ?? true;
      this.searchAllServers = parsed.searchAllServers ?? true;
      this.serverDirectory.setSearchAllServers(this.searchAllServers);
    }
  }

  authStatusKey(serverUrl: string): string {
    if (this.signalServerAuth.hasValidCredential(serverUrl)) {
      return 'settings.network.serverEndpoints.auth.authorized';
    }

    return 'settings.network.serverEndpoints.auth.needsSignIn';
  }

  async authorizeServer(serverUrl: string): Promise<void> {
    await this.signalServerAuthorize.navigateToAuthorize(serverUrl, '/settings');
  }

  dismissProvisionNotice(): void {
    this.provisionNoticeService.clear();
  }

  saveConnectionSettings(): void {
    localStorage.setItem(
      STORAGE_KEY_CONNECTION_SETTINGS,
      JSON.stringify({
        autoReconnect: this.autoReconnect,
        searchAllServers: this.searchAllServers
      })
    );

    this.serverDirectory.setSearchAllServers(this.searchAllServers);
  }
}
