import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:plezy/widgets/app_icon.dart';

import '../../widgets/dialog_action_button.dart';
import '../../focus/focusable_button.dart';
import '../../focus/focusable_text_field.dart';
import '../../i18n/strings.g.dart';
import '../../models/external_player_models.dart';
import '../../services/settings_service.dart';
import '../../utils/dialogs.dart';
import '../../widgets/expressive_button_group.dart';
import '../../widgets/focusable_list_tile.dart';
import '../../widgets/setting_tile.dart';
import '../../widgets/settings_builder.dart';
import '../../widgets/settings_page.dart';
import '../../widgets/settings_section.dart';

class ExternalPlayerScreen extends StatelessWidget {
  const ExternalPlayerScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return SettingsPage(
      title: Text(t.externalPlayer.title),
      children: [
        SettingsGroup(
          children: [
            SettingSwitchTile(
              pref: SettingsService.useExternalPlayer,
              icon: Symbols.open_in_new_rounded,
              title: t.externalPlayer.useExternalPlayer,
              subtitle: t.externalPlayer.useExternalPlayerDescription,
            ),
          ],
        ),
        SettingsBuilder(
          prefs: [
            SettingsService.useExternalPlayer,
            SettingsService.selectedExternalPlayer,
            SettingsService.customExternalPlayers,
          ],
          builder: (context) {
            final svc = SettingsService.instance;
            if (!svc.read(SettingsService.useExternalPlayer)) return const SizedBox.shrink();
            final selected = svc.read(SettingsService.selectedExternalPlayer);
            final custom = svc.read(SettingsService.customExternalPlayers);
            return Column(
              children: [
                FutureBuilder<List<ExternalPlayer>>(
                  future: KnownPlayers.getForCurrentPlatform(),
                  builder: (context, snapshot) {
                    final detected = snapshot.data;
                    if (detected == null) return const SizedBox.shrink();
                    return SettingsGroup(
                      title: t.externalPlayer.selectPlayer,
                      children: [
                        for (final p in _withSelected(detected, selected.id))
                          _PlayerTile(player: p, selectedId: selected.id),
                      ],
                    );
                  },
                ),
                SettingsGroup(
                  title: t.externalPlayer.customPlayers,
                  children: [
                    for (final p in custom) _PlayerTile(player: p, selectedId: selected.id, isCustom: true),
                    FocusableListTile(
                      leading: const AppIcon(Symbols.add_rounded, fill: 1),
                      title: Text(t.externalPlayer.addCustomPlayer),
                      onTap: () => _showAddCustomPlayerDialog(context),
                    ),
                  ],
                ),
              ],
            );
          },
        ),
        const SizedBox(height: 24),
      ],
    );
  }
}

/// Keeps the current choice on screen when detection missed it, so a false
/// negative cannot leave the list with nothing selected.
List<ExternalPlayer> _withSelected(List<ExternalPlayer> detected, String selectedId) {
  if (detected.any((p) => p.id == selectedId)) return detected;
  final selected = KnownPlayers.findById(selectedId);
  if (selected == null || !selected.isAvailable) return detected;
  return [...detected, selected];
}

class _PlayerTile extends StatelessWidget {
  final ExternalPlayer player;
  final String selectedId;
  final bool isCustom;

  const _PlayerTile({required this.player, required this.selectedId, this.isCustom = false});

  @override
  Widget build(BuildContext context) {
    final isSelected = selectedId == player.id;
    final svc = SettingsService.instance;

    Widget leading;
    if (player.iconAsset != null) {
      leading = ClipRRect(
        borderRadius: const BorderRadius.all(Radius.circular(6)),
        child: player.iconAsset!.endsWith('.svg')
            ? SvgPicture.asset(player.iconAsset!, width: 32, height: 32)
            : Image.asset(
                player.iconAsset!,
                width: 32,
                height: 32,
                errorBuilder: (_, _, _) => const AppIcon(Symbols.play_circle_rounded, fill: 1, size: 32),
              ),
      );
    } else if (player.id == 'system_default') {
      leading = const AppIcon(Symbols.open_in_new_rounded, fill: 1, size: 32);
    } else {
      leading = const AppIcon(Symbols.play_circle_rounded, fill: 1, size: 32);
    }

    return FocusableListTile(
      leading: leading,
      title: Text(player.id == 'system_default' ? t.externalPlayer.systemDefault : player.name),
      trailing: Row(
        mainAxisSize: .min,
        children: [
          if (isCustom)
            FocusableButton(
              onPressed: () => svc.removeCustomExternalPlayer(player.id),
              autoScroll: false,
              child: IconButton(
                icon: const AppIcon(Symbols.delete_rounded, fill: 1, size: 20),
                onPressed: () => svc.removeCustomExternalPlayer(player.id),
              ),
            ),
          AppIcon(
            isSelected ? Symbols.radio_button_checked_rounded : Symbols.radio_button_unchecked_rounded,
            fill: 1,
            color: isSelected ? Theme.of(context).colorScheme.primary : null,
          ),
        ],
      ),
      onTap: () => svc.write(SettingsService.selectedExternalPlayer, player),
    );
  }
}

