package com.nebula.erp.inventory.service;

import com.nebula.erp.inventory.model.Batch;
import com.nebula.erp.inventory.model.Inventory;
import com.nebula.erp.inventory.repository.BatchRepository;
import com.nebula.erp.inventory.repository.InventoryRepository;
import com.nebula.erp.inventory.utility.CreateLogger;
import com.nebula.erp.inventory.utility.JwtRequestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpEntity;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.data.domain.Page;

@Service
public class InventoryService {

        @Autowired
        private InventoryRepository inventoryRepository;

        @Autowired
        private BatchRepository batchRepository;

        @Autowired
        private JwtRequestUtils jwtRequestUtils;

        @Autowired
        private RestTemplate restTemplate;

        @Value("${product.api}")
        private String productAPI;

        @Autowired
        private CreateLogger createLogger;

        private static final String path = "/inventories";

        public Map<String, Object> getAllInventories(int page, int size, Long productId, Long brandId,
                        Long categoryId, String search) {
                String tenantName = jwtRequestUtils.getTenantName();
                long totalRecords = inventoryRepository
                                .findAllByTenant(Pageable.unpaged(), tenantName)
                                .size();
                int maxPage = (int) Math.ceil((double) totalRecords / size) - 1;
                if (page > maxPage && maxPage >= 0) {
                        page = maxPage;
                }
                List<Inventory> inventories = inventoryRepository
                                .findAllByTenant(Pageable.unpaged(), tenantName);

                // Extract Authorization headers from the request
                HttpHeaders headers = jwtRequestUtils.getAuthorizationHeaders();

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

                // Execute the request with headers
                Map<String, Object> productData = restTemplate
                                .exchange(productAPI + "?page=1&size=1000", HttpMethod.GET, entity, Map.class)
                                .getBody();
                List<Map<String, Object>> products = (List<Map<String, Object>>) ((Map<String, Object>) productData
                                .get("data")).get("items");

                // Filter products by productId, brandId, and categoryId
                List<Map<String, Object>> filteredProducts = products.stream()
                                .filter(product -> {
                                        boolean matchesProduct = productId == null ||
                                                        (product.get("id") != null && product.get("id").toString()
                                                                        .equals(productId.toString()));
                                        boolean matchesBrand = brandId == null ||
                                                        (product.get("brand_id") != null && product.get("brand_id")
                                                                        .toString().equals(brandId.toString()));
                                        boolean matchesCategory = categoryId == null ||
                                                        (product.get("category_id") != null
                                                                        && product.get("category_id").toString()
                                                                                        .equals(categoryId.toString()));
                                        return matchesProduct && matchesBrand && matchesCategory;
                                })
                                .collect(Collectors.toList());

                // Extract product IDs from filtered products
                List<Long> filteredProductIds = filteredProducts.stream()
                                .map(product -> Long.valueOf(product.get("id").toString()))
                                .collect(Collectors.toList());

                // Filter inventories by product IDs
                List<Inventory> filteredInventories = inventories.stream()
                                .filter(inventory -> filteredProductIds.contains(inventory.getProduct_id()))
                                .collect(Collectors.toList());

                // Map filtered inventories to result format
                List<Map<String, Object>> result = filteredInventories.stream()
                                .map(inventory -> {
                                        Map<String, Object> itemData = new LinkedHashMap<>();
                                        itemData.put("product_id", inventory.getProduct_id());
                                        itemData.put("total_quantity", inventory.getTotal_quantity());

                                        // Find exact product
                                        Map<String, Object> exactProduct = filteredProducts.stream()
                                                        .filter(product -> product.get("id").toString()
                                                                        .equals(inventory.getProduct_id().toString()))
                                                        .findFirst()
                                                        .orElse(null);

                                        if (exactProduct != null) {
                                                itemData.put("product_name", exactProduct.get("name"));
                                                itemData.put("brand_id", exactProduct.get("brand_id"));
                                                itemData.put("brand_name", exactProduct.get("brand_name"));
                                                itemData.put("category_id", exactProduct.get("category_id"));
                                                itemData.put("category_name", exactProduct.get("category_name"));
                                                itemData.put("unit_price", exactProduct.get("selling_price"));
                                                itemData.put("tax_id", exactProduct.get("tax_id"));
                                                itemData.put("tax_rate", exactProduct.get("tax_rate"));
                                                itemData.put("hsn_code", exactProduct.get("hsn_code"));
                                        }

                                        return itemData;
                                })
                                .collect(Collectors.toList());
                // SEARCH FILTER (no length restriction)
                if (search != null && !search.trim().isEmpty()) {
                        String keyword = search.toLowerCase();

                        result = result.stream()
                                        .filter(item -> String.valueOf(item.get("product_name")).toLowerCase()
                                                        .contains(keyword)
                                                        || String.valueOf(item.get("brand_name")).toLowerCase()
                                                                        .contains(keyword)
                                                        || String.valueOf(item.get("category_name")).toLowerCase()
                                                                        .contains(keyword)
                                                        || String.valueOf(item.get("total_quantity")).contains(keyword))
                                        .collect(Collectors.toList());
                }
                // Apply pagination AFTER filtering
                int start = page * size;
                int end = Math.min(start + size, result.size());

                List<Map<String, Object>> paginatedResult = new LinkedList<>();

                if (start <= end) {
                        paginatedResult = result.subList(start, end);
                }

                Map<String, Object> response = new LinkedHashMap<>();
                response.put("items", paginatedResult);
                response.put("total", result.size());

                return response;
        }

        // Retrieve Batch by ID
        public List<Batch> getBatchById(Long id) {
                String tenantName = jwtRequestUtils.getTenantName();
                return batchRepository.findByProductIdANDTenant(id, tenantName);
        }

}