// Voice settings dialog (SDD-097). Surfaces transmit mode, release
// tail, and the full P1 audio processing configuration:
//   - Noise suppression (NS)
//   - Echo cancellation (AEC3)
//   - Automatic gain control (AGC2)
//   - High-pass filter (HPF)
//   - VAD backend
//   - platform audio-processing mode selection where available

import 'dart:io' show Platform;

import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';

import '../l10n/generated/app_localizations.dart';
import 'audio_device_list_tile.dart';
import 'audio_output_tile.dart';
import 'audio_processing_config_state.dart';
import 'ptt_capability_badge.dart';
import 'talk_power_warning.dart';
import 'voice_platform.dart';
import 'voice_settings_controls.dart';
import '../src/rust/api.dart' as rust;

bool get _isAndroid {
  if (kIsWeb) return false;
  return Platform.isAndroid;
}

bool get _isIos {
  if (kIsWeb) return false;
  return Platform.isIOS;
}

bool get _isMacOS {
  if (kIsWeb) return false;
  return Platform.isMacOS;
}

bool get _isDesktopSileroVadHost {
  if (kIsWeb) return false;
  return Platform.isWindows || Platform.isLinux;
}

/// Result returned by [VoiceSettingsDialog].
class VoiceSettingsResult {
  const VoiceSettingsResult({
    required this.mode,
    required this.releaseTailMs,
    required this.bindKeyRequested,
    required this.audioConfig,
  });

  final rust.BridgeTransmitMode mode;
  final int releaseTailMs;
  final bool bindKeyRequested;
  final rust.BridgeAudioProcessingConfig audioConfig;
}

/// Voice + audio processing settings dialog.
class VoiceSettingsDialog extends StatefulWidget {
  const VoiceSettingsDialog({
    super.key,
    required this.initialMode,
    required this.initialReleaseTailMs,
    required this.initialAudioConfig,
    this.pttLevel = '',
    this.pttBackendId = '',
    this.pttBoundInputClass = '',
    this.talkPower,
    this.neededTalkPower,
    this.talkPowerGranted,
  });

  final rust.BridgeTransmitMode initialMode;
  final int initialReleaseTailMs;
  final rust.BridgeAudioProcessingConfig initialAudioConfig;
  final String pttLevel;
  final String pttBackendId;
  final String pttBoundInputClass;
  final int? talkPower;
  final int? neededTalkPower;
  final bool? talkPowerGranted;

  @override
  State<VoiceSettingsDialog> createState() => _VoiceSettingsDialogState();
}

class _VoiceSettingsDialogState extends State<VoiceSettingsDialog> {
  late rust.BridgeTransmitMode _mode;
  late double _releaseTail;

  late final AudioProcessingConfigState _audioProcessing;

  @override
  void initState() {
    super.initState();
    _mode = widget.initialMode;
    _releaseTail = widget.initialReleaseTailMs.clamp(0, 500).toDouble();

    _audioProcessing = AudioProcessingConfigState.fromConfig(
      widget.initialAudioConfig,
    );
  }

  rust.BridgeAudioProcessingConfig _buildConfig() {
    return _audioProcessing.buildConfig(
      base: widget.initialAudioConfig,
      isAndroid: _isAndroid,
    );
  }

