import 'dart:async';

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

import '../../core/contracts/script_widget.dart';
import '../../providers/di_providers.dart';
import '../../shared/theme/app_theme.dart';
import '../../shared/utils/user_error_formatter.dart';
import '../../shared/widgets/adaptive_modal.dart';
import '../../shared/widgets/app_card.dart';
import '../../shared/widgets/app_dialog.dart';
import '../../shared/widgets/app_error_state.dart';
import '../../shared/widgets/app_inline_alert.dart';
import '../../shared/widgets/app_loading_ring.dart';
import '../../shared/widgets/app_snack_bar.dart';
import '../../shared/widgets/auto_dismiss_menu.dart';
import '../../shared/widgets/empty_state.dart';
import '../../shared/widgets/pill_tab_bar.dart';
import 'script_widget_parameter_form.dart';


Future<void> showModuleCenterSheet(BuildContext context) {
  return showAdaptiveModal<void>(
    context: context,
    maxWidth: 720,
    compactHeightFactor: 0.92,
    useRootNavigator: true,
    builder: (sheetContext) => const _ModuleCenterSheet(),
  );
}

class _ModuleCenterSheet extends StatelessWidget {
  const _ModuleCenterSheet();

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Material(
      color: theme.colorScheme.surface,
      child: const ModuleCenterContent(),
    );
  }
}

class _SheetHeader extends StatelessWidget {
  final String title;
  final List<Widget> actions;
  final bool showCloseButton;

  const _SheetHeader({
    required this.title,
    required this.actions,
    this.showCloseButton = true,
  });

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Padding(
      padding: const EdgeInsets.fromLTRB(20, 8, 8, 8),
      child: Row(
        children: [
          Expanded(
            child: Text(
              title,
              style: theme.textTheme.titleMedium?.copyWith(
                fontWeight: FontWeight.w700,
              ),
            ),
          ),
          ...actions,
          if (showCloseButton)
            IconButton(
              onPressed: () => Navigator.of(context).pop(),
              icon: const Icon(Icons.close_rounded),
              tooltip: '关闭',
            ),
        ],
      ),
    );
  }
}


class ModuleCenterContent extends ConsumerStatefulWidget {
  final bool embedded;

  const ModuleCenterContent({super.key, this.embedded = false});

  @override
  ConsumerState<ModuleCenterContent> createState() =>
      _ModuleCenterContentState();
}

class _ModuleCenterContentState extends ConsumerState<ModuleCenterContent> {
  int _selectedSectionIndex = 0;

