/* eslint-disable @typescript-eslint/member-ordering */
import {
  Component,
  inject,
  signal,
  OnInit,
  computed
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Router } from '@angular/router';
import { NgIcon, provideIcons } from '@ng-icons/core';
import {
  lucideServer,
  lucidePlus,
  lucideTrash2,
  lucideCheck,
  lucideX,
  lucideSettings,
  lucideRefreshCw,
  lucideGlobe,
  lucideArrowLeft,
  lucideAudioLines,
  lucidePackage
} from '@ng-icons/lucide';

import { ServerDirectoryFacade } from '../../domains/server-directory';
import { VoiceConnectionFacade } from '../../domains/voice-connection';
import { NotificationAudioService, AppSound } from '../../core/services/notification-audio.service';
import { STORAGE_KEY_CONNECTION_SETTINGS, STORAGE_KEY_VOICE_SETTINGS } from '../../core/constants';
import { APP_TRANSLATE_IMPORTS, AppI18nService } from '../../core/i18n';
import { SelectOnFocusDirective, SubmitOnEnterDirective } from '../../shared/directives';

@Component({
  selector: 'app-settings',
  standalone: true,
  imports: [
    CommonModule,
    FormsModule,
    NgIcon,
    SelectOnFocusDirective,
    SubmitOnEnterDirective,
    ...APP_TRANSLATE_IMPORTS
  ],
  viewProviders: [
    provideIcons({
      lucideServer,
      lucidePlus,
      lucideTrash2,
      lucideCheck,
      lucideX,
      lucideSettings,
      lucideRefreshCw,
      lucideGlobe,
      lucideArrowLeft,
      lucideAudioLines,
      lucidePackage
    })
  ],
  templateUrl: './settings.component.html'
})
/**
 * Settings page for managing signaling servers and connection preferences.
 */
export class SettingsComponent implements OnInit {
  private serverDirectory = inject(ServerDirectoryFacade);
  private voiceConnection = inject(VoiceConnectionFacade);
  private router = inject(Router);
  private readonly appI18n = inject(AppI18nService);
  audioService = inject(NotificationAudioService);

  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;
  noiseReduction = true;

  /** Load persisted connection settings on component init. */
  ngOnInit(): void {
    this.loadConnectionSettings();
    this.loadVoiceSettings();
  }

  /** Add a new signaling server after URL validation and duplicate checking. */
  addServer(): void {
    this.addError.set(null);

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

    // Check for duplicates
    if (this.servers().some((server) => server.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(/\/$/, '') // Remove trailing slash
    });

    // Clear form
    this.newServerName = '';
    this.newServerUrl = '';

    // Test the new server
    const servers = this.servers();
    const newServer = servers[servers.length - 1];

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

  /** Remove a signaling server by its ID. */
  removeServer(id: string): void {
    this.serverDirectory.removeServer(id);
  }

  /** Set the active signaling server used for connections. */
  setActiveServer(id: string): void {
    this.serverDirectory.setActiveServer(id);
  }

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

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

  /** Test connectivity to all configured servers. */
  async testAllServers(): Promise<void> {
    this.isTesting.set(true);
    await this.serverDirectory.testAllServers();
    this.isTesting.set(false);
  }

  /** Load connection settings (auto-reconnect, search scope) from localStorage. */
  loadConnectionSettings(): void {
    const settings = localStorage.getItem(STORAGE_KEY_CONNECTION_SETTINGS);

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

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

  /** Persist current connection settings to localStorage. */
  saveConnectionSettings(): void {
    localStorage.setItem(
      STORAGE_KEY_CONNECTION_SETTINGS,
      JSON.stringify({
        autoReconnect: this.autoReconnect,
        searchAllServers: this.searchAllServers
      })
    );

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

  /** Navigate back to the main page. */
  goBack(): void {
    this.router.navigate(['/']);
  }

  openPluginStore(): void {
    const returnUrl = this.router.url.startsWith('/plugin-store') ? '/dashboard' : this.router.url;

    void this.router.navigate(['/plugin-store'], { queryParams: { returnUrl } });
  }

  /** Load voice settings (noise reduction) from localStorage. */
  loadVoiceSettings(): void {
    const settings = localStorage.getItem(STORAGE_KEY_VOICE_SETTINGS);

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

      this.noiseReduction = parsed.noiseReduction ?? false;
    }

    // Sync the live WebRTC state with the persisted preference
    if (this.noiseReduction !== this.voiceConnection.isNoiseReductionEnabled()) {
      this.voiceConnection.toggleNoiseReduction(this.noiseReduction);
    }
  }

  /** Called when the notification volume slider changes. */
  onNotificationVolumeChange(value: number): void {
    this.audioService.setNotificationVolume(value);
  }

  /** Play a preview of the notification sound at the current volume. */
  previewNotificationSound(): void {
    this.audioService.play(AppSound.Notification);
  }

  /** Persist noise reduction preference (merged into existing voice settings) and apply immediately. */
  async saveVoiceSettings(): Promise<void> {
    // Merge into existing voice settings so we don't overwrite device/volume prefs
    let existing: Record<string, unknown> = {};

    try {
      const raw = localStorage.getItem(STORAGE_KEY_VOICE_SETTINGS);

      if (raw)
        existing = JSON.parse(raw);
    } catch {}

    localStorage.setItem(
      STORAGE_KEY_VOICE_SETTINGS,
      JSON.stringify({ ...existing,
        noiseReduction: this.noiseReduction })
    );

    await this.voiceConnection.toggleNoiseReduction(this.noiseReduction);
  }
}
