import {
  Injectable,
  signal,
  computed,
  type Signal
} from '@angular/core';
import { STORAGE_KEY_ICE_SERVERS } from '../../core/constants';
import { ICE_SERVERS } from './realtime.constants';

export interface IceServerEntry {
  id: string;
  type: 'stun' | 'turn';
  urls: string;
  username?: string;
  credential?: string;
}

const DEFAULT_ENTRIES: IceServerEntry[] = ICE_SERVERS.map((server, index) => ({
  id: `default-stun-${index}`,
  type: 'stun' as const,
  urls: Array.isArray(server.urls) ? server.urls[0] : server.urls
}));

@Injectable({ providedIn: 'root' })
export class IceServerSettingsService {
  readonly entries: Signal<IceServerEntry[]>;
  readonly rtcIceServers: Signal<RTCIceServer[]>;

  private readonly _entries = signal<IceServerEntry[]>(this.load());

  constructor() {
    this.entries = this._entries.asReadonly();
    this.rtcIceServers = computed<RTCIceServer[]>(() =>
      this._entries().map((entry) => {
        if (entry.type === 'turn') {
          return {
            urls: entry.urls,
            username: entry.username ?? '',
            credential: entry.credential ?? ''
          };
        }

        return { urls: entry.urls };
      })
    );
  }

  addEntry(entry: Omit<IceServerEntry, 'id'>): void {
    const id = `${entry.type}-${Date.now()}-${Math.random().toString(36)
      .slice(2, 8)}`;
    const updated = [...this._entries(), { ...entry, id }];

    this._entries.set(updated);
    this.save(updated);
  }

  removeEntry(id: string): void {
    const updated = this._entries().filter((entry) => entry.id !== id);

    this._entries.set(updated);
    this.save(updated);
  }

  updateEntry(id: string, changes: Partial<Omit<IceServerEntry, 'id'>>): void {
    const updated = this._entries().map((entry) =>
      entry.id === id ? { ...entry, ...changes } : entry
    );

    this._entries.set(updated);
    this.save(updated);
  }

  moveEntry(fromIndex: number, toIndex: number): void {
    const entries = [...this._entries()];

    if (fromIndex < 0 || fromIndex >= entries.length || toIndex < 0 || toIndex >= entries.length) {
      return;
    }

    const [moved] = entries.splice(fromIndex, 1);

    entries.splice(toIndex, 0, moved);
    this._entries.set(entries);
    this.save(entries);
  }

  restoreDefaults(): void {
    this._entries.set([...DEFAULT_ENTRIES]);
    this.save(DEFAULT_ENTRIES);
  }

  private load(): IceServerEntry[] {
    try {
      const raw = localStorage.getItem(STORAGE_KEY_ICE_SERVERS);

      if (!raw) {
        return [...DEFAULT_ENTRIES];
      }

      const parsed = JSON.parse(raw);

      if (!Array.isArray(parsed) || parsed.length === 0) {
        return [...DEFAULT_ENTRIES];
      }

      return parsed.filter(
        (entry: unknown): entry is IceServerEntry =>
          typeof entry === 'object'
          && entry !== null
          && typeof (entry as IceServerEntry).id === 'string'
          && ((entry as IceServerEntry).type === 'stun' || (entry as IceServerEntry).type === 'turn')
          && typeof (entry as IceServerEntry).urls === 'string'
      );
    } catch {
      return [...DEFAULT_ENTRIES];
    }
  }

  private save(entries: IceServerEntry[]): void {
    localStorage.setItem(STORAGE_KEY_ICE_SERVERS, JSON.stringify(entries));
  }
}
