// ignore_for_file: use_build_context_synchronously
import 'dart:async';

import 'package:community_material_icon/community_material_icon.dart';
import 'package:flutter/material.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Provider/transactions_provider.dart';
import 'package:mobile_pos/const_commas.dart';
import 'package:mobile_pos/generated/l10n.dart' as lang;
import 'package:mobile_pos/model/print_transaction_model.dart';
import 'package:nb_utils/nb_utils.dart';
import 'package:pdf/widgets.dart' as pw;

import '../../../Provider/profile_provider.dart';
import '../../../constant.dart';
import '../../../currency.dart';
import '../../../empty_screen_widget.dart';
import '../../../generate_pdf.dart';
import '../../../pdf/sales_pdf.dart';
import '../../../thermal printing service/printing_provider/print_thermal_invoice_provider.dart';
import '../../Home/home.dart';
import '../../invoice_details/sales_invoice_details_screen.dart';

// Pagination Provider
final salesReportPaginationProvider =
    StateNotifierProvider<SalesReportPaginationNotifier, SalesReportPaginationState>((ref) {
  return SalesReportPaginationNotifier();
});

class SalesReportPaginationState {
  final int currentPage;
  final int itemsPerPage;
  final bool isLoading;
  final bool hasMore;
  final List<dynamic> displayedTransactions;

  SalesReportPaginationState({
    this.currentPage = 1,
    this.itemsPerPage = 10,
    this.isLoading = false,
    this.hasMore = true,
    List<dynamic>? displayedTransactions,
  }) : displayedTransactions = displayedTransactions ?? [];

  SalesReportPaginationState copyWith({
    int? currentPage,
    int? itemsPerPage,
    bool? isLoading,
    bool? hasMore,
    List<dynamic>? displayedTransactions,
  }) {
    return SalesReportPaginationState(
      currentPage: currentPage ?? this.currentPage,
      itemsPerPage: itemsPerPage ?? this.itemsPerPage,
      isLoading: isLoading ?? this.isLoading,
      hasMore: hasMore ?? this.hasMore,
      displayedTransactions: displayedTransactions ?? this.displayedTransactions,
    );
  }
}

class SalesReportPaginationNotifier extends StateNotifier<SalesReportPaginationState> {
  SalesReportPaginationNotifier() : super(SalesReportPaginationState());

  void resetPagination() {
    state = SalesReportPaginationState();
  }

  void loadMoreTransactions(List<dynamic> allTransactions,
      {String? invoiceFilter, DateTime? fromDate, DateTime? toDate}) {
    if (state.isLoading || !state.hasMore) return;

    state = state.copyWith(isLoading: true);

    // Filter transactions based on date range and invoice number
    final filteredTransactions = _filterTransactions(allTransactions,
        invoiceFilter: invoiceFilter, fromDate: fromDate, toDate: toDate);

    final totalItems = filteredTransactions.length;
    final startIndex = (state.currentPage - 1) * state.itemsPerPage;
    final endIndex = startIndex + state.itemsPerPage;

    // Check if we have more items to load
    final hasMoreItems = endIndex < totalItems;

    // Get the next batch of transactions
    final nextBatch = endIndex <= totalItems
        ? filteredTransactions.sublist(startIndex, endIndex)
        : filteredTransactions.sublist(startIndex);

    // Update state
    final newDisplayedTransactions = [...state.displayedTransactions, ...nextBatch];

    state = state.copyWith(
      currentPage: state.currentPage + 1,
      isLoading: false,
      hasMore: hasMoreItems,
      displayedTransactions: newDisplayedTransactions,
    );
  }