  @override
  Widget build(BuildContext context) {
    final installedWidgets = ref.watch(installedScriptWidgetsProvider);
    final subscriptions = ref.watch(scriptWidgetSubscriptionsProvider);
    final embedded = widget.embedded;

    final headerActions = <Widget>[
      IconButton(
        onPressed: () => _addFromFile(context),
        icon: const Icon(Icons.file_open_outlined),
        tooltip: '从本地文件导入',
      ),
      FButton(
        onPress: () => _addFromUrl(context),
        child: const Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(Icons.add_link_rounded, size: 17),
            SizedBox(width: 6),
            Text('添加 URL'),
          ],
        ),
      ),
    ];


    final headerHorizontalPadding = embedded
        ? const EdgeInsets.fromLTRB(4, 0, 4, 4)
        : EdgeInsets.zero;
    final tabPadding = embedded
        ? const EdgeInsets.fromLTRB(4, 8, 4, 4)
        : const EdgeInsets.fromLTRB(20, 14, 20, 4);
    final sectionPadding = embedded
        ? const EdgeInsets.fromLTRB(4, 12, 4, 24)
        : const EdgeInsets.fromLTRB(20, 12, 20, 48);

    return RefreshIndicator(
      onRefresh: _refresh,
      child: CustomScrollView(
        physics: const AlwaysScrollableScrollPhysics(
          parent: BouncingScrollPhysics(),
        ),
        slivers: [
          SliverToBoxAdapter(
            child: Padding(
              padding: headerHorizontalPadding,
              child: _SheetHeader(
                title: embedded ? '' : '模块中心',
                actions: headerActions,
                showCloseButton: !embedded,
              ),
            ),
          ),
          SliverToBoxAdapter(
            child: Padding(
              padding: tabPadding,
              child: PillTabBar(
                tabs: const <String>['已安装', '模块订阅'],
                selectedIndex: _selectedSectionIndex,
                onSelect: (selectedIndex) {
                  setState(() => _selectedSectionIndex = selectedIndex);
                },
              ),
            ),
          ),
          SliverPadding(
            padding: sectionPadding,
            sliver: SliverToBoxAdapter(
              child: _selectedSectionIndex == 0
                  ? installedWidgets.when(
                      data: (widgets) => _InstalledWidgetsSection(
                        widgets: widgets,
                        onChanged: () => ref.invalidate(
                          installedScriptWidgetsProvider,
                        ),
                      ),
                      loading: () => const Padding(
                        padding: EdgeInsets.all(32),
                        child: Center(child: AppLoadingRing()),
                      ),
                      error: (error, _) => AppErrorState(
                        compact: true,
                        message: formatUserError(error),
                        onRetry: () => ref.invalidate(
                          installedScriptWidgetsProvider,
                        ),
                      ),
                    )
                  : subscriptions.when(
                      data: (items) => _SubscriptionsSection(
                        subscriptions: items,
                        onChanged: () {
                          ref.invalidate(scriptWidgetSubscriptionsProvider);
                          ref.invalidate(installedScriptWidgetsProvider);
                        },
                      ),
                      loading: () => const Padding(
                        padding: EdgeInsets.all(24),
                        child: Center(child: AppLoadingRing(size: 30)),
                      ),
                      error: (error, _) => AppErrorState(
                        compact: true,
                        message: formatUserError(error),
                        onRetry: () => ref.invalidate(
                          scriptWidgetSubscriptionsProvider,
                        ),
                      ),
                    ),
            ),
          ),
        ],
      ),
    );
  }

  Future<void> _refresh() async {
    ref.invalidate(installedScriptWidgetsProvider);
    ref.invalidate(scriptWidgetSubscriptionsProvider);
    await Future.wait([
      ref.read(installedScriptWidgetsProvider.future),
      ref.read(scriptWidgetSubscriptionsProvider.future),
    ]);
  }

  Future<void> _addFromUrl(BuildContext context) async {
    final url = await showModuleUrlImportSheet(context);
    if (url == null || url.trim().isEmpty || !context.mounted) return;
    try {
      final service = await ref.read(scriptWidgetServiceProvider.future);
      if (url.toLowerCase().split('?').first.endsWith('.fwd')) {
        await service.importSubscription(url.trim());
        ref.invalidate(scriptWidgetSubscriptionsProvider);
        if (context.mounted) showAppToast(context, '模块订阅已添加');
      } else {
        final installed = await service.installFromUrl(url.trim());
        ref.invalidate(installedScriptWidgetsProvider);
        if (context.mounted) {
          showAppToast(context, '已安装 ${installed.manifest.title}');
        }
      }
    } catch (error) {
      if (context.mounted) {
        showAppToast(context, formatUserError(error), tone: AppAlertTone.error);
      }
    }
  }

  Future<void> _addFromFile(BuildContext context) async {
    const acceptedFiles = XTypeGroup(
      label: 'ForwardWidgets',
      extensions: <String>['js', 'fwd'],
    );
    final selectedFile = await openFile(
      acceptedTypeGroups: const <XTypeGroup>[acceptedFiles],
    );
    if (selectedFile == null || !context.mounted) return;
    try {
      final source = await selectedFile.readAsString();
      if (!context.mounted) return;
      final service = await ref.read(scriptWidgetServiceProvider.future);
      if (selectedFile.name.toLowerCase().endsWith('.fwd')) {
        await service.importSubscriptionSource(
          source,
          sourceId: 'local:${selectedFile.name}',
        );
        ref.invalidate(scriptWidgetSubscriptionsProvider);
        if (context.mounted) showAppToast(context, '本地模块订阅已添加');
        return;
      }
      final installed = await service.installFromSource(source);
      ref.invalidate(installedScriptWidgetsProvider);
      if (context.mounted) {
        showAppToast(context, '已安装 ${installed.manifest.title}');
      }
    } catch (error) {
      if (context.mounted) {
        showAppToast(context, formatUserError(error), tone: AppAlertTone.error);
      }
    }
  }
}

class _InstalledWidgetsSection extends ConsumerWidget {
  final List<InstalledScriptWidget> widgets;
  final VoidCallback onChanged;

