import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/features/my_invoices/models/get_invoice_details_response_model.dart';
import 'package:hmg_patient_app_new/features/my_invoices/models/get_invoices_list_response_model.dart';
import 'package:hmg_patient_app_new/features/my_invoices/models/get_pharmacy_invoices_response_model.dart';
import 'package:hmg_patient_app_new/features/my_invoices/my_invoices_repo.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';

enum InvoiceFilterType { all, hospital, clinic, doctor }

class MyInvoicesViewModel extends ChangeNotifier {
  bool isInvoicesListLoading = false;
  bool isInvoiceDetailsLoading = false;
  bool isPharmacyInvoicesLoading = false;

  MyInvoicesRepo myInvoicesRepo;
  ErrorHandlerService errorHandlerService;
  NavigationService navServices;

  List<GetInvoicesListResponseModel> allInvoicesList = [];
  List<GetInvoicesListResponseModel> _originalInvoicesList = [];
  List<GetPharmacyInvoicesResponseModel> allPharmacyInvoicesList = [];
  List<GetPharmacyInvoicesResponseModel> _originalPharmacyInvoicesList = [];
  InvoiceFilterType currentFilter = InvoiceFilterType.all;
  late GetInvoiceDetailsResponseModel invoiceDetailsResponseModel;

  // Filter bottom sheet properties
  List<String> filterDisplayList = [];
  List<String> _filterOriginalList = [];
  TextEditingController filterSearchController = TextEditingController();
  String? selectedFilterItem;

  String? downloadInvoicePDFBase64 = "";
  String? downloadPharmacyInvoicePDFBase64 = "";

  int selectedTabIndex = 0;

  MyInvoicesViewModel({required this.myInvoicesRepo, required this.errorHandlerService, required this.navServices});

  setInvoicesListLoading() {
    isInvoicesListLoading = true;
    isPharmacyInvoicesLoading = true;
    allInvoicesList.clear();
    allPharmacyInvoicesList.clear();
    _originalInvoicesList.clear();
    currentFilter = InvoiceFilterType.all;
    onTabChanged(0);
    notifyListeners();
  }

  setInvoiceDetailLoading() {
    isInvoiceDetailsLoading = true;
    notifyListeners();
  }

  void onTabChanged(int index) {
    selectedTabIndex = index;
    notifyListeners();
  }

  Future<void> getAllInvoicesList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await myInvoicesRepo.getAllInvoicesList();

