import 'dart:async';

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

import '../../core/contracts/script_widget.dart';
import '../../core/domain/usecases/script_widget/script_widget_service.dart';
import '../../providers/di_providers.dart';
import '../../shared/constants/layout_constants.dart';
import '../../shared/theme/app_theme.dart';
import '../../shared/utils/user_error_formatter.dart';
import '../../shared/widgets/app_card.dart';
import '../../shared/widgets/app_error_state.dart';
import '../../shared/widgets/app_loading_ring.dart';
import '../../shared/widgets/app_sliver_header.dart';
import '../../shared/widgets/empty_state.dart';
import '../../shared/widgets/page_background.dart';
import '../../shared/widgets/script_video_card.dart';
import '../../shared/widgets/section_header.dart';


const double _kInfiniteScrollThreshold = 200;

class ModuleAllPage extends ConsumerStatefulWidget {
  final String widgetId;
  final String moduleKey;


  final Map<String, String> initialParams;

  const ModuleAllPage({
    super.key,
    required this.widgetId,
    required this.moduleKey,
    this.initialParams = const <String, String>{},
  });

  @override
  ConsumerState<ModuleAllPage> createState() => _ModuleAllPageState();
}

class _ModuleAllPageState extends ConsumerState<ModuleAllPage> {
  final ScrollController _scrollController = ScrollController();

  ScriptWidgetModule? _module;
  Map<String, Object?> _parameters = <String, Object?>{};


  final List<ScriptWidgetContentSection> _sections =
      <ScriptWidgetContentSection>[];

  String? _initializedWidgetId;
  String? _initializationError;


