import 'package:flutter/material.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:provider/provider.dart';
import 'package:simplecloudnotifier/api/api_client.dart';
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
import 'package:simplecloudnotifier/models/channel.dart';
import 'package:simplecloudnotifier/models/subscription.dart';
import 'package:simplecloudnotifier/models/user.dart';
import 'package:simplecloudnotifier/state/application_log.dart';
import 'package:simplecloudnotifier/state/app_auth.dart';
import 'package:simplecloudnotifier/pages/subscription_list/subscription_list_item.dart';
import 'package:simplecloudnotifier/state/scn_data_cache.dart';

class SubscriptionListPage extends StatefulWidget {
  const SubscriptionListPage({super.key});

  @override
  State<SubscriptionListPage> createState() => _SubscriptionListPageState();
}

class _SubscriptionListPageState extends State<SubscriptionListPage> {
  final PagingController<int, Subscription> _pagingController = PagingController.fromValue(PagingState(nextPageKey: null, itemList: [], error: null), firstPageKey: 0);

  final userCache = Map<String, UserPreview>();
  final channelCache = Map<String, ChannelPreview>();

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

    for (var v in SCNDataCache().getChannelMap().entries) channelCache[v.key] = v.value.toPreview(null);

    _pagingController.addPageRequestListener(_fetchPage);

    _pagingController.refresh();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    ApplicationLog.debug('SubscriptionListPage::dispose');
    _pagingController.dispose();
    super.dispose();
  }

  Future<void> _fetchPage(int pageKey) async {
    final acc = Provider.of<AppAuth>(context, listen: false);

    ApplicationLog.debug('Start SubscriptionListPage::_pagingController::_fetchPage [ ${pageKey} ]');

    if (!acc.isAuth()) {
      _pagingController.error = 'Not logged in';
      return;
    }

    try {
      final items = (await APIClient.getSubscriptionList(acc)).toList();

      items.sort((a, b) => -1 * a.timestampCreated.compareTo(b.timestampCreated));

      var promises = Map<String, Future<UserPreview>>();

      for (var item in items) {
        if (userCache[item.subscriberUserID] == null && !promises.containsKey(item.subscriberUserID)) {
          promises[item.subscriberUserID] = APIClient.getUserPreview(acc, item.subscriberUserID).then((p) => userCache[p.userID] = p);
        }
        if (userCache[item.channelOwnerUserID] == null && !promises.containsKey(item.channelOwnerUserID)) {
          promises[item.channelOwnerUserID] = APIClient.getUserPreview(acc, item.channelOwnerUserID).then((p) => userCache[p.userID] = p);
        }
        if (channelCache[item.channelID] == null && !promises.containsKey(item.channelID)) {
          channelCache[item.channelID] = await APIClient.getChannelPreview(acc, item.channelID).then((p) => channelCache[p.channelID] = p);
        }
      }

      await Future.wait(promises.values);

      _pagingController.value = PagingState(nextPageKey: null, itemList: items, error: null);
    } catch (exc, trace) {
      _pagingController.error = exc.toString();
      ApplicationLog.error('Failed to list subscriptions: ' + exc.toString(), trace: trace);
    }
  }

  @override
  Widget build(BuildContext context) {
    return SCNScaffold(
      title: "Subscriptions",
      showSearch: false,
      showShare: false,
      child: Padding(
        padding: EdgeInsets.fromLTRB(8, 4, 8, 4),
        child: RefreshIndicator(
          onRefresh: () => Future.sync(
            () => _pagingController.refresh(),
          ),
          child: PagedListView<int, Subscription>(
            pagingController: _pagingController,
            builderDelegate: PagedChildBuilderDelegate<Subscription>(
              itemBuilder: (context, item, index) => SubscriptionListItem(item: item, userCache: userCache, channelCache: channelCache, needsReload: fullRefresh),
            ),
          ),
        ),
      ),
    );
  }

  void fullRefresh() {
    ApplicationLog.debug('SubscriptionListPage::fullRefresh');
    _pagingController.refresh();
  }
}