typedef _CustomPlayerDialogResult = ({String name, String value, CustomPlayerType type});

Future<void> _showAddCustomPlayerDialog(BuildContext context) async {
  final result = await showScopedDialog<_CustomPlayerDialogResult>(
    context: context,
    builder: (_) => const _AddCustomPlayerDialog(),
  );
  if (result == null) return;

  final id = 'custom_${DateTime.now().millisecondsSinceEpoch}';
  final newPlayer = ExternalPlayer.custom(id: id, name: result.name, value: result.value, type: result.type);

  final svc = SettingsService.instance;
  await svc.write(SettingsService.customExternalPlayers, [
    ...svc.read(SettingsService.customExternalPlayers),
    newPlayer,
  ]);
}

class _AddCustomPlayerDialog extends StatefulWidget {
  const _AddCustomPlayerDialog();

  @override
  State<_AddCustomPlayerDialog> createState() => _AddCustomPlayerDialogState();
}

class _AddCustomPlayerDialogState extends State<_AddCustomPlayerDialog> {
  final _nameController = TextEditingController();
  final _valueController = TextEditingController();
  final _valueFocusNode = FocusNode(debugLabel: 'CustomExternalPlayerValue');
  final _saveFocusNode = FocusNode(debugLabel: 'CustomExternalPlayerSave');
  CustomPlayerType _selectedType = CustomPlayerType.command;

  @override
  void dispose() {
    _valueFocusNode.dispose();
    _saveFocusNode.dispose();
    _nameController.dispose();
    _valueController.dispose();
    super.dispose();
  }

  void _submit() {
    final name = _nameController.text.trim();
    final value = _valueController.text.trim();
    if (name.isEmpty || value.isEmpty) return;
    Navigator.pop(context, (name: name, value: value, type: _selectedType));
  }

  ({String label, String hint}) get _valueFieldInfo {
    if (_selectedType == CustomPlayerType.urlScheme) {
      return (label: t.externalPlayer.playerUrlScheme, hint: 'myplayer://play?url=');
    }
    if (Platform.isAndroid) {
      return (label: t.externalPlayer.playerPackage, hint: 'com.example.player');
    }
    return (label: t.externalPlayer.playerCommand, hint: Platform.isMacOS ? 'mpv' : '/usr/bin/player');
  }

  @override
  Widget build(BuildContext context) {
    final (:label, :hint) = _valueFieldInfo;
    return AlertDialog(
      title: Text(t.externalPlayer.addCustomPlayer),
      content: SizedBox(
        width: 300,
        child: Column(
          mainAxisSize: .min,
          children: [
            FocusableTextField(
              controller: _nameController,
              decoration: InputDecoration(
                labelText: t.externalPlayer.playerName,
                hintText: t.externalPlayer.playerNameHint,
              ),
              autofocus: true,
              textInputAction: TextInputAction.next,
              onSubmitted: (_) => _valueFocusNode.requestFocus(),
            ),
            const SizedBox(height: 16),
            ExpressiveButtonGroup<CustomPlayerType>(
              segments: [
                ButtonSegment(
                  value: CustomPlayerType.command,
                  label: Text(Platform.isAndroid ? t.externalPlayer.playerPackage : t.externalPlayer.playerCommand),
                ),
                ButtonSegment(value: CustomPlayerType.urlScheme, label: Text(t.externalPlayer.playerUrlScheme)),
              ],
              selected: _selectedType,
              onChanged: (value) => setState(() => _selectedType = value),
            ),
            const SizedBox(height: 16),
            FocusableTextField(
              controller: _valueController,
              focusNode: _valueFocusNode,
              decoration: InputDecoration(labelText: label, hintText: hint),
              textInputAction: TextInputAction.done,
              onSubmitted: (_) => _saveFocusNode.requestFocus(),
            ),
          ],
        ),
      ),
      actions: [
        DialogActionButton(onPressed: () => Navigator.pop(context), label: t.common.cancel),
        DialogActionButton(focusNode: _saveFocusNode, onPressed: _submit, label: t.common.save, isPrimary: true),
      ],
    );
  }
}
