package inventory;

import inventory.DiscountCalculator.DiscountResult;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Main business logic class that manages inventory operations.
 * Requirements:
 * - Use ProductFactory for creating products
 * - Use DiscountCalculator for sales with discounts
 * - Maintain product collection
 * - Provide inventory operations and statistics
 */
public class InventoryManager {

    private final Map<String, Product> products;

    public InventoryManager() {
        products = new HashMap<>();
    }

    /**
     * Add product to inventory using Factory pattern
     * @param id - product identifier
     * @param name - product name
     * @param type - product type
     * @param price - product price
     * @param quantity - initial quantity
     * @return True if product was added, false otherwise
     */
    public boolean addProduct(String id, String name, String type, double price, int quantity) {
        try {
            Product product = ProductFactory.createProduct(id, name, type, price, quantity);
            products.put(id, product);
            System.out.println("Product added successfully: " + product);
            return true;
        } catch (IllegalArgumentException e) {
            System.out.println("Error adding product: " + e.getMessage());
            return false;
        }
    }

    /**
     * @param id - product identifier
     * @param quantity - quantity to sell
     * @param discountType - type of discount to apply
     * @return True if book was sold, False if there was an error
     */
    public boolean sellProduct(String id, int quantity, String discountType) {
        if (!productExists(id)) {
            System.out.println("Product not found: " + id);
            return false;
        }

        Product product = products.get(id);

        if (!product.isInStock() || product.getQuantity() < quantity) {
            System.out.println("Insufficient stock for product: " + id);
            return false;
        }

        // Calculate discount using Strategy pattern
        DiscountResult discount =
                DiscountCalculator.calculateDiscount(product, quantity, discountType);

        // Calculate total and apply discount
        double totalPrice = product.getPrice() * quantity;
        double finalPrice = totalPrice - discount.getDiscountAmount();

        // Update inventory
        product.sell(quantity);

        // Display sale information
        displaySalesSummary(product, quantity, totalPrice, finalPrice, discount);

        return true;
    }

    /**
     * Add stock to existing product
     * @param id - product identifier
     * @param quantity - quantity to add
     * @return True if stock was added, False if there was an error
     */
    public boolean addStock(String id, int quantity) {
        Product product = products.get(id);
        if (product == null) {
            System.out.println("Product not found: " + id);
            return false;
        }

        product.addStock(quantity);

        System.out.printf("Added %d items to product %s%n", quantity, product);

        return true;
    }

    /**
     * Display all products in inventory
     */
    public void viewInventory() {
        System.out.println("Inventory:");
        if (products.isEmpty()) {
            System.out.println("Inventory is empty.");
            return;
        }

        for (Product product : products.values().stream().sorted(Comparator.comparing(Product::getId)).toList()) {
            System.out.printf("\t%s%n",product);
        }
    }

    /**
     * Calculate total inventory value
     * @return total value of all products
     */
    public double getInventoryValue() {
        return products.values().stream().mapToDouble(p -> p.getQuantity() * p.getPrice()).sum();
    }

    /**
     * Get products with low stock
     * @param threshold - minimum stock level
     * @return list of products below threshold
     */
    public List<Product> getLowStockProducts(int threshold) {
        return products.values().stream().filter(p -> p.getQuantity() < threshold).toList();
    }

    /**
     * Display inventory statistics
     */
    public void viewStatistics() {
        System.out.printf("Total products: %d%n", products.size());
        System.out.printf("Total inventory value: %f%n", getInventoryValue());

        List<Product> lowStock = getLowStockProducts(5);
        if (lowStock.isEmpty()) {
            System.out.println("No products low on stock.");
        } else {
            System.out.println("Products low on stock (<5):");
            for (Product product : lowStock) {
                System.out.printf("\tProduct: %s (quantity: %d, price: %f)%n", product.getName(), product.getQuantity(), product.getPrice());
            }
        }
    }

    public boolean productExists(String id) {
        return id != null && products.containsKey(id);
    }

    private void displaySalesSummary(Product product, int quantity, double originalPrice, double finalPrice, DiscountResult discountInfo) {
        System.out.printf("Sale completed:%n");
        System.out.printf("Product: %s%n", product.getName());
        System.out.printf("Quantity: %d%n", quantity);
        System.out.printf("Original Price: $%.2f%n", originalPrice);
        System.out.printf("Discount: $%.2f (%s)%n", discountInfo.getDiscountAmount(), discountInfo.getDescription());
        System.out.printf("Final Price: $%.2f%n", finalPrice);
    }
}