import 'dart:async';

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

import '../../core/contracts/library.dart';
import '../../providers/di_providers.dart';
import '../../providers/session_provider.dart';
import '../../shared/mappers/media_image_url.dart';
import '../../shared/utils/media_nav.dart';
import '../../shared/utils/time_bucket.dart';
import '../../shared/widgets/app_sliver_header.dart';
import '../../shared/widgets/app_loading_ring.dart';
import '../../shared/widgets/empty_state.dart';
import 'aggregated_grouping.dart';
import 'widgets/aggregated_grouped_grid.dart';
import 'widgets/aggregated_media_card.dart';
import 'widgets/server_filter_bar.dart';

class AggregatedRecentPage extends ConsumerStatefulWidget {
  final bool embedded;

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

  @override
  ConsumerState<AggregatedRecentPage> createState() =>
      _AggregatedRecentPageState();
}

class _AggregatedRecentPageState extends ConsumerState<AggregatedRecentPage> {
  StreamSubscription<GlobalSearchServerResult>? _subscription;

  List<GlobalSearchServerResult> _serverResults = [];
  bool _loading = false;
  bool _switching = false;

  final Set<String> _collapsed = {};
  String? _serverFilter;

  @override
  void initState() {
    super.initState();
    _load();
  }

  @override
  void dispose() {
    _subscription?.cancel();
    super.dispose();
  }

  Future<void> _load() async {
    _subscription?.cancel();
    _subscription = null;

    setState(() {
      _loading = true;
      _serverResults = [];
    });

    try {
      final uc = await ref.read(aggregatedRecentUseCaseProvider.future);
      final stream = uc.executeStream();

      _subscription = stream.listen(
        (result) {
          if (mounted) {
            setState(() => _serverResults = [..._serverResults, result]);
          }
        },
        onDone: () {
          if (mounted) setState(() => _loading = false);
        },
        onError: (_) {
          if (mounted) setState(() => _loading = false);
        },
      );
    } catch (_) {
      if (mounted) setState(() => _loading = false);
    }
  }

  Future<void> _onItemTap(
    BuildContext context,
    GlobalSearchServerResult serverResult,
    EmbyRawItem item,
  ) async {
    if (_switching) return;
    setState(() => _switching = true);
    try {
      await goMediaDetailOnServer(
        context,
        ref,
        serverId: serverResult.serverId,
        item: item,
      );
    } finally {
      if (mounted) setState(() => _switching = false);
    }
  }

  void _toggle(String key) {
    setState(() {
      if (!_collapsed.remove(key)) _collapsed.add(key);
    });
  }

  @override
  Widget build(BuildContext context) {
    ref.listen(sessionProvider, (previous, next) {
      final prevIds =
          previous?.value?.sessions.map((s) => s.serverId).toSet() ??
          <String>{};
      final nextIds =
          next.value?.sessions.map((s) => s.serverId).toSet() ?? <String>{};
      if (prevIds.length == nextIds.length && prevIds.containsAll(nextIds)) {
        return;
      }
      if (_serverFilter != null && !nextIds.contains(_serverFilter)) {
        setState(() => _serverFilter = null);
      }
      _load();
    });

    if (widget.embedded) {
      return Stack(
        fit: StackFit.expand,
        children: [
          CustomScrollView(
            slivers: [
              SliverOverlapInjector(
                handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
                  context,
                ),
              ),
              ..._buildContentSlivers(context),
            ],
          ),
          if (_switching) _switchingOverlay(),
        ],
      );
    }

    return Stack(
      fit: StackFit.expand,
      children: [
        Scaffold(
          extendBodyBehindAppBar: true,
          body: CustomScrollView(
            slivers: [
              AppSliverHeader(
                title: '最近添加',
                actions: [
                  IconButton(
                    onPressed: _loading ? null : _load,
                    icon: _loading
                        ? const AppLoadingRing(size: 16)
                        : const Icon(Icons.refresh, size: 18),
                    tooltip: '刷新',
                  ),
                ],
              ),
              ..._buildContentSlivers(context),
            ],
          ),
        ),
        if (_switching) _switchingOverlay(),
      ],
    );
  }

  Widget _switchingOverlay() => const Positioned.fill(
    child: ColoredBox(
      color: Color(0x44000000),
      child: Center(child: AppLoadingRing()),
    ),
  );

  List<Widget> _buildContentSlivers(BuildContext context) {
    if (_serverResults.isEmpty && !_loading) {
      return const [
        SliverFillRemaining(
          hasScrollBody: false,
          child: EmptyState(
            icon: Icons.new_releases_outlined,
            title: '暂无最近添加内容',
          ),
        ),
      ];
    }
    if (_serverResults.isEmpty && _loading) {
      return const [
        SliverFillRemaining(
          hasScrollBody: false,
          child: Center(child: AppLoadingRing()),
        ),
      ];
    }

    final now = DateTime.now();
    final entries = flatten(
      _serverResults,
      serverFilter: _serverFilter,
      deduplicateAcrossServers: true,
    );
    final groups = groupEntries(entries, GroupAxis.addedTime, now);
    final servers = _serverResults
        .map((sr) => (id: sr.serverId, name: sr.serverName))
        .toList(growable: false);

    return [
      SliverToBoxAdapter(
        child: Padding(
          padding: const EdgeInsets.only(top: 8),
          child: ServerFilterBar(
            servers: servers,
            selected: _serverFilter,
            onSelect: (v) => setState(() => _serverFilter = v),
          ),
        ),
      ),
      ...buildAggregatedGridSlivers(
        groups: groups,
        collapsed: _collapsed,
        onToggle: _toggle,
        cardBuilder: (entry) => _card(context, entry, now),
      ),
    ];
  }

  Widget _card(BuildContext context, AggregatedEntry entry, DateTime now) {
    final sr = entry.source;
    final item = entry.item;
    final subtitle = item.ProductionYear != null
        ? '${item.ProductionYear}'
        : null;

    return AggregatedMediaCard(
      item: item,
      imageUrl: EmbyImageUrl.landscapeCard(
        baseUrl: sr.serverUrl,
        token: sr.token,
        item: item,
        maxWidth: 400,
      ),
      imageHeaders: buildEmbyImageHeaders(
        ref,
        token: sr.token,
        userId: sr.userId,
      ),
      title: item.Name,
      subtitle: subtitle,
      serverName: sr.serverName,
      timeLabel: relativeTimeLabel(entry.dateFor(GroupAxis.addedTime), now),
      showProgress: false,
      onTap: () => _onItemTap(context, sr, item),
    );
  }
}