  const _InstalledWidgetsSection({
    required this.widgets,
    required this.onChanged,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    if (widgets.isEmpty) {
      return const EmptyState(
        compact: true,
        icon: Icons.widgets_outlined,
        title: '尚未安装模块',
        message: '可导入 ForwardWidgets 的 JS 地址、.fwd 订阅或本地脚本。',
      );
    }
    return Column(
      children: [
        for (var index = 0; index < widgets.length; index++) ...[
          _InstalledWidgetTile(
            installedWidget: widgets[index],
            onOpen: () {
              final widgetId = widgets[index].manifest.id;


              Navigator.of(context).pop();
              context.go('/modules/${Uri.encodeComponent(widgetId)}');
            },
            onToggle: (enabled) async {
              final service = await ref.read(
                scriptWidgetServiceProvider.future,
              );
              await service.setWidgetEnabled(
                widgets[index].manifest.id,
                enabled,
              );
              onChanged();
            },
            onConfigure: widgets[index].manifest.globalParams.isEmpty
                ? null
                : () async {
                    final values = await showAppRawDialog<Map<String, Object?>>(
                      context,
                      builder: (_) => _GlobalParametersDialog(
                        parameters: widgets[index].manifest.globalParams,
                        initialValues: widgets[index].globalParams,
                      ),
                    );
                    if (values == null || !context.mounted) return;
                    final service = await ref.read(
                      scriptWidgetServiceProvider.future,
                    );
                    await service.updateGlobalParams(
                      widgets[index].manifest.id,
                      values,
                    );
                    ref.invalidate(
                      installedScriptWidgetProvider(widgets[index].manifest.id),
                    );
                    onChanged();
                    if (context.mounted) {
                      showAppToast(context, '模块参数已保存');
                    }
                  },
            onRefresh: widgets[index].sourceUrl.isEmpty
                ? null
                : () async {
                    try {
                      final service = await ref.read(
                        scriptWidgetServiceProvider.future,
                      );
                      await service.refreshWidget(widgets[index].manifest.id);
                      onChanged();
                      if (context.mounted) {
                        showAppToast(context, '模块已更新');
                      }
                    } catch (error) {
                      if (context.mounted) {
                        showAppToast(
                          context,
                          formatUserError(error),
                          tone: AppAlertTone.error,
                        );
                      }
                    }
                  },
            onDelete: () async {
              final confirmed = await showAppConfirmDialog(
                context,
                title: '删除模块',
                body: Text('确定删除“${widgets[index].manifest.title}”吗？'),
                confirmLabel: '删除',
                destructive: true,
              );
              if (!confirmed) return;
              final service = await ref.read(
                scriptWidgetServiceProvider.future,
              );
              await service.deleteWidget(widgets[index].manifest.id);
              onChanged();
            },
          ),
          if (index < widgets.length - 1) const SizedBox(height: 10),
        ],
      ],
    );
  }
}

class _InstalledWidgetTile extends StatelessWidget {
  final InstalledScriptWidget installedWidget;
  final VoidCallback onOpen;
  final ValueChanged<bool> onToggle;
  final VoidCallback? onConfigure;
  final VoidCallback? onRefresh;
  final VoidCallback onDelete;

  const _InstalledWidgetTile({
    required this.installedWidget,
    required this.onOpen,
    required this.onToggle,
    required this.onConfigure,
    required this.onRefresh,
    required this.onDelete,
  });

