import 'dart:async';

import 'package:flutter/material.dart';
import 'package:forui/forui.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../../core/contracts/danmaku.dart';
import '../../../providers/danmaku_settings_provider.dart';
import '../../../shared/constants/breakpoints.dart';
import '../../../shared/theme/app_theme_scope.dart';
import '../../../shared/theme/app_theme.dart';

String danmakuSourcesSummary(List<DanmakuSource> sources) {
  if (sources.isEmpty) return '未配置';
  final enabled = sources.where((s) => s.enabled).length;
  if (enabled == 0) return '已配置 ${sources.length} 个，全部停用';
  final first = sources.firstWhere(
    (s) => s.enabled,
    orElse: () => sources.first,
  );
  return '$enabled/${sources.length} 个启用，优先：${first.displayName}';
}

void showDanmakuSourcesDialog(
  BuildContext context,
  List<DanmakuSource> sources,
) {
  final isCompact = MediaQuery.sizeOf(context).width < Breakpoints.compact;
  if (isCompact) {
    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      backgroundColor: Colors.transparent,
      builder: (_) => _DanmakuSourcesSheet(initialSources: sources),
    );
  } else {
    showFSheet<void>(
      context: context,
      side: FLayout.rtl,
      mainAxisMaxRatio: 0.42,
      draggable: false,
      builder: (_) => AppThemeScope(
        child: _DanmakuSourcesDesktopSheet(initialSources: sources),
      ),
    );
  }
}

mixin _DanmakuSourcesLogic<T extends ConsumerStatefulWidget>
    on ConsumerState<T> {
  late List<DanmakuSource> sources;

  void initSources(List<DanmakuSource> initial) {
    sources = List.of(initial);
  }

  Future<void> persist(List<DanmakuSource> next) async {
    final normalized = await ref
        .read(danmakuSettingsProvider.notifier)
        .setSources(next);
    if (!mounted) return;
    setState(() => sources = normalized);
  }

  Future<void> showEditDialog(DanmakuSource? source) async {
    final nameCtrl = TextEditingController(text: source?.name ?? '');
    final urlCtrl = TextEditingController(text: source?.url ?? '');
    try {
      final saved = await showFDialog<DanmakuSource>(
        context: context,
        builder: (ctx, _, animation) => AppThemeScope(
          child: FDialog.adaptive(
            animation: animation,
            title: Text(source == null ? '添加弹幕源' : '编辑弹幕源'),
            body: SizedBox(
              width: 420,
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  TextField(
                    controller: nameCtrl,
                    decoration: const InputDecoration(
                      labelText: '名称',
                      hintText: '例如：主源、备用源',
                      isDense: true,
                    ),
                  ),
                  const SizedBox(height: 12),
                  TextField(
                    controller: urlCtrl,
                    autofocus: source == null,
                    decoration: const InputDecoration(
                      labelText: '服务地址',
                      hintText: 'http://localhost:8080',
                      isDense: true,
                    ),
                  ),
                ],
              ),
            ),
            actions: [
              FButton(
                onPress: () {
                  final url = urlCtrl.text.trim();
                  if (url.isEmpty) return;
                  final id = source?.id.isNotEmpty == true
                      ? source!.id
                      : 'src_${url.hashCode.toUnsigned(32).toRadixString(16)}';
                  Navigator.pop(
                    ctx,
                    DanmakuSource(
                      id: id,
                      name: nameCtrl.text.trim(),
                      url: url,
                      enabled: source?.enabled ?? true,
                    ),
                  );
                },
                child: const Text('保存'),
              ),
              FButton(
                onPress: () => Navigator.pop(ctx),
                variant: FButtonVariant.outline,
                child: const Text('取消'),
              ),
            ],
          ),
        ),
      );
      if (saved == null) return;

      final existing = sources.indexWhere((s) => s.id == saved.id);
      final next = [...sources];
      if (existing >= 0) {
        next[existing] = saved;
      } else {
        next.add(saved);
      }
      await persist(next);
    } finally {
      nameCtrl.dispose();
      urlCtrl.dispose();
    }
  }

  Future<void> removeSource(DanmakuSource source) async {
    await persist(sources.where((s) => s.id != source.id).toList());
  }

  Future<void> toggleSource(DanmakuSource source, bool enabled) async {
    await persist(
      sources
          .map((s) => s.id == source.id ? s.copyWith(enabled: enabled) : s)
          .toList(),
    );
  }

  Future<void> reorderSource(int oldIndex, int newIndex) async {
    final next = [...sources];
    if (newIndex > oldIndex) newIndex -= 1;
    final item = next.removeAt(oldIndex);
    next.insert(newIndex, item);
    await persist(next);
  }
}

