import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:gen_service/Services/api_calling.dart';
import 'package:open_filex/open_filex.dart';
import 'package:path_provider/path_provider.dart';

import '../Models/TransactionModels/BillDetailResponse.dart';
import '../Models/TransactionModels/PaymentDetailResponse.dart';
import '../Models/TransactionModels/TransactionListResponse.dart';
import '../Services/api_post_request.dart';
import '../Utility/CustomSnackbar.dart';

class TransactionsProvider with ChangeNotifier {
  TransactionListResponse? _transactionList;
  bool _isLoading = false;
  String? _errorMessage;
  int _currentPage = 1;
  bool _hasMore = true;
  bool _isLoadingMore = false;

  TransactionListResponse? get transactionList => _transactionList;
  bool get isLoading => _isLoading;
  bool get isLoadingMore => _isLoadingMore;
  String? get errorMessage => _errorMessage;
  bool get hasMore => _hasMore;

  /// Fetch Transactions from API (initial load)
  Future<void> fetchTransactions(String accId, String sessionId) async {
    _currentPage = 1;
    _hasMore = true;
    _isLoading = true;
    _errorMessage = null;
    notifyListeners();

    try {
      final response = await ApiCalling.fetchTransactionListApi(
          accId,
          sessionId,
          _currentPage.toString()
      );

      if (response != null) {
        _transactionList = response;
        _errorMessage = null;

        // Check if we have more data (assuming 15 items per page)
        _hasMore = _calculateHasMore(response);
      } else {
        _errorMessage = "No response from server";
      }
    } catch (e) {
      _errorMessage = "Failed to fetch transactions: $e";
    }

    _isLoading = false;
    notifyListeners();
  }

  /// Load more transactions
  Future<void> loadMoreTransactions(String accId, String sessionId) async {
    if (_isLoadingMore || !_hasMore) return;

    _isLoadingMore = true;
    notifyListeners();

    try {
      final response = await ApiCalling.fetchTransactionListApi(
          accId,
          sessionId,
          (_currentPage + 1).toString()
      );
      debugPrint("\nPage Number ${_currentPage+1}");

      if (response != null && response.transactions != null) {
        _currentPage++;

        // Merge new transactions with existing ones
        _mergeTransactions(response);

        // Check if we have more data
        _hasMore = _calculateHasMore(response);
      }
    } catch (e) {
      debugPrint("Load more error: $e");
    }

    _isLoadingMore = false;
    notifyListeners();
  }

  /// Merge new transactions with existing data
  void _mergeTransactions(TransactionListResponse newResponse) {
    if (_transactionList == null) {
      _transactionList = newResponse;
      return;
    }

    // Merge transactions by month
    if (newResponse.transactions != null) {
      if (_transactionList!.transactions == null) {
        _transactionList!.transactions = {};
      }

      newResponse.transactions!.forEach((month, newItems) {
        if (_transactionList!.transactions!.containsKey(month)) {
          // Month exists, append items
          _transactionList!.transactions![month]!.addAll(newItems);
        } else {
          // New month, add all items
          _transactionList!.transactions![month] = newItems;
        }
      });
    }
  }

  /// Check if there are more pages to load
  bool _calculateHasMore(TransactionListResponse response) {
    if (response.transactions == null || response.transactions!.isEmpty) {
      return false;
    }

    // Count total items in current response
    int totalItems = 0;
    response.transactions!.forEach((month, items) {
      totalItems += items.length;
    });

    // If we got less than 15 items, probably no more data
    return totalItems >= 15;
  }

  /// Clear Data
  void clearTransactions() {
    _transactionList = null;
    _errorMessage = null;
    _currentPage = 1;
    _hasMore = true;
    _isLoadingMore = false;
    notifyListeners();
  }



  // Payment Detail properties
  bool _isPaymentLoading = false;
  PaymentDetailResponse? _paymentDetail;

  bool get isPaymentLoading => _isPaymentLoading;
  PaymentDetailResponse? get paymentDetail => _paymentDetail;

  // Bill Detail properties
  bool _isBillLoading = false;
  BillDetailResponse? _billDetail;

  bool get isBillLoading => _isBillLoading;
  BillDetailResponse? get billDetail => _billDetail;


  // 🔹 Fetch Payment Detail API
  Future<void> fetchPaymentDetails(
      String accId, String sessionId, String billId) async {
    _isPaymentLoading = true;
    notifyListeners();

    try {
      final response =
      await ApiCalling.fetchPaymentDetailApi(accId, sessionId, billId);

      if (response != null) {
        _paymentDetail = response;
      } else {
        debugPrint("No payment detail response");
      }
    } catch (e) {
      debugPrint("❌ Payment Details Error: $e");
    }

    _isPaymentLoading = false;
    notifyListeners();
  }