  @override
  Widget build(BuildContext context) {
    final manifest = installedWidget.manifest;
    final theme = Theme.of(context);
    final tokens = context.appTokens;
    final menuItems = <FItem>[
      if (onConfigure != null)
        FItem(
          prefix: const Icon(Icons.settings_outlined, size: 17),
          title: const Text('配置全局参数'),
          onPress: onConfigure,
        ),
      if (onRefresh != null)
        FItem(
          prefix: const Icon(Icons.refresh_rounded, size: 17),
          title: const Text('检查更新'),
          onPress: onRefresh,
        ),
      FItem(
        prefix: Icon(
          Icons.delete_outline_rounded,
          size: 17,
          color: theme.colorScheme.error,
        ),
        title: Text('删除模块', style: TextStyle(color: theme.colorScheme.error)),
        onPress: onDelete,
      ),
    ];

    return Opacity(
      opacity: installedWidget.enabled ? 1 : 0.62,
      child: AppCard(
        onTap: installedWidget.enabled ? onOpen : null,
        padding: const EdgeInsets.all(14),
        child: Row(
          children: [
            Container(
              width: 42,
              height: 42,
              alignment: Alignment.center,
              decoration: BoxDecoration(
                color: theme.colorScheme.primary.withValues(alpha: 0.12),
                borderRadius: BorderRadius.circular(tokens.radiusCard),
              ),
              child: Text(
                manifest.title.isEmpty ? '?' : manifest.title[0],
                style: theme.textTheme.titleMedium?.copyWith(
                  color: theme.colorScheme.primary,
                  fontWeight: FontWeight.w700,
                ),
              ),
            ),
            const SizedBox(width: 14),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    manifest.title,
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    style: theme.textTheme.titleSmall?.copyWith(
                      fontWeight: FontWeight.w700,
                    ),
                  ),
                  const SizedBox(height: 4),
                  Text(
                    [
                      if (manifest.author.isNotEmpty) manifest.author,
                      'v${manifest.version}',
                      '${manifest.modules.length} 个功能',
                    ].join(' · '),
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    style: theme.textTheme.bodySmall?.copyWith(
                      color: tokens.mutedForeground,
                    ),
                  ),
                ],
              ),
            ),
            FSwitch(value: installedWidget.enabled, onChange: onToggle),
            const SizedBox(width: 6),
            FPopoverMenu(
              menuBuilder: autoDismissMenuBuilder,
              menuAnchor: Alignment.topRight,
              childAnchor: Alignment.bottomRight,
              menu: [FItemGroup(children: menuItems)],
              builder: (context, controller, child) =>
                  GestureDetector(onTap: controller.toggle, child: child),
              child: const Padding(
                padding: EdgeInsets.all(8),
                child: Icon(Icons.more_vert_rounded, size: 19),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _SubscriptionsSection extends ConsumerWidget {
  final List<ScriptWidgetSubscription> subscriptions;
  final VoidCallback onChanged;

  const _SubscriptionsSection({
    required this.subscriptions,
    required this.onChanged,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    if (subscriptions.isEmpty) {
      return const EmptyState(
        compact: true,
        icon: Icons.inventory_2_outlined,
        title: '尚未添加订阅',
        message: '添加 .fwd URL 后，可从仓库中安装和更新模块。',
      );
    }

    return Column(
      children: [
        for (final subscription in subscriptions)
          Padding(
            padding: const EdgeInsets.only(bottom: 12),
            child: AppCard(
              padding: EdgeInsets.zero,
              child: ExpansionTile(
                shape: const Border(),
                collapsedShape: const Border(),
                title: Text(subscription.catalog.title),
                subtitle: Text(
                  '${subscription.catalog.widgets.length} 个模块 · ${subscription.url}',
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
                trailing: IconButton(
                  icon: const Icon(Icons.refresh_rounded),
                  tooltip: '刷新订阅',
                  onPressed: subscription.url.startsWith('http')
                      ? () async {
                          try {
                            final service = await ref.read(
                              scriptWidgetServiceProvider.future,
                            );
                            await service.importSubscription(subscription.url);
                            onChanged();
                          } catch (error) {
                            if (context.mounted) {
                              showAppToast(
                                context,
                                formatUserError(error),
                                tone: AppAlertTone.error,
                              );
                            }
                          }
                        }
                      : null,
                ),
                children: [
                  for (final entry in subscription.catalog.widgets)
                    _CatalogEntryRow(
                      entry: entry,
                      onInstall: () async {
                        try {
                          final service = await ref.read(
                            scriptWidgetServiceProvider.future,
                          );
                          await service.installFromUrl(entry.url);
                          onChanged();
                          if (context.mounted) {
                            showAppToast(context, '已安装 ${entry.title}');
                          }
                        } catch (error) {
                          if (context.mounted) {
                            showAppToast(
                              context,
                              formatUserError(error),
                              tone: AppAlertTone.error,
                            );
                          }
                        }
                      },
                    ),
                ],
              ),
            ),
          ),
      ],
    );
  }
}

class _CatalogEntryRow extends StatelessWidget {
  final ScriptWidgetCatalogEntry entry;
  final VoidCallback onInstall;

  const _CatalogEntryRow({required this.entry, required this.onInstall});

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Padding(
      padding: const EdgeInsets.fromLTRB(16, 10, 16, 12),
      child: Row(
        children: [
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  entry.title,
                  style: theme.textTheme.bodyMedium?.copyWith(
                    fontWeight: FontWeight.w600,
                  ),
                ),
                const SizedBox(height: 3),
                Text(
                  entry.description.isNotEmpty
                      ? entry.description
                      : '${entry.author} · v${entry.version}',
                  maxLines: 2,
                  overflow: TextOverflow.ellipsis,
                  style: theme.textTheme.bodySmall?.copyWith(
                    color: context.appTokens.mutedForeground,
                  ),
                ),
              ],
            ),
          ),
          const SizedBox(width: 12),
          FButton(
            variant: FButtonVariant.outline,
            onPress: onInstall,
            child: const Text('安装'),
          ),
        ],
      ),
    );
  }
}

class _GlobalParametersDialog extends StatefulWidget {
  final List<ScriptWidgetParam> parameters;
  final Map<String, Object?> initialValues;