  List<dynamic> _filterTransactions(List<dynamic> transactions,
      {String? invoiceFilter, DateTime? fromDate, DateTime? toDate}) {
    return transactions.where((transaction) {
      // Filter by invoice number if provided
      if (invoiceFilter != null && invoiceFilter.isNotEmpty) {
        if (!transaction.invoiceNumber
            .toString()
            .toLowerCase()
            .contains(invoiceFilter.toLowerCase())) {
          return false;
        }
      }

      // Filter by date range if provided
      if (fromDate != null && toDate != null) {
        try {
          final purchaseDate = _safeParsePurchaseDate(transaction.purchaseDate);
          final normalizedFromDate = DateTime(fromDate.year, fromDate.month, fromDate.day);
          final normalizedToDate = DateTime(toDate.year, toDate.month, toDate.day);
          final normalizedPurchaseDate =
              DateTime(purchaseDate.year, purchaseDate.month, purchaseDate.day);

          final isInRange = (normalizedPurchaseDate.isAfter(normalizedFromDate) ||
                  normalizedPurchaseDate.isAtSameMomentAs(normalizedFromDate)) &&
              (normalizedPurchaseDate.isBefore(normalizedToDate) ||
                  normalizedPurchaseDate.isAtSameMomentAs(normalizedToDate));

          if (!isInRange) {
            return false;
          }
        } catch (e) {
          return false;
        }
      }

      return true;
    }).toList();
  }

  DateTime _safeParsePurchaseDate(String dateString) {
    try {
      return DateTime.parse(dateString);
    } catch (e) {
      try {
        return DateFormat("yyyy-MM-dd HH:mm:ss").parse(dateString);
      } catch (e2) {
        return DateTime.now();
      }
    }
  }
}

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

  @override
  _SalesReportScreenState createState() => _SalesReportScreenState();
}

class _SalesReportScreenState extends State<SalesReportScreen> {
  String? invoiceNumber;
  late TextEditingController fromDateTextEditingController;
  late TextEditingController toDateTextEditingController;
  late DateTime fromDate;
  late DateTime toDate;
  double totalSell = 0;
  bool isPicked = false;
  int count = 0;

  final pw.Document doc = pw.Document();
  final pdf = pw.Document();
  final ScrollController _scrollController = ScrollController();

  late StreamSubscription subscription;
  bool isDeviceConnected = false;
  bool isAlertSet = false;

  @override
  void initState() {
    super.initState();
    // Initialize dates with safe defaults
    fromDate = DateTime(2021);
    toDate = DateTime.now();
    fromDateTextEditingController = TextEditingController(text: _formatDate(fromDate));
    toDateTextEditingController = TextEditingController(text: _formatDate(toDate));

    // Add scroll listener for pagination
    _scrollController.addListener(_scrollListener);
  }

  @override
  void dispose() {
    fromDateTextEditingController.dispose();
    toDateTextEditingController.dispose();
    _scrollController.dispose();
    subscription.cancel();
    super.dispose();
  }

