import 'dart:async';

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

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

const _favoriteTypeFilters = <_FavoriteTypeFilter>[
  _FavoriteTypeFilter(includeItemTypes: 'Movie,Series,Episode', label: '全部'),
  _FavoriteTypeFilter(includeItemTypes: 'Movie', label: '电影'),
  _FavoriteTypeFilter(includeItemTypes: 'Series', label: '剧集'),
  _FavoriteTypeFilter(includeItemTypes: 'Episode', label: '单集'),
];

class AggregatedFavoritesPage extends ConsumerStatefulWidget {

  final bool embedded;

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

  @override
  ConsumerState<AggregatedFavoritesPage> createState() =>
      _AggregatedFavoritesPageState();
}

class _AggregatedFavoritesPageState
    extends ConsumerState<AggregatedFavoritesPage> {
  StreamSubscription<GlobalSearchServerResult>? _subscription;

  _FavoriteTypeFilter _selectedFilter = _favoriteTypeFilters.first;
  List<GlobalSearchServerResult> _serverResults = [];
  bool _loading = false;
  bool _switching = false;
  final Map<String, bool> _favoriteLoadingMap = {};

  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(aggregatedFavoritesUseCaseProvider.future);
      final stream = uc.executeStream(
        includeItemTypes: _selectedFilter.includeItemTypes,
      );

      _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);
    }
  }

  Future<void> _removeFavorite(
    GlobalSearchServerResult serverResult,
    EmbyRawItem item,
  ) async {
    if (_favoriteLoadingMap[item.Id] == true) return;
    setState(() => _favoriteLoadingMap[item.Id] = true);
    try {
      final gateway = await ref.read(embyGatewayProvider.future);
      final ctx = AuthedRequestContext(
        baseUrl: serverResult.serverUrl,
        token: serverResult.token,
        userId: serverResult.userId,
      );
      await gateway.setFavoriteStatus(
        ctx: ctx,
        itemId: item.Id,
        isFavorite: false,
      );
      if (mounted) {
        setState(() {
          _serverResults = _serverResults
              .map((sr) {
                if (sr.serverId != serverResult.serverId) return sr;
                final filtered = sr.items
                    .where((i) => i.Id != item.Id)
                    .toList();
                return GlobalSearchServerResult(
                  serverId: sr.serverId,
                  serverName: sr.serverName,
                  serverUrl: sr.serverUrl,
                  userId: sr.userId,
                  token: sr.token,
                  items: filtered,
                );
              })
              .where((sr) => sr.items.isNotEmpty)
              .toList();
        });
      }
    } finally {
      if (mounted) setState(() => _favoriteLoadingMap[item.Id] = false);
    }
  }

  List<FItem> _cardMenuItems(
    GlobalSearchServerResult sr,
    EmbyRawItem item,
  ) => [
    FItem(
      prefix: const Icon(Icons.favorite, size: 16),
      enabled: !(_favoriteLoadingMap[item.Id] ?? false),
      title: const Text('取消收藏'),
      onPress: () => _removeFavorite(sr, item),
    ),
  ];

  void _changeType(_FavoriteTypeFilter filter) {
    if (_selectedFilter == filter) return;
    setState(() => _selectedFilter = filter);
    _load();
  }

  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,
                ),
              ),
              SliverToBoxAdapter(child: _buildTypeFilterRow()),
              ..._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: '刷新',
                  ),
                ],
              ),
              SliverToBoxAdapter(child: _buildTypeFilterRow()),
              ..._buildContentSlivers(context),
            ],
          ),
        ),
        if (_switching) _switchingOverlay(),
      ],
    );
  }

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

  Widget _buildTypeFilterRow() => Padding(
    padding: const EdgeInsets.fromLTRB(24, 8, 24, 8),
    child: Align(
      alignment: Alignment.centerLeft,
      child: SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: Row(
          children: _favoriteTypeFilters.map(_buildTypeButton).toList(),
        ),
      ),
    ),
  );

  Widget _buildTypeButton(_FavoriteTypeFilter filter) {
    final selected = _selectedFilter == filter;
    final child = Text(filter.label);

    return Padding(
      padding: const EdgeInsets.only(right: 8),
      child: FButton(
        variant: selected ? FButtonVariant.primary : FButtonVariant.ghost,
        onPress: () => _changeType(filter),
        child: child,
      ),
    );
  }

  List<Widget> _buildContentSlivers(BuildContext context) {
    if (_serverResults.isEmpty && !_loading) {
      return const [
        SliverFillRemaining(
          hasScrollBody: false,
          child: EmptyState(icon: Icons.favorite_border, 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.mediaType, now);
    final servers = _serverResults
        .map((sr) => (id: sr.serverId, name: sr.serverName))
        .toList(growable: false);

    return [
      SliverToBoxAdapter(
        child: ServerFilterBar(
          servers: servers,
          selected: _serverFilter,
          onSelect: (v) => setState(() => _serverFilter = v),
        ),
      ),
      ...buildAggregatedGridSlivers(
        groups: groups,
        collapsed: _collapsed,
        onToggle: _toggle,
        cardBuilder: (entry) => _card(context, entry),
      ),
    ];
  }

  Widget _card(BuildContext context, AggregatedEntry entry) {
    final sr = entry.source;
    final item = entry.item;
    final episode = formatEpisodeNumber(item.IndexNumber);
    final subtitle = item.Type == 'Episode' && episode != null
        ? '${item.SeriesName ?? ''} $episode'.trim()
        : (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.SeriesName ?? item.Name,
      subtitle: subtitle,
      serverName: sr.serverName,
      showProgress: false,
      onTap: () => _onItemTap(context, sr, item),
      contextMenuItems: _cardMenuItems(sr, item),
    );
  }
}

class _FavoriteTypeFilter {
  final String includeItemTypes;
  final String label;

  const _FavoriteTypeFilter({
    required this.includeItemTypes,
    required this.label,
  });
}