  const _GlobalParametersDialog({
    required this.parameters,
    required this.initialValues,
  });

  @override
  State<_GlobalParametersDialog> createState() =>
      _GlobalParametersDialogState();
}

class _GlobalParametersDialogState extends State<_GlobalParametersDialog> {
  late Map<String, Object?> _values;

  @override
  void initState() {
    super.initState();
    _values = <String, Object?>{
      ...buildScriptWidgetParameterDefaults(widget.parameters),
      ...widget.initialValues,
    };
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(24),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('全局参数', style: Theme.of(context).textTheme.titleLarge),
          const SizedBox(height: 8),
          const Text('这些值会自动合并到该模块的每次调用中。'),
          const SizedBox(height: 18),
          ConstrainedBox(
            constraints: const BoxConstraints(maxHeight: 440),
            child: SingleChildScrollView(
              child: ScriptWidgetParameterForm(
                parameters: widget.parameters,
                initialValues: _values,
                onChanged: (values) {
                  _values = Map<String, Object?>.from(values);
                },
              ),
            ),
          ),
          const SizedBox(height: 20),
          Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              FButton(
                variant: FButtonVariant.outline,
                onPress: () => Navigator.of(context).pop(),
                child: const Text('取消'),
              ),
              const SizedBox(width: 8),
              FButton(
                onPress: () => Navigator.of(context).pop(_values),
                child: const Text('保存'),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

Future<String?> showModuleUrlImportSheet(BuildContext context) {
  return showAdaptiveModal<String>(
    context: context,
    maxWidth: 520,
    useRootNavigator: true,
    compactMaxHeightFactor: 0.6,
    builder: (sheetContext) => const _UrlImportSheet(),
  );
}

class _UrlImportSheet extends StatefulWidget {
  const _UrlImportSheet();

  @override
  State<_UrlImportSheet> createState() => _UrlImportSheetState();
}

class _UrlImportSheetState extends State<_UrlImportSheet> {
  final TextEditingController _urlController = TextEditingController();

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

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final tokens = context.appTokens;
    final inputBorder = OutlineInputBorder(
      borderRadius: BorderRadius.circular(8),
      borderSide: BorderSide(
        color: tokens.mutedForeground.withValues(alpha: 0.28),
      ),
    );

    return Padding(
      padding: const EdgeInsets.all(24),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('添加模块', style: theme.textTheme.titleLarge),
          const SizedBox(height: 8),
          const Text('支持单个 .js 脚本地址或 ForwardWidgets .fwd 订阅地址。'),
          const SizedBox(height: 18),
          TextField(
            controller: _urlController,
            autofocus: true,
            decoration: InputDecoration(
              labelText: 'HTTP(S) URL',
              hintText: 'https://example.com/widgets.fwd',
              filled: true,
              fillColor: theme.colorScheme.surface.withValues(alpha: 0.42),
              border: inputBorder,
              enabledBorder: inputBorder,
              focusedBorder: inputBorder.copyWith(
                borderSide: BorderSide(color: theme.colorScheme.primary),
              ),
              isDense: true,
            ),
            onSubmitted: (_) => _submit(),
          ),
          const SizedBox(height: 20),
          Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              FButton(
                variant: FButtonVariant.outline,
                onPress: () => Navigator.of(context).pop(),
                child: const Text('取消'),
              ),
              const SizedBox(width: 8),
              FButton(onPress: _submit, child: const Text('继续')),
            ],
          ),
        ],
      ),
    );
  }

  void _submit() {
    final url = _urlController.text.trim();
    if (url.isEmpty) return;
    Navigator.of(context).pop(url);
  }
}