  // ---------------------------------------------------------------------------
  // 🔹 Fetch Bill Detail API
  Future<void> fetchBillDetails(
      String accId, String sessionId, String billId) async {
    _isBillLoading = true;
    notifyListeners();

    try {
      final response =
      await ApiCalling.fetchBillDetailApi(accId, sessionId, billId);

      if (response != null) {
        _billDetail = response;
      } else {
        debugPrint("No bill detail response");
      }
    } catch (e) {
      debugPrint("❌ Bill Details Error: $e");
    }

    _isBillLoading = false;
    notifyListeners();
  }



  bool _isDownloading = false;
  bool get isDownloading => _isDownloading;

  void setDownloading(bool value) {
    _isDownloading = value;
    notifyListeners();
  }

  ///  Download Bill
  Future<void> downloadBill(BuildContext context,
      String sessionId, String billId, String accId) async {
    setDownloading(true);
    try {
      // Step 1: Call billDownloadApi to get file path
      final res = await ApiCalling.billDownloadApi(sessionId, billId, accId);
      if (res == null || res.error != 0 || res.filePath == null) {
        // showToast(res?.message ?? "Download failed");
        setDownloading(false);
        return;
      }

      final fileUrl = res.filePath!;
      final dir = await getApplicationDocumentsDirectory();
      final savePath = '${dir.path}/receipt_${billId}.pdf';

      // Step 2: Download file
      final success = await downloadFile(fileUrl, savePath);
      if (success) {
        CustomSnackBar.showSuccess(
            context: context,
            message: "File downloaded successfully!"
        );
        // showToast("File downloaded successfully!");
        await OpenFilex.open(savePath);
      } else {
        CustomSnackBar.showError(
            context: context,
            message: "Failed to download file"
        );
        // showToast("Failed to download file");
      }
    } catch (e) {
      debugPrint("❌ Bill download error: $e");
      CustomSnackBar.showError(
          context: context,
          message: "Error downloading file"
      );
      // showToast("Error downloading file");

    } finally {
      setDownloading(false);
    }
  }

  ///  File Downloader
  Future<bool> downloadFile(String apiUrl, String savePath) async {
    try {
      final response = await get(apiUrl, {}); //  Using your get() helper
      if (response != null && response.statusCode == 200) {
        final file = File(savePath);
        await file.writeAsBytes(response.bodyBytes);
        return true;
      } else {
        debugPrint("❌ Failed to download file: ${response?.statusCode}");
        return false;
      }
    } catch (e) {
      debugPrint("❌ File download error: $e");
      return false;
    }
  }


  ///  Download Payment Receipt
  Future<void> downloadPaymentReceipt(
      BuildContext context,
      String sessionId,
      String ledgerId,
      String accId,
      ) async {
    setDownloading(true);
    try {
      // Step 1: Call paymentReceiptDownloadApi to get file URL/path
      final res = await ApiCalling.paymentReceiptDownloadApi(sessionId, ledgerId, accId);
      if (res == null || res.error != 0 || res.filePath == null) {
        CustomSnackBar.showError(
          context: context,
          message: res?.message ?? "Download failed",
        );
        setDownloading(false);
        return;
      }

      final fileUrl = res.filePath!;
      final dir = await getApplicationDocumentsDirectory();
      final savePath = '${dir.path}/payment_receipt_$ledgerId.pdf';

      // Step 2: Download file using helper
      final success = await downloadFile(fileUrl, savePath);

      if (success) {
        CustomSnackBar.showSuccess(
          context: context,
          message: "Payment receipt downloaded successfully!",
        );
        await OpenFilex.open(savePath);
      } else {
        CustomSnackBar.showError(
          context: context,
          message: "Failed to download payment receipt",
        );
      }
    } catch (e) {
      debugPrint("❌ Payment receipt download error: $e");
      CustomSnackBar.showError(
        context: context,
        message: "Error downloading payment receipt",
      );
    } finally {
      setDownloading(false);
    }
  }


  // ---------------------------------------------------------------------------
  // 🔹 Clear All Data (optional helper)
  void clearAll() {
    _transactionList = null;
    _paymentDetail = null;
    _billDetail = null;
    _errorMessage = null;
    notifyListeners();
  }

}