class _DanmakuSourcesSheet extends ConsumerStatefulWidget {
  final List<DanmakuSource> initialSources;

  const _DanmakuSourcesSheet({required this.initialSources});

  @override
  ConsumerState<_DanmakuSourcesSheet> createState() =>
      _DanmakuSourcesSheetState();
}

class _DanmakuSourcesSheetState extends ConsumerState<_DanmakuSourcesSheet>
    with _DanmakuSourcesLogic<_DanmakuSourcesSheet> {
  bool _editing = false;

  @override
  void initState() {
    super.initState();
    initSources(widget.initialSources);
  }

  @override
  Future<void> persist(List<DanmakuSource> next) async {
    await super.persist(next);
    if (mounted && sources.isEmpty && _editing) {
      setState(() => _editing = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final tokens = context.appTokens;

    return Container(
      constraints: BoxConstraints(
        maxHeight: MediaQuery.sizeOf(context).height * 0.7,
      ),
      decoration: BoxDecoration(
        color: theme.colorScheme.surface,
        borderRadius: const BorderRadius.vertical(top: Radius.circular(20)),
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Padding(
            padding: const EdgeInsets.fromLTRB(20, 20, 8, 0),
            child: Row(
              children: [
                Text(
                  '弹幕源',
                  style: theme.textTheme.titleMedium?.copyWith(
                    fontWeight: FontWeight.w700,
                  ),
                ),
                const Spacer(),
                if (sources.isNotEmpty)
                  TextButton(
                    onPressed: () => setState(() => _editing = !_editing),
                    child: Text(_editing ? '完成' : '编辑'),
                  ),
              ],
            ),
          ),

          Padding(
            padding: const EdgeInsets.fromLTRB(20, 4, 20, 12),
            child: Align(
              alignment: Alignment.centerLeft,
              child: Text(
                '按顺序自动匹配；启用的源会聚合显示候选，选中后从对应源加载弹幕。',
                style: TextStyle(
                  fontSize: 13,
                  color: theme.colorScheme.onSurfaceVariant,
                ),
              ),
            ),
          ),

          if (sources.isNotEmpty)
            Flexible(
              child: _editing
                  ? ReorderableListView.builder(
                      shrinkWrap: true,
                      buildDefaultDragHandles: false,
                      itemCount: sources.length,
                      onReorder: (oldIdx, newIdx) =>
                          unawaited(reorderSource(oldIdx, newIdx)),
                      itemBuilder: (context, index) {
                        final source = sources[index];
                        return _DanmakuEditRow(
                          key: ValueKey(source.id),
                          source: source,
                          index: index,
                          onDelete: () => unawaited(removeSource(source)),
                          onEdit: () => unawaited(showEditDialog(source)),
                        );
                      },
                    )
                  : ListView.builder(
                      shrinkWrap: true,
                      itemCount: sources.length,
                      itemBuilder: (context, index) {
                        final source = sources[index];
                        final hasName = source.name.trim().isNotEmpty;
                        return InkWell(
                          onTap: () => unawaited(showEditDialog(source)),
                          child: Padding(
                            padding: const EdgeInsets.symmetric(
                              horizontal: 20,
                              vertical: 10,
                            ),
                            child: Row(
                              children: [
                                Expanded(
                                  child: Column(
                                    crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                    children: [
                                      Text(
                                        hasName
                                            ? source.name.trim()
                                            : source.url,
                                        style: theme.textTheme.bodyMedium
                                            ?.copyWith(
                                              fontWeight: FontWeight.w500,
                                            ),
                                        maxLines: 1,
                                        overflow: TextOverflow.ellipsis,
                                      ),
                                      if (hasName)
                                        Text(
                                          source.url,
                                          style: theme.textTheme.bodySmall
                                              ?.copyWith(
                                                color: tokens.mutedForeground,
                                              ),
                                          maxLines: 1,
                                          overflow: TextOverflow.ellipsis,
                                        ),
                                    ],
                                  ),
                                ),
                                FSwitch(
                                  value: source.enabled,
                                  onChange: (v) =>
                                      unawaited(toggleSource(source, v)),
                                ),
                              ],
                            ),
                          ),
                        );
                      },
                    ),
            ),

          Padding(
            padding: EdgeInsets.fromLTRB(
              8,
              4,
              8,
              MediaQuery.paddingOf(context).bottom + 16,
            ),
            child: SizedBox(
              width: double.infinity,
              child: TextButton.icon(
                onPressed: () => unawaited(showEditDialog(null)),
                icon: const Icon(Icons.add, size: 16),
                label: const Text('添加弹幕源'),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _DanmakuEditRow extends StatefulWidget {
  final DanmakuSource source;
  final int index;
  final VoidCallback onDelete;
  final VoidCallback onEdit;

  const _DanmakuEditRow({
    required super.key,
    required this.source,
    required this.index,
    required this.onDelete,
    required this.onEdit,
  });

  @override
  State<_DanmakuEditRow> createState() => _DanmakuEditRowState();
}

class _DanmakuEditRowState extends State<_DanmakuEditRow>
    with SingleTickerProviderStateMixin {
  static const _deleteWidth = 72.0;

  late final AnimationController _controller;
  late final Animation<Offset> _slideAnim;
  bool _expanded = false;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 250),
    );
    _slideAnim = Tween<Offset>(
      begin: Offset.zero,
      end: const Offset(-0.2, 0),
    ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _toggle() {
    setState(() => _expanded = !_expanded);
    if (_expanded) {
      _controller.forward();
    } else {
      _controller.reverse();
    }
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final tokens = context.appTokens;
    final source = widget.source;
    final hasName = source.name.trim().isNotEmpty;

    return ClipRect(
      child: SizedBox(
        height: hasName ? 64 : 52,
        child: Stack(
          children: [
            Positioned(
              right: 0,
              top: 0,
              bottom: 0,
              width: _deleteWidth,
              child: Material(
                color: Colors.red,
                child: InkWell(
                  onTap: widget.onDelete,
                  child: const Center(
                    child: Text(
                      '删除',
                      style: TextStyle(
                        color: Colors.white,
                        fontWeight: FontWeight.w600,
                        fontSize: 14,
                      ),
                    ),
                  ),
                ),
              ),
            ),

            SlideTransition(
              position: _slideAnim,
              child: Container(
                color: theme.colorScheme.surface,
                padding: const EdgeInsets.symmetric(vertical: 6),
                child: Row(
                  children: [
                    GestureDetector(
                      onTap: _toggle,
                      behavior: HitTestBehavior.opaque,
                      child: Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 16),
                        child: AnimatedRotation(
                          turns: _expanded ? 0.0 : -0.25,
                          duration: const Duration(milliseconds: 250),
                          child: const Icon(
                            Icons.remove_circle,
                            color: Colors.red,
                            size: 22,
                          ),
                        ),
                      ),
                    ),

                    Expanded(
                      child: GestureDetector(
                        onTap: widget.onEdit,
                        behavior: HitTestBehavior.opaque,
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Text(
                              hasName ? source.name.trim() : source.url,
                              style: theme.textTheme.bodyMedium?.copyWith(
                                fontWeight: FontWeight.w500,
                              ),
                              maxLines: 1,
                              overflow: TextOverflow.ellipsis,
                            ),
                            if (hasName)
                              Text(
                                source.url,
                                style: theme.textTheme.bodySmall?.copyWith(
                                  color: tokens.mutedForeground,
                                ),
                                maxLines: 1,
                                overflow: TextOverflow.ellipsis,
                              ),
                          ],
                        ),
                      ),
                    ),

                    ReorderableDragStartListener(
                      index: widget.index,
                      child: Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 16),
                        child: Icon(
                          Icons.drag_handle,
                          size: 18,
                          color: tokens.mutedForeground,
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _DanmakuSourcesDesktopSheet extends ConsumerStatefulWidget {
  final List<DanmakuSource> initialSources;

  const _DanmakuSourcesDesktopSheet({required this.initialSources});

  @override
  ConsumerState<_DanmakuSourcesDesktopSheet> createState() =>
      _DanmakuSourcesDesktopSheetState();
}

class _DanmakuSourcesDesktopSheetState
    extends ConsumerState<_DanmakuSourcesDesktopSheet>
    with _DanmakuSourcesLogic<_DanmakuSourcesDesktopSheet> {
  bool _editing = false;
  DanmakuSource? _editingSource;
  final _nameCtrl = TextEditingController();
  final _urlCtrl = TextEditingController();

  @override
  void initState() {
    super.initState();
    initSources(widget.initialSources);
  }

  @override
  void dispose() {
    _nameCtrl.dispose();
    _urlCtrl.dispose();
    super.dispose();
  }

  void _startEdit(DanmakuSource? source) {
    _nameCtrl.text = source?.name ?? '';
    _urlCtrl.text = source?.url ?? '';
    setState(() {
      _editing = true;
      _editingSource = source;
    });
  }

  void _cancelEdit() {
    setState(() {
      _editing = false;
      _editingSource = null;
    });
  }

  Future<void> _saveEdit() async {
    final url = _urlCtrl.text.trim();
    if (url.isEmpty) return;
    final source = _editingSource;
    final id = source?.id.isNotEmpty == true
        ? source!.id
        : 'src_${url.hashCode.toUnsigned(32).toRadixString(16)}';
    final saved = DanmakuSource(
      id: id,
      name: _nameCtrl.text.trim(),
      url: url,
      enabled: source?.enabled ?? true,
    );
    final existing = sources.indexWhere((s) => s.id == saved.id);
    final next = [...sources];
    if (existing >= 0) {
      next[existing] = saved;
    } else {
      next.add(saved);
    }
    await persist(next);
    if (!mounted) return;
    setState(() {
      _editing = false;
      _editingSource = null;
    });
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);

    return Material(
      color: theme.colorScheme.surface,
      child: SafeArea(
        left: false,
        right: false,
        child: Column(
          children: [
            _buildHeader(theme),
            const Divider(height: 1),
            Expanded(child: _editing ? _buildEditView() : _buildListView(theme)),
          ],
        ),
      ),
    );
  }

  Widget _buildHeader(ThemeData theme) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(16, 12, 8, 12),
      child: Row(
        children: [
          if (_editing)
            IconButton(
              tooltip: '返回',
              icon: const Icon(Icons.arrow_back, size: 20),
              onPressed: _cancelEdit,
            )
          else
            const SizedBox(width: 8),
          Expanded(
            child: Text(
              _editing
                  ? (_editingSource == null ? '添加弹幕源' : '编辑弹幕源')
                  : '弹幕源',
              style: theme.textTheme.titleMedium?.copyWith(
                fontWeight: FontWeight.w600,
              ),
            ),
          ),
          IconButton(
            tooltip: '关闭',
            icon: const Icon(Icons.close, size: 20),
            onPressed: () => Navigator.pop(context),
          ),
        ],
      ),
    );
  }

  Widget _buildListView(ThemeData theme) {
    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.fromLTRB(20, 16, 20, 12),
          child: Align(
            alignment: Alignment.centerLeft,
            child: Text(
              '按顺序自动匹配；启用的源会聚合显示候选，选中后从对应源加载弹幕。',
              style: TextStyle(
                fontSize: 13,
                color: theme.colorScheme.onSurfaceVariant,
              ),
            ),
          ),
        ),
        Expanded(
          child: sources.isEmpty
              ? Center(
                  child: Text(
                    '尚未配置弹幕源',
                    style: TextStyle(
                      color: theme.colorScheme.onSurfaceVariant,
                    ),
                  ),
                )
              : ReorderableListView.builder(
                  buildDefaultDragHandles: false,
                  padding: const EdgeInsets.symmetric(horizontal: 8),
                  itemCount: sources.length,
                  onReorder: (oldIndex, newIndex) =>
                      unawaited(reorderSource(oldIndex, newIndex)),
                  itemBuilder: (context, index) {
                    final source = sources[index];
                    return ListTile(
                      key: ValueKey(source.id),
                      leading: ReorderableDragStartListener(
                        index: index,
                        child: const Icon(Icons.drag_handle, size: 18),
                      ),
                      title: Text(
                        source.displayName,
                        maxLines: 1,
                        overflow: TextOverflow.ellipsis,
                      ),
                      subtitle: source.name.trim().isEmpty
                          ? null
                          : Text(
                              source.url,
                              maxLines: 1,
                              overflow: TextOverflow.ellipsis,
                            ),
                      trailing: Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          FSwitch(
                            value: source.enabled,
                            onChange: (v) => unawaited(toggleSource(source, v)),
                          ),
                          IconButton(
                            tooltip: '编辑',
                            icon: const Icon(Icons.edit_outlined, size: 18),
                            onPressed: () => _startEdit(source),
                          ),
                          IconButton(
                            tooltip: '移除',
                            icon: const Icon(Icons.delete_outline, size: 18),
                            onPressed: () => unawaited(removeSource(source)),
                          ),
                        ],
                      ),
                    );
                  },
                ),
        ),
        const Divider(height: 1),
        Padding(
          padding: const EdgeInsets.fromLTRB(16, 12, 16, 16),
          child: Row(
            children: [
              Expanded(
                child: FButton(
                  onPress: () => _startEdit(null),
                  prefix: const Icon(Icons.add, size: 16),
                  child: const Text('添加'),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget _buildEditView() {
    return Column(
      children: [
        Expanded(
          child: SingleChildScrollView(
            padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                TextField(
                  controller: _nameCtrl,
                  decoration: const InputDecoration(
                    labelText: '名称',
                    hintText: '例如：主源、备用源',
                    isDense: true,
                  ),
                ),
                const SizedBox(height: 16),
                TextField(
                  controller: _urlCtrl,
                  autofocus: _editingSource == null,
                  decoration: const InputDecoration(
                    labelText: '服务地址',
                    hintText: 'http://localhost:8080',
                    isDense: true,
                  ),
                ),
              ],
            ),
          ),
        ),
        const Divider(height: 1),
        Padding(
          padding: const EdgeInsets.fromLTRB(16, 12, 16, 16),
          child: Row(
            children: [
              Expanded(
                child: FButton(
                  onPress: _cancelEdit,
                  variant: FButtonVariant.outline,
                  child: const Text('取消'),
                ),
              ),
              const SizedBox(width: 12),
              Expanded(
                child: FButton(
                  onPress: () => unawaited(_saveEdit()),
                  child: const Text('保存'),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }
}