  bool _isFirstLoad = true;
  bool _isLoadingMore = false;
  bool _hasMore = true;
  String? _loadError;

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(_onScroll);
  }

  @override
  void dispose() {
    _scrollController.removeListener(_onScroll);
    _scrollController.dispose();
    super.dispose();
  }

  void _onScroll() {
    if (!_scrollController.hasClients) return;
    final remaining =
        _scrollController.position.maxScrollExtent -
        _scrollController.position.pixels;
    if (remaining <= _kInfiniteScrollThreshold) {
      unawaited(_fetchNextPage());
    }
  }

  Future<void> _initialize(InstalledScriptWidget installedWidget) async {
    if (_initializedWidgetId == installedWidget.manifest.id) return;
    _initializedWidgetId = installedWidget.manifest.id;

    final module = installedWidget.manifest.modules
        .where((candidate) => _moduleKey(candidate) == widget.moduleKey)
        .firstOrNull;
    if (module == null) {
      setState(() {
        _initializationError = '未找到模块功能：${widget.moduleKey}';
      });
      return;
    }

    final resolvedParameters = buildScriptWidgetParameterDefaults(module.params);
    for (final entry in widget.initialParams.entries) {
      if (resolvedParameters.containsKey(entry.key)) {
        resolvedParameters[entry.key] = entry.value;
      }
    }
    setState(() {
      _module = module;
      _parameters = resolvedParameters;
      _initializationError = null;
    });
    await _fetchNextPage();
  }

  String _moduleKey(ScriptWidgetModule module) {
    return module.id.isEmpty ? module.functionName : module.id;
  }

  ScriptWidgetParam? get _pagingParameter {
    return _module?.params
        .where(
          (parameter) => parameter.type == 'page' || parameter.type == 'offset',
        )
        .firstOrNull;
  }


  bool get _supportsPagination => _pagingParameter != null;

  Future<void> _fetchNextPage() async {
    if (_isLoadingMore || !_hasMore) return;
    final module = _module;
    if (module == null) return;

    setState(() {
      _isLoadingMore = true;
      _loadError = null;
    });

    try {
      final service = await ref.read(scriptWidgetServiceProvider.future);
      final freshSections = await service.loadModuleSections(
        widget.widgetId,
        module,
        _parameters,
      );
      if (!mounted) return;

      final contentItemCount = freshSections.fold<int>(
        0,
        (count, section) =>
            count +
            section.items
                .where((item) => item.type.toLowerCase() != 'text')
                .length,
      );

      setState(() {
        _mergeSections(freshSections);
        if (!_supportsPagination || contentItemCount == 0) {
          _hasMore = false;
        } else {
          _advancePagingCursor();
        }
        _isFirstLoad = false;
        _isLoadingMore = false;
      });
    } catch (error) {
      if (!mounted) return;
      setState(() {
        _loadError = formatUserError(error);
        _isFirstLoad = false;
        _isLoadingMore = false;
      });
    }
  }


  void _mergeSections(List<ScriptWidgetContentSection> freshSections) {
    for (final freshSection in freshSections) {
      final existingIndex = _sections.indexWhere(
        (existing) => existing.title == freshSection.title,
      );
      if (existingIndex == -1) {
        _sections.add(freshSection);
        continue;
      }
      final merged = <ScriptVideoItem>[
        ..._sections[existingIndex].items,
        ...freshSection.items,
      ];
      _sections[existingIndex] = ScriptWidgetContentSection(
        title: freshSection.title,
        items: merged,
      );
    }
  }


  void _advancePagingCursor() {
    final module = _module;
    final pagingParameter = _pagingParameter;
    if (module == null || pagingParameter == null) return;

    final minimumValue = pagingParameter.type == 'page' ? 1 : 0;
    final currentValue =
        int.tryParse(_parameters[pagingParameter.name]?.toString() ?? '') ??
        minimumValue;
    final countParameter = module.params
        .where((parameter) => parameter.type == 'count')
        .firstOrNull;
    final pageStep = pagingParameter.type == 'offset'
        ? int.tryParse(_parameters[countParameter?.name]?.toString() ?? '') ??
              20
        : 1;
    _parameters[pagingParameter.name] = currentValue + pageStep;
  }

  Future<void> _refresh() async {
    setState(() {
      _sections.clear();
      _isFirstLoad = true;
      _isLoadingMore = false;
      _hasMore = true;
      _loadError = null;
      final module = _module;
      if (module != null) {
        _parameters = buildScriptWidgetParameterDefaults(module.params);
        for (final entry in widget.initialParams.entries) {
          if (_parameters.containsKey(entry.key)) {
            _parameters[entry.key] = entry.value;
          }
        }
      }
    });
    await _fetchNextPage();
  }

  @override
  Widget build(BuildContext context) {
    final installedWidget = ref.watch(
      installedScriptWidgetProvider(widget.widgetId),
    );
    return Scaffold(
      backgroundColor: Colors.transparent,
      extendBodyBehindAppBar: true,
      body: Stack(
        children: [
          const Positioned.fill(child: PageBackground()),
          installedWidget.when(
            loading: () => const Center(child: AppLoadingRing()),
            error: (error, _) => Center(
              child: AppErrorState(
                message: formatUserError(error),
                onRetry: () => ref.invalidate(
                  installedScriptWidgetProvider(widget.widgetId),
                ),
              ),
            ),
            data: (widgetData) {
              WidgetsBinding.instance.addPostFrameCallback((_) {
                if (mounted) unawaited(_initialize(widgetData));
              });
              return _buildContent(widgetData);
            },
          ),
        ],
      ),
    );
  }

  Widget _buildContent(InstalledScriptWidget installedWidget) {
    final moduleTitle = _module?.title.trim();
    final title = moduleTitle == null || moduleTitle.isEmpty
        ? installedWidget.manifest.title
        : moduleTitle;
    return RefreshIndicator(
      onRefresh: _refresh,
      child: CustomScrollView(
        controller: _scrollController,
        physics: const AlwaysScrollableScrollPhysics(
          parent: BouncingScrollPhysics(),
        ),
        slivers: [
          AppSliverHeader(title: title),
          ..._buildBodySlivers(),
        ],
      ),
    );
  }

  List<Widget> _buildBodySlivers() {
    if (_initializationError case final initializationError?) {
      return [
        SliverFillRemaining(
          hasScrollBody: false,
          child: AppErrorState(message: initializationError),
        ),
      ];
    }
    if (_module == null || (_isFirstLoad && _isLoadingMore)) {
      return const [
        SliverFillRemaining(
          hasScrollBody: false,
          child: Center(child: AppLoadingRing()),
        ),
      ];
    }
    final firstLoadError = _isFirstLoad ? _loadError : null;
    if (firstLoadError != null) {
      return [
        SliverFillRemaining(
          hasScrollBody: false,
          child: AppErrorState(
            message: firstLoadError,
            onRetry: _fetchNextPage,
          ),
        ),
      ];
    }
    if (_sections.every((section) => section.items.isEmpty)) {
      return const [
        SliverFillRemaining(
          hasScrollBody: false,
          child: EmptyState(
            compact: true,
            icon: Icons.video_library_outlined,
            title: '没有可显示的内容',
          ),
        ),
      ];
    }

    return [
      SliverPadding(
        padding: const EdgeInsets.fromLTRB(20, 14, 20, 0),
        sliver: SliverList(
          delegate: SliverChildListDelegate.fixed([
            for (final section in _sections) ...[
              _ModuleGridSection(
                section: section,
                widgetId: widget.widgetId,
              ),
              const SizedBox(height: 28),
            ],
          ]),
        ),
      ),
      SliverToBoxAdapter(child: _buildFooter()),
    ];
  }

  Widget _buildFooter() {
    if (_isLoadingMore) {
      return const Padding(
        padding: EdgeInsets.symmetric(vertical: 24),
        child: Center(child: AppLoadingRing()),
      );
    }
    if (_loadError case final loadError?) {
      return Padding(
        padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
        child: AppErrorState(
          compact: true,
          message: loadError,
          onRetry: _fetchNextPage,
        ),
      );
    }
    if (!_hasMore) {
      return Padding(
        padding: const EdgeInsets.symmetric(vertical: 24),
        child: Center(
          child: Text(
            '没有更多了',
            style: Theme.of(context).textTheme.bodySmall?.copyWith(
              color: context.appTokens.mutedForeground,
            ),
          ),
        ),
      );
    }
    return const SizedBox(height: 40);
  }
}

