import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:plezy/widgets/app_icon.dart';
import 'package:material_symbols_icons/symbols.dart';
import '../../focus/dpad_navigator.dart';
import '../../focus/focusable_text_field.dart';
import '../../focus/key_event_utils.dart';
import '../../i18n/strings.g.dart';
import '../../mixins/controller_disposer_mixin.dart';
import '../../models/mpv_config_models.dart';
import '../../utils/dialogs.dart';
import '../../utils/snackbar_helper.dart';
import '../../mixins/settings_effect_mixin.dart';
import '../../services/settings_service.dart';
import '../../widgets/focused_scroll_scaffold.dart';
import '../../widgets/focusable_popup_menu_button.dart';
import '../../widgets/settings_builder.dart';

class MpvConfigScreen extends StatefulWidget {
  const MpvConfigScreen({super.key});

  @override
  State<MpvConfigScreen> createState() => _MpvConfigScreenState();
}

class _MpvConfigScreenState extends State<MpvConfigScreen> with SettingsEffectMixin, ControllerDisposerMixin {
  SettingsService get _settingsService => SettingsService.instanceOrNull!;

  late final TextEditingController _textController = createTextEditingController(
    text: _settingsService.read(SettingsService.mpvConfigText),
  );
  final _savePresetFocusNode = FocusNode();
  final _textFieldFocusNode = FocusNode();

  @override
  void initState() {
    super.initState();
    // Sync the editor when the pref is mutated externally (e.g. loadMpvPreset).
    // Skip when the listener fires for the same value the controller already
    // holds — avoids fighting user-typed text mid-edit.
    bindEffect<String>(SettingsService.mpvConfigText, (v) {
      if (_textController.text != v) _textController.text = v;
    }, fireImmediately: false);
  }

  @override
  void dispose() {
    _savePresetFocusNode.dispose();
    _textFieldFocusNode.dispose();
    super.dispose();
  }

  Future<void> _saveText() async {
    await _settingsService.write(SettingsService.mpvConfigText, _textController.text);
  }

  Future<void> _showSavePresetDialog() async {
    if (_textController.text.trim().isEmpty) return;

    final name = await showTextInputDialog(
      context,
      title: t.mpvConfig.saveAsPreset,
      labelText: t.mpvConfig.presetName,
      hintText: t.mpvConfig.presetNameHint,
    );

    if (name != null && name.trim().isNotEmpty) {
      await _settingsService.saveMpvPreset(name.trim(), _textController.text);
      if (mounted) showSuccessSnackBar(context, t.mpvConfig.presetSaved);
    }
  }

  Future<void> _loadPreset(MpvPreset preset) async {
    await _settingsService.loadMpvPreset(preset.name);
    // Controller text is updated reactively via the bindEffect above.
    if (mounted) showAppSnackBar(context, t.mpvConfig.presetLoaded);
  }