    result.fold(
      (failure) async {
        isInvoicesListLoading = false;
        notifyListeners();
      },
      (apiResponse) {
        _originalInvoicesList =[];
        allInvoicesList =[];
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          _originalInvoicesList = apiResponse.data!;
          _originalInvoicesList.sort((a, b) => b.appointmentDate!.compareTo(a.appointmentDate!));
          allInvoicesList = List.from(_originalInvoicesList);
          isInvoicesListLoading = false;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getAllPharmacyInvoices({Function(dynamic)? onSuccess, Function(String)? onError}) async {
    isPharmacyInvoicesLoading = true;
    allPharmacyInvoicesList.clear();
    notifyListeners();

    final result = await myInvoicesRepo.getAllPharmacyInvoices();

    result.fold(
      (failure) async {
        isPharmacyInvoicesLoading = false;
        notifyListeners();
        if (onError != null) {
          onError(failure.message);
        }
      },
      (apiResponse) {
        _originalPharmacyInvoicesList = [];
        allPharmacyInvoicesList = [];
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          _originalPharmacyInvoicesList = apiResponse.data ?? [];
          _originalPharmacyInvoicesList.sort((a, b) => (b.appointmentDate ?? '').compareTo(a.appointmentDate ?? ''));
          allPharmacyInvoicesList = List.from(_originalPharmacyInvoicesList);
          isPharmacyInvoicesLoading = false;
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> getInvoiceDetails({required num appointmentNo, required num invoiceNo, required int projectID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await myInvoicesRepo.getInvoiceDetails(appointmentNo: appointmentNo, invoiceNo: invoiceNo, projectID: projectID);
    result.fold(
      (failure) async {
        isInvoiceDetailsLoading = false;
        notifyListeners();
        if (onError != null) {
          onError(failure.message);
        }
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          invoiceDetailsResponseModel = apiResponse.data!;
          isInvoiceDetailsLoading = false;

          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> downloadInvoicePDF({required String setupId, required int invoiceNo, required int projectID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await myInvoicesRepo.downloadInvoice(setupId: setupId, invoiceNo: invoiceNo, projectID: projectID);

    result.fold(
      (failure) async {
        if (onError != null) {
          onError(failure.message);
        }
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          if (apiResponse.data != null && apiResponse.data!.isNotEmpty) {
            downloadInvoicePDFBase64 = apiResponse.data!;
          } else {
            downloadInvoicePDFBase64 = "";
          }
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> sendInvoiceEmail({required num appointmentNo, required int projectID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await myInvoicesRepo.sendInvoiceEmail(appointmentNo: appointmentNo, projectID: projectID);

    result.fold(
      (failure) async {
        notifyListeners();
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          notifyListeners();
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  Future<void> downloadPharmacyInvoicePDF({required String setupId, required int invoiceNo, required int projectID, required dynamic locationID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
    final result = await myInvoicesRepo.downloadPharmacyInvoice(setupId: setupId, invoiceNo: invoiceNo, projectID: projectID, locationID: locationID);

    result.fold(
      (failure) async {
        if (onError != null) {
          onError(failure.message);
        }
      },
      (apiResponse) {
        if (apiResponse.messageStatus == 2) {
          // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
        } else if (apiResponse.messageStatus == 1) {
          if (apiResponse.data != null && apiResponse.data!.isNotEmpty) {
            downloadPharmacyInvoicePDFBase64 = apiResponse.data!;
          } else {
            downloadPharmacyInvoicePDFBase64 = "";
          }
          if (onSuccess != null) {
            onSuccess(apiResponse);
          }
        }
      },
    );
  }

  void filterInvoices(InvoiceFilterType filterType) {
    currentFilter = filterType;
    
    switch (filterType) {
      case InvoiceFilterType.all:
        allInvoicesList = List.from(_originalInvoicesList);
        break;
      case InvoiceFilterType.hospital:
        allInvoicesList = _originalInvoicesList.where((invoice) {
          return invoice.projectName != null && invoice.projectName!.isNotEmpty;
        }).toList();
        // Group by hospital (projectName) and sort
        allInvoicesList.sort((a, b) {
          int projectComparison = (a.projectName ?? '').compareTo(b.projectName ?? '');
          if (projectComparison != 0) return projectComparison;
          return b.appointmentDate!.compareTo(a.appointmentDate!);
        });
        break;
      case InvoiceFilterType.clinic:
        allInvoicesList = _originalInvoicesList.where((invoice) {
          return invoice.clinicName != null && invoice.clinicName!.isNotEmpty;
        }).toList();
        // Group by clinic (clinicName) and sort
        allInvoicesList.sort((a, b) {
          int clinicComparison = (a.clinicName ?? '').compareTo(b.clinicName ?? '');
          if (clinicComparison != 0) return clinicComparison;
          return b.appointmentDate!.compareTo(a.appointmentDate!);
        });
        break;
      case InvoiceFilterType.doctor:
        allInvoicesList = _originalInvoicesList.where((invoice) {
          return invoice.doctorName != null && invoice.doctorName!.isNotEmpty;
        }).toList();
        // Group by doctor (doctorName) and sort
        allInvoicesList.sort((a, b) {
          int doctorComparison = (a.doctorName ?? '').compareTo(b.doctorName ?? '');
          if (doctorComparison != 0) return doctorComparison;
          return b.appointmentDate!.compareTo(a.appointmentDate!);
        });
        break;
    }
    
    notifyListeners();
  }

  void filterInvoicesByHospital(String hospitalName) {
    currentFilter = InvoiceFilterType.hospital;
    allInvoicesList = _originalInvoicesList
        .where((invoice) => invoice.projectName == hospitalName)
        .toList();
    allInvoicesList.sort((a, b) => b.appointmentDate!.compareTo(a.appointmentDate!));
    notifyListeners();
  }

  void filterInvoicesByClinic(String clinicName) {
    currentFilter = InvoiceFilterType.clinic;
    allInvoicesList = _originalInvoicesList
        .where((invoice) => invoice.clinicName == clinicName)
        .toList();
    allInvoicesList.sort((a, b) => b.appointmentDate!.compareTo(a.appointmentDate!));
    notifyListeners();
  }

  void filterInvoicesByDoctor(String doctorName) {
    currentFilter = InvoiceFilterType.doctor;
    allInvoicesList = _originalInvoicesList
        .where((invoice) => invoice.doctorName == doctorName)
        .toList();
    allInvoicesList.sort((a, b) => b.appointmentDate!.compareTo(a.appointmentDate!));
    notifyListeners();
  }

  List<GetInvoicesListResponseModel> getOriginalInvoicesList() {
    return _originalInvoicesList;
  }

  // Filter bottom sheet methods
  void prepareFilterList(InvoiceFilterType filterType) {
    Set<String> uniqueItems = {};
    
    for (var invoice in _originalInvoicesList) {
      String? itemName;
      if (filterType == InvoiceFilterType.hospital) {
        itemName = invoice.projectName;
      } else if (filterType == InvoiceFilterType.clinic) {
        itemName = invoice.clinicName;
      } else if (filterType == InvoiceFilterType.doctor) {
        itemName = getIt<AppState>().isArabic() ? invoice.doctorNameN : invoice.doctorName;
      }
      
      if (itemName != null && itemName.isNotEmpty) {
        uniqueItems.add(itemName);
      }
    }
    
    _filterOriginalList = uniqueItems.toList()..sort();
    filterDisplayList = List.from(_filterOriginalList);
    filterSearchController.clear();
    selectedFilterItem = null;
    notifyListeners();
  }

  void searchFilterItems(String query) {
    if (query.isEmpty) {
      filterDisplayList = List.from(_filterOriginalList);
    } else {
      filterDisplayList = _filterOriginalList
          .where((item) => item.toLowerCase().contains(query.toLowerCase()))
          .toList();
    }
    notifyListeners();
  }

  void clearFilterSearch() {
    filterSearchController.clear();
    filterDisplayList = List.from(_filterOriginalList);
    notifyListeners();
  }

  void selectFilterItem(String item) {
    selectedFilterItem = item;
    notifyListeners();
  }
}
