import { STORAGE_KEY_VOICE_SETTINGS } from '../../../../core/constants';
import {
  DEFAULT_LATENCY_PROFILE,
  DEFAULT_SCREEN_SHARE_QUALITY,
  LATENCY_PROFILES,
  SCREEN_SHARE_QUALITIES,
  type LatencyProfile,
  type ScreenShareQuality
} from '../../../../shared-kernel';

export interface VoiceSettings {
  inputDevice: string;
  outputDevice: string;
  inputVolume: number;
  outputVolume: number;
  audioBitrate: number;
  latencyProfile: LatencyProfile;
  includeSystemAudio: boolean;
  noiseReduction: boolean;
  screenShareQuality: ScreenShareQuality;
  askScreenShareQuality: boolean;
}

export const DEFAULT_VOICE_SETTINGS: VoiceSettings = {
  inputDevice: '',
  outputDevice: '',
  inputVolume: 100,
  outputVolume: 100,
  audioBitrate: 96,
  latencyProfile: DEFAULT_LATENCY_PROFILE,
  includeSystemAudio: false,
  noiseReduction: true,
  screenShareQuality: DEFAULT_SCREEN_SHARE_QUALITY,
  askScreenShareQuality: true
};

export function loadVoiceSettingsFromStorage(): VoiceSettings {
  try {
    const raw = localStorage.getItem(STORAGE_KEY_VOICE_SETTINGS);

    if (!raw)
      return { ...DEFAULT_VOICE_SETTINGS };

    return normaliseVoiceSettings(JSON.parse(raw) as Partial<VoiceSettings>);
  } catch {
    return { ...DEFAULT_VOICE_SETTINGS };
  }
}

export function saveVoiceSettingsToStorage(patch: Partial<VoiceSettings>): VoiceSettings {
  const nextSettings = normaliseVoiceSettings({
    ...loadVoiceSettingsFromStorage(),
    ...patch
  });

  try {
    localStorage.setItem(STORAGE_KEY_VOICE_SETTINGS, JSON.stringify(nextSettings));
  } catch {}

  return nextSettings;
}

function normaliseVoiceSettings(raw: Partial<VoiceSettings>): VoiceSettings {
  return {
    inputDevice: typeof raw.inputDevice === 'string' ? raw.inputDevice : DEFAULT_VOICE_SETTINGS.inputDevice,
    outputDevice: typeof raw.outputDevice === 'string' ? raw.outputDevice : DEFAULT_VOICE_SETTINGS.outputDevice,
    inputVolume: clampNumber(raw.inputVolume, 0, 100, DEFAULT_VOICE_SETTINGS.inputVolume),
    outputVolume: clampNumber(raw.outputVolume, 0, 200, DEFAULT_VOICE_SETTINGS.outputVolume),
    audioBitrate: clampNumber(raw.audioBitrate, 32, 256, DEFAULT_VOICE_SETTINGS.audioBitrate),
    latencyProfile: LATENCY_PROFILES.includes(raw.latencyProfile as LatencyProfile)
      ? raw.latencyProfile as LatencyProfile
      : DEFAULT_VOICE_SETTINGS.latencyProfile,
    includeSystemAudio: typeof raw.includeSystemAudio === 'boolean'
      ? raw.includeSystemAudio
      : DEFAULT_VOICE_SETTINGS.includeSystemAudio,
    noiseReduction: typeof raw.noiseReduction === 'boolean'
      ? raw.noiseReduction
      : DEFAULT_VOICE_SETTINGS.noiseReduction,
    screenShareQuality: SCREEN_SHARE_QUALITIES.includes(raw.screenShareQuality as ScreenShareQuality)
      ? raw.screenShareQuality as ScreenShareQuality
      : DEFAULT_VOICE_SETTINGS.screenShareQuality,
    askScreenShareQuality: typeof raw.askScreenShareQuality === 'boolean'
      ? raw.askScreenShareQuality
      : DEFAULT_VOICE_SETTINGS.askScreenShareQuality
  };
}

function clampNumber(
  value: unknown,
  min: number,
  max: number,
  fallback: number
): number {
  if (typeof value !== 'number' || Number.isNaN(value)) {
    return fallback;
  }

  return Math.max(min, Math.min(max, value));
}