  @override
  Widget build(BuildContext context) {
    final l10n = AppL10n.of(context);
    final theme = Theme.of(context);
    return AlertDialog(
      title: Text(l10n.voiceSettingsTitle),
      contentPadding: const EdgeInsets.fromLTRB(24, 16, 24, 0),
      content: SizedBox(
        width: 400,
        child: SingleChildScrollView(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // ── Transmit mode ──────────────────────────────────────
              VoiceSectionHeader(l10n.voiceModeLabel),
              SegmentedButton<rust.BridgeTransmitMode>(
                style: voiceSegmentedButtonStyle(theme),
                segments: transmitModeSegments,
                selected: {_mode},
                onSelectionChanged: (s) => setState(() => _mode = s.first),
              ),

              // ── PTT options ────────────────────────────────────────
              if (_mode == rust.BridgeTransmitMode.ptt) ...[
                const Divider(height: 24),
                if (!isTouchOnlyPttHost) ...[
                  OutlinedButton.icon(
                    icon: const Icon(Icons.keyboard),
                    label: Text(l10n.voiceBindKeyAction),
                    onPressed: () => Navigator.of(context).pop(
                      VoiceSettingsResult(
                        mode: _mode,
                        releaseTailMs: _releaseTail.round(),
                        bindKeyRequested: true,
                        audioConfig: _buildConfig(),
                      ),
                    ),
                  ),
                  const SizedBox(height: 8),
                ],
                Text(
                  l10n.voiceReleaseTailLabel,
                  style: theme.textTheme.titleSmall,
                ),
                Row(
                  children: [
                    Expanded(
                      child: Slider(
                        value: _releaseTail,
                        min: 0,
                        max: 500,
                        divisions: 20,
                        label:
                            '${_releaseTail.round()}${l10n.voiceReleaseTailHint}',
                        onChanged: (v) => setState(() => _releaseTail = v),
                      ),
                    ),
                    SizedBox(
                      width: 64,
                      child: Text(
                        '${_releaseTail.round()}${l10n.voiceReleaseTailHint}',
                        style: theme.textTheme.bodySmall,
                        textAlign: TextAlign.end,
                      ),
                    ),
                  ],
                ),
              ],

              // ── Audio processing ───────────────────────────────────
              const Divider(height: 24),
              const VoiceSectionHeader('Audio processing'),

              // Android HW/SW selector
              if (_isAndroid) ...[
                const VoiceSubHeader('Processing backend'),
                SegmentedButton<bool>(
                  style: voiceSegmentedButtonStyle(theme),
                  segments: androidProcessingSegments,
                  selected: {_audioProcessing.preferHardware},
                  onSelectionChanged: (s) =>
                      setState(() => _audioProcessing.preferHardware = s.first),
                ),
                const SizedBox(height: 4),
                Text(
                  _audioProcessing.preferHardware
                      ? 'Android hardware mode still falls back to WebRTC APM per stage when device effects are missing, so these controls remain available.'
                      : 'Android software mode applies the full WebRTC APM control set.',
                  style: theme.textTheme.bodySmall?.copyWith(
                    color: theme.colorScheme.onSurfaceVariant,
                  ),
                ),
                const SizedBox(height: 8),
              ],

              // DSP toggles
              const VoiceSubHeader('DSP stages'),
              if (_isIos) ...[
                Text(
                  'iOS uses Apple VoiceProcessingIO. WebRTC APM controls are '
                  'hidden here; only settings that still affect the shipping '
                  'iOS path are shown.',
                  style: theme.textTheme.bodySmall?.copyWith(
                    color: theme.colorScheme.onSurfaceVariant,
                  ),
                ),
                const SizedBox(height: 8),
              ],
              if (!_isIos &&
                  (!_isAndroid || androidShowsNsControl(_audioProcessing)))
                AudioProcessingToggleRow(
                  label: 'Noise suppression (NS)',
                  subtitle: 'Wiener filter · stationary noise',
                  value: _audioProcessing.nsEnabled,
                  onChanged: (v) =>
                      setState(() => _audioProcessing.nsEnabled = v),
                ),
              if (!_isIos &&
                  (!_isAndroid || androidShowsAecControl(_audioProcessing)))
                AudioProcessingToggleRow(
                  label: 'Echo cancellation (AEC3)',
                  subtitle: _isAndroid
                      ? (_audioProcessing.preferHardware
                            ? 'Prefers device/OS effect; WebRTC AEC3 fallback when binding is unavailable'
                            : 'WebRTC AEC3 · adaptive filter')
                      : (_isMacOS
                            ? 'Managed by platform VPIO'
                            : 'WebRTC AEC3 · adaptive filter'),
                  value: _isMacOS ? true : _audioProcessing.aecEnabled,
                  onChanged: _isMacOS
                      ? null
                      : (v) => setState(() => _audioProcessing.aecEnabled = v),
                ),
              if (!_isIos &&
                  (!_isAndroid || androidShowsAgcControl(_audioProcessing)))
                AudioProcessingToggleRow(
                  label: 'Auto gain control (AGC2)',
                  subtitle: 'RNN VAD-gated · -18 dBFS target',
                  value: _audioProcessing.agcEnabled,
                  onChanged: (v) =>
                      setState(() => _audioProcessing.agcEnabled = v),
                ),
              if (!_isAndroid || androidShowsHpfControl(_audioProcessing))
                AudioProcessingToggleRow(
                  label: 'High-pass filter (HPF)',
                  subtitle: '80 Hz Butterworth · DC removal',
                  value: _audioProcessing.hpfEnabled,
                  onChanged: (v) =>
                      setState(() => _audioProcessing.hpfEnabled = v),
                ),
              if (!_isIos &&
                  (!_isAndroid || androidShowsLimiterControl(_audioProcessing)))
                AudioProcessingToggleRow(
                  label: 'Peak limiter',
                  subtitle: '-1 dBFS soft-knee · 2 ms look-ahead',
                  value: _audioProcessing.limiterEnabled,
                  onChanged: (v) =>
                      setState(() => _audioProcessing.limiterEnabled = v),
                ),

              if (isTalkPowerBlocked(
                talkPower: widget.talkPower,
                neededTalkPower: widget.neededTalkPower,
                talkPowerGranted: widget.talkPowerGranted,
              )) ...[
                const SizedBox(height: 8),
                TalkPowerWarning(
                  talkPower: widget.talkPower,
                  neededTalkPower: widget.neededTalkPower,
                  talkPowerGranted: widget.talkPowerGranted,
                ),
              ],

              // ── VAD ────────────────────────────────────────────────
              const Divider(height: 24),
              const VoiceSectionHeader('Voice activity detection (VAD)'),

              const VoiceSubHeader('Backend'),
              SegmentedButton<rust.BridgeVadBackend>(
                style: voiceSegmentedButtonStyle(theme),
                segments: _isDesktopSileroVadHost
                    ? desktopVadBackendSegments
                    : vadBackendSegments,
                selected: {_audioProcessing.vadBackend},
                onSelectionChanged: (s) =>
                    setState(() => _audioProcessing.vadBackend = s.first),
              ),
              const SizedBox(height: 8),

              // ── PTT capability badge ────────────────────────────────
              if (_mode == rust.BridgeTransmitMode.ptt &&
                  widget.pttLevel.isNotEmpty) ...[
                const Divider(height: 24),
                const VoiceSectionHeader('PTT capability'),
                PttCapabilityBadge(
                  level: widget.pttLevel,
                  backendId: widget.pttBackendId,
                  boundInputClass: widget.pttBoundInputClass,
                ),
              ],

              // ── Audio output route picker (mobile only) ─────────────
              if (_isAndroid || _isIos) ...[
                const Divider(height: 24),
                const VoiceSectionHeader('Audio output'),
                const AudioOutputTile(),
              ],

              // ── Audio devices (desktop only, SRS-026) ──────────────
              if (!_isAndroid && !_isIos) ...[
                const Divider(height: 24),
                const VoiceSectionHeader('Audio devices'),
                const AudioDeviceListTile(
                  label: 'Input',
                  kind: AudioDeviceKind.input,
                ),
                const AudioDeviceListTile(
                  label: 'Output',
                  kind: AudioDeviceKind.output,
                ),
                const SizedBox(height: 8),
              ],

              // ── Debug ──────────────────────────────────────────────
              const Divider(height: 24),
              const VoiceSectionHeader('Debug'),
              AudioProcessingToggleRow(
                label: 'WAV dump',
                subtitle: 'Record raw/processed mic to temp dir',
                value: _audioProcessing.debugWavDump,
                onChanged: (v) =>
                    setState(() => _audioProcessing.debugWavDump = v),
              ),
              const SizedBox(height: 8),
            ],
          ),
        ),
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.of(context).pop(),
          child: Text(l10n.closeAction),
        ),
        FilledButton(
          onPressed: () => Navigator.of(context).pop(
            VoiceSettingsResult(
              mode: _mode,
              releaseTailMs: _releaseTail.round(),
              bindKeyRequested: false,
              audioConfig: _buildConfig(),
            ),
          ),
          child: Text(l10n.pttConfigureSaveAction),
        ),
      ],
    );
  }
}