  Future<void> _deletePreset(MpvPreset preset) async {
    final confirmed = await showDeleteConfirmation(
      context,
      title: t.mpvConfig.deletePreset,
      message: t.mpvConfig.confirmDeletePreset,
    );
    if (!confirmed) return;
    await _settingsService.deleteMpvPreset(preset.name);
    if (mounted) showSuccessSnackBar(context, t.mpvConfig.presetDeleted);
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: (didPop, _) {
        if (didPop) return;
        if (BackKeyCoordinator.consumeIfHandled()) return;
        BackKeyUpSuppressor.suppressBackUntilKeyUp();
        if (_textFieldFocusNode.hasFocus && _savePresetFocusNode.canRequestFocus) {
          _savePresetFocusNode.requestFocus();
        } else {
          Navigator.pop(context);
        }
      },
      child: FocusedScrollScaffold(
        title: Text(t.screens.mpvConfig),
        slivers: [
          SliverPadding(
            padding: const EdgeInsets.all(16),
            sliver: SliverList(
              delegate: SliverChildListDelegate([
                _buildConfigEditor(),
                const SizedBox(height: 16),
                _buildPresetsCard(),
                const SizedBox(height: 24),
              ]),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildConfigEditor() {
    return Focus(
      canRequestFocus: false,
      onKeyEvent: (_, event) {
        // Back/Escape: move focus to the save preset button instead of exiting.
        // Suppress the KeyUp so it doesn't reach handleBackKeyNavigation
        // on the new focus chain after focus moves away from the text field.
        if (event.logicalKey.isBackKey) {
          if (!_savePresetFocusNode.canRequestFocus) {
            return KeyEventResult.ignored;
          }
          if (event is KeyDownEvent) {
            BackKeyUpSuppressor.suppressBackUntilKeyUp();
            _savePresetFocusNode.requestFocus();
          }
          return KeyEventResult.handled;
        }
        // We must consume Enter to prevent parent handlers from unfocusing,
        // but that also blocks Flutter's text editing shortcuts (which are
        // higher in the focus tree). So we manually insert newlines here.
        if (event.logicalKey == LogicalKeyboardKey.enter || event.logicalKey == LogicalKeyboardKey.numpadEnter) {
          if (event is KeyDownEvent || event is KeyRepeatEvent) {
            final sel = _textController.selection;
            if (sel.isValid) {
              final text = _textController.text;
              _textController.value = TextEditingValue(
                text: text.replaceRange(sel.start, sel.end, '\n'),
                selection: TextSelection.collapsed(offset: sel.start + 1),
              );
              _saveText();
            }
          }
          return KeyEventResult.handled;
        }
        if (event.logicalKey.isSelectKey) {
          return KeyEventResult.handled;
        }
        if (event.logicalKey.isDownKey && event.isActionable) {
          final sel = _textController.selection;
          if (sel.isValid && _textController.text.indexOf('\n', sel.extentOffset) == -1) {
            _savePresetFocusNode.requestFocus();
            return KeyEventResult.handled;
          }
        }
        return KeyEventResult.ignored;
      },
      child: FocusableTextField(
        controller: _textController,
        focusNode: _textFieldFocusNode,
        keyboardType: TextInputType.multiline,
        maxLines: null,
        minLines: 12,
        decoration: InputDecoration(
          hintText: t.mpvConfig.configPlaceholder,
          border: const OutlineInputBorder(),
          contentPadding: const EdgeInsets.all(12),
        ),
        style: const TextStyle(fontFamily: 'monospace', fontSize: 13),
        onChanged: (_) => _saveText(),
      ),
    );
  }

  Widget _buildPresetsCard() {
    return SettingValueBuilder<List<MpvPreset>>(
      pref: SettingsService.mpvPresets,
      builder: (context, presets, _) => Card(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Padding(
              padding: const EdgeInsets.all(16),
              child: Text(
                t.mpvConfig.presets,
                style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold),
              ),
            ),
            ListTile(
              focusNode: _savePresetFocusNode,
              leading: const AppIcon(Symbols.save_rounded, fill: 1),
              title: Text(t.mpvConfig.saveAsPreset),
              enabled: _textController.text.trim().isNotEmpty,
              onTap: _textController.text.trim().isNotEmpty ? _showSavePresetDialog : null,
            ),
            if (presets.isNotEmpty) ...[
              const Divider(),
              ...presets.map(
                (preset) => ListTile(
                  leading: const AppIcon(Symbols.folder_rounded, fill: 1),
                  title: Text(preset.name),
                  trailing: FocusablePopupMenuButton<String>(
                    icon: const AppIcon(Symbols.more_vert_rounded, fill: 1),
                    onSelected: (value) {
                      if (value == 'load') {
                        _loadPreset(preset);
                      } else if (value == 'delete') {
                        _deletePreset(preset);
                      }
                    },
                    itemBuilder: (context) => [
                      PopupMenuItem(value: 'load', child: Text(t.mpvConfig.loadPreset)),
                      PopupMenuItem(value: 'delete', child: Text(t.mpvConfig.deletePreset)),
                    ],
                  ),
                  onTap: () => _loadPreset(preset),
                ),
              ),
            ] else
              Padding(
                padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
                child: Text(
                  t.mpvConfig.noPresets,
                  style: Theme.of(
                    context,
                  ).textTheme.bodyMedium?.copyWith(color: Theme.of(context).colorScheme.onSurfaceVariant),
                ),
              ),
          ],
        ),
      ),
    );
  }
}