  void _scrollListener() {
    if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
      // Load more data when scrolled to bottom
      _loadMoreData();
    }
  }

  void _loadMoreData() {
    final ref = ProviderScope.containerOf(context);
    final providerData = ref.read(transitionProvider);

    providerData.whenData((transactions) {
      ref.read(salesReportPaginationProvider.notifier).loadMoreTransactions(
            transactions.reversed.toList(),
            invoiceFilter: invoiceNumber,
            fromDate: fromDate,
            toDate: toDate,
          );
    });
  }

  void _resetAndLoadData() {
    final ref = ProviderScope.containerOf(context);
    ref.read(salesReportPaginationProvider.notifier).resetPagination();
    _loadMoreData();
  }

  String _formatDate(DateTime date) {
    try {
      return DateFormat.yMMMd().format(date);
    } catch (e) {
      return DateFormat.yMMMd().format(DateTime.now());
    }
  }

  DateTime _parseDate(String dateString, {DateTime? fallback}) {
    try {
      return DateFormat.yMMMd().parse(dateString);
    } catch (e) {
      return fallback ?? DateTime.now();
    }
  }

  bool _isDateInRange(DateTime dateToCheck, DateTime startDate, DateTime endDate) {
    try {
      final normalizedStart = DateTime(startDate.year, startDate.month, startDate.day);
      final normalizedEnd = DateTime(endDate.year, endDate.month, endDate.day);
      final normalizedCheck = DateTime(dateToCheck.year, dateToCheck.month, dateToCheck.day);

      return (normalizedCheck.isAfter(normalizedStart) ||
              normalizedCheck.isAtSameMomentAs(normalizedStart)) &&
          (normalizedCheck.isBefore(normalizedEnd) ||
              normalizedCheck.isAtSameMomentAs(normalizedEnd));
    } catch (e) {
      return false;
    }
  }

  DateTime _safeParsePurchaseDate(String dateString) {
    try {
      return DateTime.parse(dateString);
    } catch (e) {
      try {
        return DateFormat("yyyy-MM-dd HH:mm:ss").parse(dateString);
      } catch (e2) {
        return DateTime.now();
      }
    }
  }

  void _updateTotalSales(List<dynamic> transactions) {
    totalSell = 0;
    for (var element in transactions) {
      try {
        final purchaseDate = _safeParsePurchaseDate(element.purchaseDate);

        if (!isPicked) {
          // Default to current month if no date range is picked
          if (purchaseDate.month == DateTime.now().month &&
              purchaseDate.year == DateTime.now().year) {
            totalSell += element.totalAmount?.toDouble() ?? 0;
          }
        } else {
          // Use selected date range
          if (_isDateInRange(purchaseDate, fromDate, toDate)) {
            totalSell += element.totalAmount?.toDouble() ?? 0;
          }
        }
      } catch (e) {
        // Skip transactions with invalid dates
        continue;
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        return await const Home().launch(context, isNewTask: true);
      },
      child: Scaffold(
        backgroundColor: kMainColor,
        appBar: AppBar(
          title: Text(
            lang.S.of(context).saleReports,
            style: GoogleFonts.poppins(
              color: Colors.white,
              fontSize: 20.0,
            ),
          ),
          iconTheme: const IconThemeData(color: Colors.white),
          centerTitle: true,
          backgroundColor: kMainColor,
          elevation: 0.0,
        ),
        body: Consumer(builder: (context, ref, __) {
          final providerData = ref.watch(transitionProvider);
          final profile = ref.watch(profileDetailsProvider);
          final personalData = ref.watch(profileDetailsProvider);
          final paginationState = ref.watch(salesReportPaginationProvider);

          return Container(
            alignment: Alignment.topCenter,
            decoration: const BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.only(
                    topRight: Radius.circular(30), topLeft: Radius.circular(30))),
            child: SingleChildScrollView(
              controller: _scrollController,
              child: Column(
                children: [
                  Padding(
                    padding: const EdgeInsets.only(right: 20.0, left: 20.0, top: 20, bottom: 10),
                    child: Row(
                      children: [
                        Expanded(
                          child: AppTextField(
                            textFieldType: TextFieldType.NAME,
                            readOnly: true,
                            controller: fromDateTextEditingController,
                            decoration: InputDecoration(
                              floatingLabelBehavior: FloatingLabelBehavior.always,
                              labelText: lang.S.of(context).formDate,
                              border: const OutlineInputBorder(),
                              suffixIcon: IconButton(
                                onPressed: () async {
                                  final DateTime? picked = await showDatePicker(
                                    initialDate: fromDate,
                                    firstDate: DateTime(2015, 8),
                                    lastDate: DateTime(2101),
                                    context: context,
                                  );
                                  if (picked != null) {
                                    setState(() {
                                      fromDateTextEditingController.text = _formatDate(picked);
                                      fromDate = picked;
                                      totalSell = 0;
                                      count = 0;
                                      isPicked = true;
                                      _resetAndLoadData();
                                    });
                                  }
                                },
                                icon: const Icon(FeatherIcons.calendar),
                              ),
                            ),
                          ),
                        ),
                        const SizedBox(width: 10),
                        Expanded(
                          child: AppTextField(
                            textFieldType: TextFieldType.NAME,
                            readOnly: true,
                            controller: toDateTextEditingController,
                            decoration: InputDecoration(
                              floatingLabelBehavior: FloatingLabelBehavior.always,
                              labelText: lang.S.of(context).toDate,
                              border: const OutlineInputBorder(),
                              suffixIcon: IconButton(
                                onPressed: () async {
                                  final DateTime? picked = await showDatePicker(
                                    initialDate: toDate.isAfter(fromDate) ? toDate : fromDate,
                                    firstDate: fromDate,
                                    lastDate: DateTime(2101),
                                    context: context,
                                  );
                                  if (picked != null) {
                                    setState(() {
                                      toDateTextEditingController.text = _formatDate(picked);
                                      toDate = picked;
                                      totalSell = 0;
                                      count = 0;
                                      isPicked = true;
                                      _resetAndLoadData();
                                    });
                                  }
                                },
                                icon: const Icon(FeatherIcons.calendar),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  providerData.when(data: (transaction) {
                    final reTransaction = transaction.reversed.toList();

                    // Update total sales calculation
                    if (count == 0 && reTransaction.isNotEmpty) {
                      count++;
                      _updateTotalSales(reTransaction);
                    }

                    // Initial load of data
                    if (paginationState.displayedTransactions.isEmpty &&
                        !paginationState.isLoading) {
                      WidgetsBinding.instance.addPostFrameCallback((_) {
                        _resetAndLoadData();
                      });
                    }

                    final displayedTransactions = paginationState.displayedTransactions;

                    return displayedTransactions.isNotEmpty || paginationState.isLoading
                        ? Column(
                            children: [
                              Padding(
                                padding: const EdgeInsets.only(left: 20, right: 20.0),
                                child: Container(
                                  height: 120,
                                  width: double.infinity,
                                  decoration: BoxDecoration(
                                    borderRadius: const BorderRadius.all(Radius.circular(15)),
                                    color: kMainColor.withOpacity(0.08),
                                  ),
                                  child: Center(
                                    child: ListTile(
                                      leading: Container(
                                        height: 40,
                                        width: 40,
                                        decoration: const BoxDecoration(
                                          borderRadius: BorderRadius.all(Radius.circular(80)),
                                          image: DecorationImage(
                                            image: AssetImage(
                                              'images/ledger_total_sale.png',
                                            ),
                                          ),
                                        ),
                                      ),
                                      title: Text(
                                        "$currency${myFormat.format(totalSell)}",
                                        style: const TextStyle(
                                          fontSize: 20,
                                          fontWeight: FontWeight.bold,
                                        ),
                                      ),
                                      trailing: Row(mainAxisSize: MainAxisSize.min, children: [
                                        Container(
                                          height: 40,
                                          width: 40,
                                          decoration: BoxDecoration(
                                              borderRadius:
                                                  const BorderRadius.all(Radius.circular(80)),
                                              color: kMainColor.withValues(alpha: 0.2)),
                                          child: const Icon(
                                            Icons.picture_as_pdf_outlined,
                                            color: kMainColor,
                                          ),
                                        ),
                                        const SizedBox(width: 7),
                                        Container(
                                          height: 40,
                                          width: 40,
                                          decoration: BoxDecoration(
                                            borderRadius:
                                                const BorderRadius.all(Radius.circular(80)),
                                            color: Colors.green.withValues(alpha: 0.2),
                                          ),
                                          child: const Icon(
                                            Icons.print,
                                            color: Colors.grey,
                                          ),
                                        ),
                                        const SizedBox(width: 7),
                                        Container(
                                          height: 40,
                                          width: 40,
                                          decoration: BoxDecoration(
                                              borderRadius:
                                                  const BorderRadius.all(Radius.circular(80)),
                                              color: Colors.orange.withValues(alpha: 0.2)),
                                          child: const Icon(
                                            Icons.notifications_none,
                                            color: Colors.orange,
                                          ),
                                        ),
                                      ]).visible(false),
                                      subtitle: Text(
                                          '${lang.S.of(context).totalSale} ${isPicked ? '${lang.S.of(context).from} ${_formatDate(fromDate)} ${lang.S.of(context).to} ${_formatDate(toDate)}' : lang.S.of(context).thisMonth}'),
                                    ),
                                  ),
                                ),
                              ),
                              Padding(
                                padding: const EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0),
                                child: AppTextField(
                                  textFieldType: TextFieldType.NUMBER,
                                  onChanged: (value) {
                                    setState(() {
                                      invoiceNumber = value;
                                      _resetAndLoadData();
                                    });
                                  },
                                  decoration: InputDecoration(
                                      floatingLabelBehavior: FloatingLabelBehavior.never,
                                      labelText: lang.S.of(context).invoiceNumber,
                                      hintText: lang.S.of(context).enterInvoiceNumber,
                                      border: const OutlineInputBorder(),
                                      prefixIcon: const Icon(Icons.search)),
                                ),
                              ),
                              ListView.builder(
                                shrinkWrap: true,
                                physics: const NeverScrollableScrollPhysics(),
                                itemCount: displayedTransactions.length +
                                    (paginationState.hasMore ? 1 : 0),
                                itemBuilder: (context, index) {
                                  // Loading indicator at the end
                                  if (index == displayedTransactions.length) {
                                    return paginationState.hasMore
                                        ? const Padding(
                                            padding: EdgeInsets.all(16.0),
                                            child: Center(
                                              child: CircularProgressIndicator(),
                                            ),
                                          )
                                        : displayedTransactions.isNotEmpty
                                            ? Padding(
                                                padding: const EdgeInsets.all(16.0),
                                                child: Center(
                                                  child: Text(
                                                    lang.S.of(context).noData,
                                                    style: const TextStyle(color: Colors.grey),
                                                  ),
                                                ),
                                              )
                                            : const SizedBox.shrink();
                                  }

                                  final transaction = displayedTransactions[index];
                                  final purchaseDate =
                                      _safeParsePurchaseDate(transaction.purchaseDate);

                                  return GestureDetector(
                                    onTap: () {
                                      SalesInvoiceDetails(
                                        transitionModel: transaction,
                                        personalInformationModel: profile.value!,
                                      ).launch(context);
                                    },
                                    child: Column(
                                      children: [
                                        Container(
                                          padding: const EdgeInsets.all(20),
                                          width: context.width(),
                                          child: Column(
                                            crossAxisAlignment: CrossAxisAlignment.start,
                                            children: [
                                              Row(
                                                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                                children: [
                                                  Flexible(
                                                    child: Text(
                                                      transaction.customerName.isNotEmpty
                                                          ? transaction.customerName
                                                          : transaction.customerPhone,
                                                      style: const TextStyle(fontSize: 16),
                                                      maxLines: 2,
                                                      overflow: TextOverflow.ellipsis,
                                                    ),
                                                  ),
                                                  Text(
                                                    '#${transaction.invoiceNumber}',
                                                    style: const TextStyle(
                                                        color: Colors.black,
                                                        fontWeight: FontWeight.bold),
                                                  ),
                                                ],
                                              ),
                                              const SizedBox(height: 10),
                                              Row(
                                                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                                children: [
                                                  Container(
                                                    padding: const EdgeInsets.all(8),
                                                    decoration: BoxDecoration(
                                                        color: transaction.dueAmount! <= 0
                                                            ? const Color(0xff0dbf7d)
                                                                .withValues(alpha: 0.1)
                                                            : const Color(0xFFED1A3B)
                                                                .withValues(alpha: 0.1),
                                                        borderRadius: const BorderRadius.all(
                                                            Radius.circular(10))),
                                                    child: Text(
                                                      transaction.dueAmount! <= 0
                                                          ? lang.S.of(context).paid
                                                          : lang.S.of(context).unpaid,
                                                      style: TextStyle(
                                                          color: transaction.dueAmount! <= 0
                                                              ? const Color(0xff0dbf7d)
                                                              : const Color(0xFFED1A3B)),
                                                    ),
                                                  ),
                                                  Column(
                                                    crossAxisAlignment: CrossAxisAlignment.end,
                                                    children: [
                                                      Text(
                                                        _formatDate(purchaseDate),
                                                        style: const TextStyle(color: Colors.grey),
                                                      ),
                                                      const SizedBox(height: 2),
                                                      Text(
                                                        DateFormat.jm().format(purchaseDate),
                                                        style: const TextStyle(color: Colors.grey),
                                                      ),
                                                    ],
                                                  ),
                                                ],
                                              ),
                                              const SizedBox(height: 10),
                                              Row(
                                                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                                children: [
                                                  Column(
                                                    crossAxisAlignment: CrossAxisAlignment.start,
                                                    children: [
                                                      Text(
                                                        '${lang.S.of(context).total} : $currency ${myFormat.format(transaction.totalAmount)}',
                                                        style: const TextStyle(color: Colors.grey),
                                                      ),
                                                      const SizedBox(height: 3),
                                                      Text(
                                                        '${lang.S.of(context).paid} : $currency ${myFormat.format((transaction.totalAmount!.toDouble() - (transaction.dueAmount?.toDouble() ?? 0)))}',
                                                        style: const TextStyle(color: Colors.grey),
                                                      ),
                                                      const SizedBox(height: 3),
                                                      Text(
                                                        '${lang.S.of(context).due}: $currency ${myFormat.format(transaction.dueAmount)}',
                                                        style: const TextStyle(fontSize: 16),
                                                      ).visible(
                                                          transaction.dueAmount!.toInt() != 0),
                                                    ],
                                                  ),
                                                  personalData.when(data: (data) {
                                                    return Row(
                                                      children: [
                                                        IconButton(
                                                            onPressed: () async {
                                                              PrintTransactionModel model =
                                                                  PrintTransactionModel(
                                                                      transitionModel: transaction,
                                                                      personalInformationModel:
                                                                          data);
                                                              ref
                                                                  .watch(thermalPrinterProvider)
                                                                  .printSalesThermalInvoiceNow(
                                                                      transaction: model,
                                                                      productList: model
                                                                          .transitionModel
                                                                          ?.productList,
                                                                      context: context);
                                                            },
                                                            icon: const Icon(
                                                              FeatherIcons.printer,
                                                              color: Colors.grey,
                                                            )),
                                                        IconButton(
                                                            onPressed: () async =>
                                                                await GeneratePdf1()
                                                                    .generateSaleDocument(
                                                                  transaction,
                                                                  data,
                                                                  context,
                                                                ),
                                                            icon: const Icon(
                                                              Icons.picture_as_pdf,
                                                              color: Colors.grey,
                                                            )),
                                                        IconButton(
                                                            onPressed: () async {
                                                              shareSalePDF(
                                                                transactions: transaction,
                                                                personalInformation: data,
                                                                context: context,
                                                              );
                                                            },
                                                            icon: const Icon(
                                                              CommunityMaterialIcons.share,
                                                              color: Colors.grey,
                                                            )),
                                                      ],
                                                    );
                                                  }, error: (e, stack) {
                                                    return Text(e.toString());
                                                  }, loading: () {
                                                    return Text(lang.S.of(context).loading);
                                                  }),
                                                ],
                                              ),
                                            ],
                                          ),
                                        ),
                                        Container(
                                          height: 0.5,
                                          width: context.width(),
                                          color: Colors.grey,
                                        )
                                      ],
                                    ),
                                  );
                                },
                              ),
                            ],
                          )
                        : const Center(
                            child: Padding(
                            padding: EdgeInsets.only(top: 60),
                            child: EmptyScreenWidget(),
                          ));
                  }, error: (e, stack) {
                    return Text(e.toString());
                  }, loading: () {
                    return const Padding(
                      padding: EdgeInsets.all(20),
                      child: Center(child: CircularProgressIndicator()),
                    );
                  }),
                ],
              ),
            ),
          );
        }),
      ),
    );
  }
}
