import 'dart:convert';

import 'package:fl_query_example/models/product.dart';
import 'package:fl_query/fl_query.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';

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

  @override
  State<InfiniteQueryPageWidget> createState() =>
      _InfiniteQueryPageWidgetState();
}

class _InfiniteQueryPageWidgetState extends State<InfiniteQueryPageWidget> {
  final controller = ScrollController();

  @override
  void initState() {
    super.initState();
    controller.addListener(() async {
      if (controller.position.pixels == controller.position.maxScrollExtent) {
        final query = QueryClient.of(context).getInfiniteQuery("products");
        await query?.fetchNext();
      }
    });
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Infinite Query'),
      ),
      floatingActionButton:
          InfiniteQueryListenable("products", builder: (context, query) {
        return FloatingActionButton(
          onPressed: () {
            query?.fetchNext();
          },
          child: Text(query?.pages.length.toString() ?? "-69"),
        );
      }),
      body: InfiniteQueryBuilder<PagedProducts, ClientException, int>(
        "products",
        (page) async {
          final res = await get(Uri.parse(
            "https://dummyjson.com/products?limit=10&skip=${page * 10}",
          ));

          if (res.statusCode == 200) {
            return PagedProducts.fromJson(jsonDecode(res.body));
          } else {
            throw ClientException(res.statusCode.toString(), res.request?.url);
          }
        },
        nextPage: (lastPage, pages) {
          if (pages.isNotEmpty &&
              pages.last.products.length < pages[lastPage].limit) {
            /// returning [null] will set [hasNextPage] to [false]
            return null;
          }
          return lastPage + 1;
        },
        initialPage: 0,
        jsonConfig: JsonConfig(
          fromJson: (json) => PagedProducts.fromJson(json),
          toJson: (data) => data.toJson(),
        ),
        builder: (context, query) {
          final products = query.pages.map((e) => e.products).expand((e) => e);
          if (!query.hasPages) {
            return const Center(
              child: CircularProgressIndicator(),
            );
          }
          return ListView(
            controller: controller,
            children: [
              for (final product in products)
                ListTile(
                  title: Text(product.title),
                  subtitle: Text(product.description),
                  leading: Image.network(product.thumbnail),
                ),
              if (query.hasNextPage)
                const Center(
                  child: CircularProgressIndicator(),
                ),
              if (query.hasErrors)
                ...query.errors.map((e) => Text(e.message)).toList(),
            ],
          );
        },
      ),
    );
  }
}
