/*
 * File: src/main/java/reports/service/PatientPrescriptionService.java
 * Description: This service class provides functionality for handling prescription-related operations in the ERP reporting system.
 * It includes methods for retrieving KPI data and generating patient prescription reports based on sales and prescription data.
 */

package com.nebula.erp.reports.service;

import com.nebula.erp.reports.model.sales.Prescriptions;
import com.nebula.erp.reports.model.sales.Sales;
import com.nebula.erp.reports.model.sales.SalesItem;
import com.nebula.erp.reports.repository.product.BrandRepository;
import com.nebula.erp.reports.repository.product.CategoryRepository;
import com.nebula.erp.reports.repository.product.ProductRepository;
import com.nebula.erp.reports.repository.sales.PrescriptionItemRepository;
import com.nebula.erp.reports.repository.sales.PrescriptionsRepository;
import com.nebula.erp.reports.repository.sales.SalesItemRepository;
import com.nebula.erp.reports.repository.sales.SalesRepository;
import com.nebula.erp.reports.requestmodel.SalesRequest;
import com.nebula.erp.reports.utility.ApiResponseStructure;
import com.nebula.erp.reports.utility.CreateLogger;
import com.nebula.erp.reports.utility.JwtRequestUtils;
import com.nebula.erp.reports.utility.MoneyUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class PatientPrescriptionService {

    @Autowired
    private SalesRepository salesRepository;

    @Autowired
    private SalesItemRepository salesItemRepository;

    @Autowired
    private CategoryRepository categoryRepository;

    @Autowired
    private BrandRepository brandRepository;

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private PrescriptionsRepository prescriptionsRepository;

    @Autowired
    private PrescriptionItemRepository prescriptionItemRepository;

    @Autowired
    private JwtRequestUtils jwtRequestUtils;

    @Autowired
    private HttpServletRequest httpServletRequest;

    @Autowired
    private RestTemplate restTemplate;

    @Value("${encounter.api}")
    private String encounterApiUrl;

    @Autowired
    private CreateLogger createLogger;

    private static final String path = "/reports/patient-prescription";

    public ApiResponseStructure<Map<String, Object>> getKPIData(LocalDate fromDate, LocalDate toDate) {
        // Extract Authorization headers from the request
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.AUTHORIZATION, httpServletRequest.getHeader(HttpHeaders.AUTHORIZATION));

        String tenantName = jwtRequestUtils.getTenantNameFromHeaders(headers);

        if (fromDate != null && toDate != null) {
            // Initial values
            Integer totalPatients = 0;
            Integer totalDoctors = 0;
            Integer totalPrescriptions = 0;
            String product_name = "";
            Double averagePrescriptionValue = 0.00;

            // Convert LocalDate to LocalDateTime for comparison with created_at
            LocalDateTime fromDateTime = fromDate.atStartOfDay();
            LocalDateTime toDateTime = toDate.atTime(23, 59, 59);

            totalPrescriptions = prescriptionsRepository.countTotalPrescriptions(fromDateTime, toDateTime, tenantName);

            List<String> productIds = prescriptionItemRepository.findMostPrescribedProductIds(tenantName);

            String productId = productIds.isEmpty() ? null : productIds.get(0);
            if (productId != null) {
                try {
                    Long productLongId = Long.valueOf(productId);
                    product_name = productRepository.findProductNameById(productLongId, tenantName);
                } catch (NumberFormatException ex) {
                    product_name = "-";
                }
            }

            Double averagePrescription = prescriptionsRepository.averagePrescriptionValue(fromDateTime, toDateTime,
                    tenantName);
            if (averagePrescription != null) {
                averagePrescriptionValue = averagePrescription;
            }

            // Create the response map
            Map<String, Object> patientPrescriptionData = new LinkedHashMap<>();
            patientPrescriptionData.put("total_patients", totalPatients);
            patientPrescriptionData.put("total_prescriptions", totalPrescriptions);
            patientPrescriptionData.put("top_prescribed_product", product_name);
            patientPrescriptionData.put("average_prescription_value",
                    MoneyUtils.truncateToTwoDecimals(averagePrescriptionValue * 100.0) / 100.0);
            patientPrescriptionData.put("total_doctors", totalDoctors);

            // Create and return the structured ApiResponseStructure
            return new ApiResponseStructure<>("Success", 200, "Data retrieved.", patientPrescriptionData);
        }
        createLogger.createLogger("error", path, "GET", "", "");
        return new ApiResponseStructure<>("Failure", 500, "Please provide start-date and end-date with valid dates.",
                Collections.emptyMap());
    }

    @Transactional(transactionManager = "salesTransactionManager")
    public ApiResponseStructure<Map<String, Object>> getPatientPrescriptionReport(SalesRequest salesRequest,
            String reportType) {
        // Extract Authorization headers from the request
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.AUTHORIZATION, httpServletRequest.getHeader(HttpHeaders.AUTHORIZATION));

        String tenantName = jwtRequestUtils.getTenantNameFromHeaders(headers);

        // Create an HttpEntity with the extracted headers
        HttpEntity<String> entity = new HttpEntity<>(headers);

        // Validate presence of fromDate and toDate
        if (salesRequest.getStartDate() == null || salesRequest.getEndDate() == null) {
            createLogger.createLogger("error", path, "POST", "Both 'startDate' and 'endDate' must be provided.", "");
            return new ApiResponseStructure<>("Error", HttpStatus.BAD_REQUEST.value(),
                    "Both 'startDate' and 'endDate' must be provided.", new HashMap<>());
        }

        // Check the data types for getStartDate() and getEndDate()
        LocalDate fromDate = salesRequest.getStartDate(); // Ensure this is LocalDate
        LocalDate toDate = salesRequest.getEndDate(); // Ensure this is LocalDate

        // Convert LocalDate to LocalDateTime
        LocalDateTime fromDateTime = fromDate.atStartOfDay();
        LocalDateTime toDateTime = toDate.atTime(23, 59, 59);

        // Switch cases to handle various report type
        switch (reportType) {
            case "patientPrescriptionHistory":
            case "prescriptionSummaryByDoctor":
                // Create a specification for the query
                Specification<Prescriptions> spec = Specification.where(null);

                // Add tenant name filtering
                spec = spec
                        .and((root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("tenant"), tenantName));

                // Add date range filtering
                if (salesRequest.getStartDate() != null && salesRequest.getEndDate() != null) {
                    spec = spec.and((root, query, criteriaBuilder) -> criteriaBuilder.between(root.get("created_at"),
                            fromDateTime, toDateTime));
                }

                // Add dynamic conditions
                if (salesRequest.getConditions() != null) {
                    for (SalesRequest.Condition condition : salesRequest.getConditions()) {
                        switch (condition.getOperator()) {
                            case "equals":
                                spec = spec.and((root, query, criteriaBuilder) -> criteriaBuilder
                                        .equal(root.get(condition.getField()), condition.getValue()));
                                break;
                            case "greaterThan":
                                spec = spec.and((root, query, criteriaBuilder) -> criteriaBuilder.greaterThan(
                                        root.get(condition.getField()), (Comparable) condition.getValue()));
                                break;
                            case "lessThan":
                                spec = spec.and((root, query, criteriaBuilder) -> criteriaBuilder
                                        .lessThan(root.get(condition.getField()), (Comparable) condition.getValue()));
                                break;
                            case "greaterThanOrEquals":
                                spec = spec.and((root, query, criteriaBuilder) -> criteriaBuilder.greaterThanOrEqualTo(
                                        root.get(condition.getField()), (Comparable) condition.getValue()));
                                break;
                            case "lessThanOrEquals":
                                spec = spec.and((root, query, criteriaBuilder) -> criteriaBuilder.lessThanOrEqualTo(
                                        root.get(condition.getField()), (Comparable) condition.getValue()));
                                break;
                            default:
                                createLogger.createLogger("error", path, "POST", "", "");
                                throw new IllegalArgumentException(
                                        "Operator " + condition.getOperator() + " is not supported.");
                        }
                    }
                }

                // Fetch the data with pagination for prescription items
                Pageable pageable = PageRequest.of(salesRequest.getPage() != null ? salesRequest.getPage() : 0, // Page
                                                                                                                // number
                                                                                                                // is
                                                                                                                // zero-based
                        salesRequest.getSize() != null ? salesRequest.getSize() : 20);

                Page<Prescriptions> prescriptionPage = prescriptionsRepository.findAll(spec, pageable);

                List<Map<String, Object>> prescriptionDataList = prescriptionPage.getContent().stream()
                        .map(prescriptionData -> {
                            Map<String, Object> itemData = new LinkedHashMap<>();

                            // Add prescription-related fields to itemData
                            itemData.put("prescription_id", prescriptionData.getId());
                            itemData.put("patient_id", prescriptionData.getPatient_id());
                            itemData.put("doctor_id", prescriptionData.getDoctor_id());
                            itemData.put("encounter_id", prescriptionData.getEncounter_id());
                            itemData.put("custom_encounter_id", prescriptionData.getCustom_encounter_id());

                            // Get patient and doctor name by encounter ID
                            try {
                                Map<String, Object> encounterData = restTemplate
                                        .exchange(encounterApiUrl + prescriptionData.getEncounter_id(), HttpMethod.GET,
                                                entity, Map.class)
                                        .getBody();
                                Map<String, Object> encounterItem = (Map<String, Object>) encounterData.get("data");

                                if (encounterItem != null) {
                                    itemData.put("patient_name", encounterItem.get("patient_name"));
                                    itemData.put("class_name", encounterItem.get("class_name"));
                                    itemData.put("doctor_name", encounterItem.get("practitioner_name"));
                                } else {
                                    itemData.put("patient_name", "-");
                                    itemData.put("class_name", "-");
                                }
                            } catch (HttpClientErrorException | HttpServerErrorException ex) {
                                createLogger.createLogger("error", path, "POST", ex.getMessage(), "");
                                ;
                                if (ex.getStatusCode().value() == 500 || ex.getStatusCode().value() == 404) {
                                    itemData.put("patient_name", "-");
                                    itemData.put("class_name", "-");
                                } else {
                                    createLogger.createLogger("error", path, "POST", ex.getMessage(), "");
                                    ;
                                    throw ex;
                                }
                            }

                            itemData.put("prescription_date", String.valueOf(prescriptionData.getDate()));

                            // Map sales items
                            List<Map<String, Object>> prescriptionItemsData = prescriptionData.getPrescription_items()
                                    .stream()
                                    .map(item -> {
                                        Map<String, Object> itemsData = new LinkedHashMap<>();
                                        if (item.getProduct_id() != null
                                                && !item.getProduct_id().trim().isEmpty()
                                                && "product".equals(item.getType())) {

                                            Long productId = Long.valueOf(item.getProduct_id().trim());
                                            itemsData.put("product_id", productId);
                                            String productName = productRepository.findProductNameById(productId,
                                                    tenantName);
                                            Long categoryId = productRepository.findCategoryIdByProductId(productId,
                                                    tenantName);
                                            Long brandId = productRepository.findBrandIdByProductId(productId,
                                                    tenantName);
                                            String categoryName = categoryRepository.findCategoryNameById(categoryId,
                                                    tenantName);
                                            String brandName = brandRepository.findBrandNameById(brandId, tenantName);
                                            itemsData.put("product_name", productName);
                                            itemsData.put("category_id", categoryId);
                                            itemsData.put("category_name", categoryName);
                                            itemsData.put("brand_id", brandId);
                                            itemsData.put("brand_name", brandName);
                                            itemsData.put("quantity_prescribed", item.getQuantity());
                                        }
                                        return itemsData;
                                    }).collect(Collectors.toList());

                            itemData.put("prescriptions_items", prescriptionItemsData);
                            return itemData;
                        }).collect(Collectors.toList());

                // Prepare pagination details
                Map<String, Object> pagination = new LinkedHashMap<>();
                pagination.put("currentPage", prescriptionPage.getNumber() + 1); // Page number is 0-based
                pagination.put("totalPages", prescriptionPage.getTotalPages());
                pagination.put("pageSize", pageable.getPageSize());
                pagination.put("totalRecords", prescriptionPage.getTotalElements());

                // Prepare column details
                Map<String, Object> column = new LinkedHashMap<>();
                column.put("prescription_id", "PRESCRIPTION ID");
                column.put("patient_id", "PATIENT ID");
                column.put("patient_name", "PATIENT NAME");
                column.put("doctor_id", "DOCTOR ID");
                column.put("doctor_name", "DOCTOR NAME");
                column.put("encounter_id", "ENCOUNTER ID");
                column.put("class_name", "CLASS NAME");
                column.put("prescription_date", "PRESCRIPTION DATE");
                column.put("product_id", "PRODUCT ID");
                column.put("product_name", "PRODUCT NAME");
                column.put("category_id", "CATEGORY ID");
                column.put("category_name", "CATEGORY NAME");
                column.put("brand_id", "BRAND ID");
                column.put("brand_name", "BRAND NAME");
                column.put("quantity_prescribed", "QUANTITY PRESCRIBED");

                // Initial values
                Integer totalPatients = 0;
                Integer totalPrescriptions = 0;
                String topPrescribedProduct = "";
                totalPrescriptions = prescriptionsRepository.countTotalPrescriptions(fromDateTime, toDateTime,
                        tenantName);
                List<String> productIds = prescriptionItemRepository.findMostPrescribedProductIds(tenantName);

                String productId = productIds.isEmpty() ? null : productIds.get(0);
                topPrescribedProduct = "-";
                if (productId != null) {
                    try {
                        Long productLongId = Long.valueOf(productId);
                        topPrescribedProduct = productRepository.findProductNameById(productLongId, tenantName);
                    } catch (NumberFormatException ignored) {
                    }
                }

                // Prepare summary details
                Map<String, Object> summary = new LinkedHashMap<>();
                summary.put("totalPatients", totalPatients);
                summary.put("totalPrescriptionsIssued", totalPrescriptions);
                summary.put("topPrescribedProduct", topPrescribedProduct);

                // Prepare response data
                Map<String, Object> prescriptionData = new LinkedHashMap<>();
                prescriptionData.put("module", "sales");
                prescriptionData.put("reportType", reportType);
                prescriptionData.put("startDate", String.valueOf(fromDate));
                prescriptionData.put("endDate", String.valueOf(toDate));
                prescriptionData.put("reportData", prescriptionDataList);
                prescriptionData.put("column", column);
                prescriptionData.put("pagination", pagination);
                prescriptionData.put("summary", summary);

                // Create and return the structured ApiResponseStructure
                return new ApiResponseStructure<>("Success", 200, "Data retrieved.", prescriptionData);
            case "patientSales":
                // Create a specification for the query
                Specification<Sales> specs = Specification.where(null);

                // Add tenant name filtering
                specs = specs
                        .and((root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("tenant"), tenantName));

                // Add date range filtering
                if (salesRequest.getStartDate() != null && salesRequest.getEndDate() != null) {
                    specs = specs.and((root, query, criteriaBuilder) -> criteriaBuilder.between(root.get("created_at"),
                            fromDateTime, toDateTime));
                }
                // Add dynamic conditions for the daily report
                if (salesRequest.getConditions() != null) {
                    for (SalesRequest.Condition condition : salesRequest.getConditions()) {
                        switch (condition.getOperator()) {
                            case "equals":
                                specs = specs.and((root, query, criteriaBuilder) -> criteriaBuilder
                                        .equal(root.get(condition.getField()), condition.getValue()));
                                break;
                            case "greaterThan":
                                specs = specs.and((root, query, criteriaBuilder) -> criteriaBuilder.greaterThan(
                                        root.get(condition.getField()), (Comparable) condition.getValue()));
                                break;
                            case "lessThan":
                                specs = specs.and((root, query, criteriaBuilder) -> criteriaBuilder
                                        .lessThan(root.get(condition.getField()), (Comparable) condition.getValue()));
                                break;
                            case "greaterThanOrEquals":
                                specs = specs
                                        .and((root, query, criteriaBuilder) -> criteriaBuilder.greaterThanOrEqualTo(
                                                root.get(condition.getField()), (Comparable) condition.getValue()));
                                break;
                            case "lessThanOrEquals":
                                specs = specs.and((root, query, criteriaBuilder) -> criteriaBuilder.lessThanOrEqualTo(
                                        root.get(condition.getField()), (Comparable) condition.getValue()));
                                break;
                            default:
                                createLogger.createLogger("error", path, "POST", "", "runtime");
                                ;
                                throw new IllegalArgumentException(
                                        "Operator " + condition.getOperator() + " is not supported.");
                        }
                    }
                }

                // Fetch all sales items based on date range and tenant name
                pageable = PageRequest.of(salesRequest.getPage() != null ? salesRequest.getPage() : 0, // Page number is
                                                                                                       // zero-based
                        salesRequest.getSize() != null ? salesRequest.getSize() : 20);

                Page<Sales> salesPage = salesRepository.findAll(specs, pageable);

                List<Map<String, Object>> saleDataList = salesPage.getContent().stream()
                        .map(saleData -> {
                            Map<String, Object> itemData = new LinkedHashMap<>();

                            // Add sale-related fields to itemData
                            itemData.put("sales_id", saleData.getId());
                            itemData.put("patient_id", saleData.getPatient_id());
                            itemData.put("encounter_id", saleData.getEncounter_id());
                            itemData.put("custom_encounter_id", saleData.getCustom_encounter_id());
                            itemData.put("patient_name", saleData.getPatient_name());
                            itemData.put("customer_name", saleData.getCustomer_name());
                            itemData.put("customer_mobile", saleData.getCustomer_mobile());
                            itemData.put("total_amount", MoneyUtils.truncateToTwoDecimals(saleData.getTotal_amount()));
                            itemData.put("payment_status", saleData.getPayment_status());

                            // Get patient and doctor name by encounter ID
                            try {
                                Map<String, Object> encounterData = restTemplate
                                        .exchange(encounterApiUrl + saleData.getEncounter_id(), HttpMethod.GET, entity,
                                                Map.class)
                                        .getBody();
                                Map<String, Object> encounterItem = (Map<String, Object>) encounterData.get("data");

                                if (encounterItem != null) {
                                    itemData.put("patient_name", encounterItem.get("patient_name"));
                                    itemData.put("class_name", encounterItem.get("class_name"));
                                } else {
                                    itemData.put("patient_name", "-");
                                    itemData.put("class_name", "-");
                                }
                            } catch (HttpClientErrorException | HttpServerErrorException ex) {
                                createLogger.createLogger("error", path, "POST", ex.getMessage(), "");
                                ;
                                if (ex.getStatusCode().value() == 500 || ex.getStatusCode().value() == 404) {
                                    itemData.put("patient_name", "-");
                                    itemData.put("class_name", "-");
                                } else {
                                    createLogger.createLogger("error", path, "POST", ex.getMessage(), "");
                                    ;
                                    throw ex;
                                }
                            }

                            itemData.put("sales_date", String.valueOf(saleData.getCreated_at()));

                            // Map sales items
                            List<Map<String, Object>> salesItemsData = saleData.getSales_items().stream()
                                    .map(item -> {
                                        Map<String, Object> itemsData = new LinkedHashMap<>();
                                        if ("product".equals(item.getType())
                                                && item.getProduct_id() != null
                                                && !item.getProduct_id().trim().isEmpty()) {

                                            Long product_Id = Long.valueOf(item.getProduct_id().trim());
                                            itemsData.put("product_id", product_Id);
                                            String productName = productRepository.findProductNameById(product_Id,
                                                    tenantName);
                                            Long categoryId = productRepository.findCategoryIdByProductId(product_Id,
                                                    tenantName);
                                            Long brandId = productRepository.findBrandIdByProductId(product_Id,
                                                    tenantName);
                                            String categoryName = categoryRepository.findCategoryNameById(categoryId,
                                                    tenantName);
                                            String brandName = brandRepository.findBrandNameById(brandId, tenantName);
                                            itemsData.put("product_name", productName);
                                            itemsData.put("category_id", categoryId);
                                            itemsData.put("category_name", categoryName);
                                            itemsData.put("brand_id", brandId);
                                            itemsData.put("brand_name", brandName);
                                            itemsData.put("quantity", item.getQuantity());
                                            itemsData.put("total_price",
                                                    MoneyUtils.truncateToTwoDecimals(item.getTotal_price()));
                                            itemsData.put("unit_price", item.getUnit_price());
                                        }
                                        return itemsData;
                                    }).collect(Collectors.toList());

                            itemData.put("sales_items", salesItemsData);
                            return itemData;
                        }).collect(Collectors.toList());

                // Prepare pagination details
                Map<String, Object> salesPagination = new LinkedHashMap<>();
                salesPagination.put("currentPage", salesPage.getNumber() + 1); // Page number is 0-based
                salesPagination.put("totalPages", salesPage.getTotalPages());
                salesPagination.put("pageSize", pageable.getPageSize());
                salesPagination.put("totalRecords", salesPage.getTotalElements());

                // Prepare column details
                Map<String, Object> columns = new LinkedHashMap<>();
                columns.put("sales_id", "SALES ID");
                columns.put("sales_date", "SALES DATE");
                columns.put("patient_id", "PATIENT ID");
                columns.put("patient_name", "PATIENT NAME");
                columns.put("customer_name", "CUSTOMER NAME");
                columns.put("customer_mobile", "CUSTOMER MOBILE");
                columns.put("total_amount", "TOTAL AMOUNT");
                columns.put("payment_status", "PAYMENT STATUS");
                columns.put("encounter_id", "ENCOUNTER ID");
                columns.put("class_name", "CLASS NAME");
                columns.put("product_id", "PRODUCT ID");
                columns.put("product_name", "PRODUCT NAME");
                columns.put("category_id", "CATEGORY ID");
                columns.put("category_name", "CATEGORY NAME");
                columns.put("brand_id", "BRAND ID");
                columns.put("brand_name", "BRAND NAME");
                columns.put("quantity", "QUANTITY");
                columns.put("total_price", "TOTAL PRICE");
                columns.put("unit_price", "UNIT PRICE");

                // Initial values
                Double totalSales = 0.00;
                Long totalItemsSold = 0L;
                String topSellingProduct = "";

                // Calculate summary details
                totalSales = salesPage.getContent().stream().mapToDouble(Sales::getTotal_amount).sum();

                totalItemsSold = salesPage.getContent().stream().flatMap(sales -> sales.getSales_items().stream())
                        .count();
                // long highQuantityProductId = salesPage.getContent().stream()
                // .flatMap(sales -> sales.getSales_items().stream())
                // .max(Comparator.comparingInt(SalesItem::getQuantity))
                // .map(SalesItem::getProduct_id)
                // .orElse(-1L); // Default to -1 if no product found
                //
                // if (highQuantityProductId != -1L) {
                // topSellingProduct =
                // productRepository.findProductNameById(highQuantityProductId, tenantName);
                // }

                Optional<SalesItem> topSellingItem = salesPage.getContent().stream()
                        .flatMap(sales -> sales.getSales_items().stream())
                        .max(Comparator.comparingInt(SalesItem::getQuantity)); // Find item with max quantity

                String topSellingName = topSellingItem.map(item -> {
                    if ("product".equals(item.getType())
                            && item.getProduct_id() != null
                            && !item.getProduct_id().trim().isEmpty()) {

                        return productRepository.findProductNameById(
                                Long.valueOf(item.getProduct_id().trim()),
                                tenantName);
                    } else if ("service".equals(item.getType()) || "package".equals(item.getType())) {
                        // return
                        // externalApiService.getServiceOrPackageNameById(item.getProduct_id().toString(),
                        // tenantName);
                    }
                    return "Unknown"; // Fallback case
                }).orElse("No top-selling item found");

                // Prepare summary details
                Map<String, Object> summaries = new LinkedHashMap<>();
                summaries.put("totalSales", MoneyUtils.truncateToTwoDecimals(totalSales));
                summaries.put("totalItemsSold", totalItemsSold);
                summaries.put("topSellingProduct", topSellingName);

                // Prepare response data
                Map<String, Object> patientSalesData = new LinkedHashMap<>();
                patientSalesData.put("module", "sales");
                patientSalesData.put("reportType", reportType);
                patientSalesData.put("startDate", String.valueOf(fromDate));
                patientSalesData.put("endDate", String.valueOf(toDate));
                patientSalesData.put("reportData", saleDataList);
                patientSalesData.put("column", columns);
                patientSalesData.put("pagination", salesPagination);
                patientSalesData.put("summary", summaries);

                // Create and return the structured ApiResponseStructure
                return new ApiResponseStructure<>("Success", 200, "Data retrieved.", patientSalesData);
            default:
                createLogger.createLogger("error", path, "POST", "Invalid report type provided.", "");
                return new ApiResponseStructure<>("Error", 400, "Invalid report type provided.", new HashMap<>());
        }
    }

}