import { Injectable } from '@angular/core';
import { STORAGE_KEY_NOTIFICATION_SETTINGS } from '../../../../core/constants';
import { jsonStorage } from '../../../../infrastructure/persistence/json-storage.service';
import { createDefaultNotificationSettings, type NotificationsSettings } from '../../domain/models/notification.model';

@Injectable({ providedIn: 'root' })
export class NotificationSettingsStorageService {
  private readonly storage = jsonStorage;

  load(): NotificationsSettings {
    const fallback = createDefaultNotificationSettings();
    const parsed = this.storage.read<Partial<NotificationsSettings> | null>(
      STORAGE_KEY_NOTIFICATION_SETTINGS,
      null
    );

    if (!parsed) {
      return fallback;
    }

    return {
      enabled: parsed.enabled ?? fallback.enabled,
      showPreview: parsed.showPreview ?? fallback.showPreview,
      respectBusyStatus: parsed.respectBusyStatus ?? fallback.respectBusyStatus,
      mutedRooms: normaliseBooleanRecord(parsed.mutedRooms),
      mutedChannels: normaliseNestedBooleanRecord(parsed.mutedChannels),
      roomBaselines: normaliseNumberRecord(parsed.roomBaselines),
      lastReadByChannel: normaliseNestedNumberRecord(parsed.lastReadByChannel)
    };
  }

  save(settings: NotificationsSettings): void {
    this.storage.write(STORAGE_KEY_NOTIFICATION_SETTINGS, settings);
  }
}

function normaliseBooleanRecord(value: unknown): Record<string, boolean> {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    return {};
  }

  return Object.fromEntries(
    Object.entries(value)
      .filter((entry): entry is [string, boolean] => typeof entry[1] === 'boolean')
  );
}

function normaliseNumberRecord(value: unknown): Record<string, number> {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    return {};
  }

  return Object.fromEntries(
    Object.entries(value)
      .filter((entry): entry is [string, number] => typeof entry[1] === 'number' && Number.isFinite(entry[1]))
  );
}

function normaliseNestedBooleanRecord(value: unknown): Record<string, Record<string, boolean>> {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    return {};
  }

  return Object.fromEntries(
    Object.entries(value)
      .map(([roomId, channels]) => [roomId, normaliseBooleanRecord(channels)])
  );
}

function normaliseNestedNumberRecord(value: unknown): Record<string, Record<string, number>> {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    return {};
  }

  return Object.fromEntries(
    Object.entries(value)
      .map(([roomId, channels]) => [roomId, normaliseNumberRecord(channels)])
  );
}
