import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/post.dart';
import 'package:island/pods/network.dart';
import 'package:island/widgets/post/post_item.dart';
import 'package:island/widgets/post/post_item_creator.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';

part 'post_list.g.dart';

@riverpod
class PostListNotifier extends _$PostListNotifier
    with CursorPagingNotifierMixin<SnPost> {
  static const int _pageSize = 20;

  @override
  Future<CursorPagingData<SnPost>> build(
    String? pubName, {
    int? type,
    List<String>? categories,
    List<String>? tags,
  }) {
    return fetch(cursor: null);
  }

  @override
  Future<CursorPagingData<SnPost>> fetch({required String? cursor}) async {
    final client = ref.read(apiClientProvider);
    final offset = cursor == null ? 0 : int.parse(cursor);

    final queryParams = {
      'offset': offset,
      'take': _pageSize,
      if (pubName != null) 'pub': pubName,
      if (type != null) 'type': type,
      if (tags != null) 'tags': tags,
      if (categories != null) 'categories': categories,
    };

    final response = await client.get(
      '/sphere/posts',
      queryParameters: queryParams,
    );
    final total = int.parse(response.headers.value('X-Total') ?? '0');
    final List<dynamic> data = response.data;
    final posts = data.map((json) => SnPost.fromJson(json)).toList();

    final hasMore = offset + posts.length < total;
    final nextCursor = hasMore ? (offset + posts.length).toString() : null;

    return CursorPagingData(
      items: posts,
      hasMore: hasMore,
      nextCursor: nextCursor,
    );
  }
}

/// Defines which post item widget to use in the list
enum PostItemType {
  /// Regular post item with user information
  regular,

  /// Creator view with analytics and metadata
  creator,
}

class SliverPostList extends HookConsumerWidget {
  final String? pubName;
  final int? type;
  final List<String>? categories;
  final List<String>? tags;
  final PostItemType itemType;
  final Color? backgroundColor;
  final EdgeInsets? padding;
  final bool isOpenable;
  final Function? onRefresh;
  final Function(SnPost)? onUpdate;

  const SliverPostList({
    super.key,
    this.pubName,
    this.type,
    this.categories,
    this.tags,
    this.itemType = PostItemType.regular,
    this.backgroundColor,
    this.padding,
    this.isOpenable = true,
    this.onRefresh,
    this.onUpdate,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return PagingHelperSliverView(
      provider: postListNotifierProvider(
        pubName,
        type: type,
        categories: categories,
        tags: tags,
      ),
      futureRefreshable:
          postListNotifierProvider(
            pubName,
            type: type,
            categories: categories,
            tags: tags,
          ).future,
      notifierRefreshable:
          postListNotifierProvider(
            pubName,
            type: type,
            categories: categories,
            tags: tags,
          ).notifier,
      contentBuilder:
          (data, widgetCount, endItemView) => SliverList.builder(
            itemCount: widgetCount,
            itemBuilder: (context, index) {
              if (index == widgetCount - 1) {
                return endItemView;
              }

              final post = data.items[index];

              return _buildPostItem(post);
            },
          ),
    );
  }

  Widget _buildPostItem(SnPost post) {
    switch (itemType) {
      case PostItemType.creator:
        return Column(
          children: [
            PostItemCreator(
              item: post,
              backgroundColor: backgroundColor,
              padding: padding,
              isOpenable: isOpenable,
              onRefresh: onRefresh,
              onUpdate: onUpdate,
            ),
            const Divider(),
          ],
        );
      case PostItemType.regular:
        return Card(
          margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
          child: PostActionableItem(item: post, borderRadius: 8),
        );
    }
  }
}