class _ModuleGridSection extends StatelessWidget {
  final ScriptWidgetContentSection section;
  final String widgetId;

  const _ModuleGridSection({required this.section, required this.widgetId});

  @override
  Widget build(BuildContext context) {
    final statusItems = section.items
        .where((item) => item.type.toLowerCase() == 'text')
        .toList(growable: false);
    final contentItems = section.items
        .where((item) => item.type.toLowerCase() != 'text')
        .toList(growable: false);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        SectionHeader(label: section.title, count: contentItems.length),
        for (final statusItem in statusItems) ...[
          _ModuleStatusCard(item: statusItem),
          const SizedBox(height: 12),
        ],
        if (contentItems.isNotEmpty)
          GridView.builder(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            itemCount: contentItems.length,
            gridDelegate: mediaGridDelegate,
            itemBuilder: (context, index) {
              final item = contentItems[index];
              return ScriptVideoCard(
                item: item,
                width: double.infinity,
                onTap: () => context.push(
                  '/modules/${Uri.encodeComponent(widgetId)}/detail',
                  extra: item,
                ),
              );
            },
          ),
      ],
    );
  }
}

class _ModuleStatusCard extends StatelessWidget {
  final ScriptVideoItem item;

  const _ModuleStatusCard({required this.item});

  @override
  Widget build(BuildContext context) {
    final normalizedId = item.id.toLowerCase();
    final indicatesError =
        normalizedId.startsWith('err') ||
        item.title.contains('失败') ||
        item.title.contains('错误') ||
        item.title.contains('拦截');
    final foregroundColor = indicatesError
        ? Theme.of(context).colorScheme.error
        : context.appTokens.mutedForeground;

    return AppCard(
      padding: const EdgeInsets.all(16),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Icon(
            indicatesError
                ? Icons.error_outline_rounded
                : Icons.info_outline_rounded,
            color: foregroundColor,
          ),
          const SizedBox(width: 12),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  item.title.isEmpty ? '模块提示' : item.title,
                  style: Theme.of(context).textTheme.titleSmall?.copyWith(
                    color: foregroundColor,
                    fontWeight: FontWeight.w700,
                  ),
                ),
                if (item.description.trim().isNotEmpty) ...[
                  const SizedBox(height: 4),
                  Text(
                    item.description,
                    style: Theme.of(context).textTheme.bodySmall?.copyWith(
                      color: context.appTokens.mutedForeground,
                    ),
                  ),
                ],
              ],
            ),
          ),
        ],
      ),
    );
  }
}
