package dev.service;

import dev.dao.MenuItemDao;
import dev.dao.OrderDao;
import dev.dao.OrderDetailDao;
import dev.model.MenuItem;
import dev.model.Order;
import dev.model.OrderDetail;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class OrderService {

    private final MenuItemDao menuItemDao = new MenuItemDao();
    private final OrderDao orderDao = new OrderDao();
    private final OrderDetailDao orderDetailDao = new OrderDetailDao();

    private final Scanner scanner;

    /** The Scanner is shared with the console UI so input stays consistent. */
    public OrderService(Scanner scanner) {
        this.scanner = scanner;
    }

    /**
     * Lets the logged-in user build an order item by item, then stores the
     * Order and its OrderDetail rows in the database and prints a receipt.
     */
    public void placeOrder(int userId) {

        List<MenuItem> menu = menuItemDao.findAll();
        if (menu.isEmpty()) {
            System.out.println("Sorry, there is nothing on the menu right now.");
            return;
        }

        System.out.println("\nAvailable Items:");
        for (MenuItem item : menu) {
            System.out.printf("%d. %s - $%.2f%n", item.getId(), item.getName(), item.getPrice());
        }

        // The "cart": order lines the user has chosen so far.
        List<OrderDetail> cart = new ArrayList<>();

        while (true) {
            System.out.print("\nEnter the ID of the item to add (or 0 to finish): ");
            int itemId = readInt();

            if (itemId == 0) {
                break;
            }

            MenuItem item = menuItemDao.findById(itemId);
            if (item == null) {
                System.out.println("No item with that ID. Try again.");
                continue;
            }

            System.out.print("Enter quantity: ");
            int quantity = readInt();
            if (quantity <= 0) {
                System.out.println("Quantity must be at least 1.");
                continue;
            }

            // Store the current price so the receipt stays correct later.
            OrderDetail line = new OrderDetail();
            line.setMenuItemId(item.getId());
            line.setQuantity(quantity);
            line.setPrice(item.getPrice());
            cart.add(line);

            System.out.printf("Added %dx %s to your cart.%n", quantity, item.getName());
        }

        if (cart.isEmpty()) {
            System.out.println("Your cart is empty, order cancelled.");
            return;
        }

        // Work out the grand total.
        double total = 0;
        for (OrderDetail line : cart) {
            total += line.getSubtotal();
        }

        // Save the order first so we get its generated id.
        Order order = new Order();
        order.setUserId(userId);
        order.setTotalPrice(total);

        int orderId = orderDao.save(order);
        if (orderId == -1) {
            System.out.println("Could not save the order. Please try again.");
            return;
        }

        // Now save each line with the order id we just got back.
        for (OrderDetail line : cart) {
            line.setOrderId(orderId);
            orderDetailDao.save(line);
        }

        printReceipt(orderId);
        System.out.println("Order saved successfully!");
    }

    /**
     * Reads an order back from the database and prints a detailed receipt:
     * item names, quantities, unit prices, subtotals and the grand total.
     */
    public void printReceipt(int orderId) {

        List<OrderDetail> details = orderDetailDao.findByOrderId(orderId);
        if (details.isEmpty()) {
            System.out.println("No details found for order #" + orderId);
            return;
        }

        System.out.println("\n[Order Summary / Receipt]");
        System.out.println("---------------------------------------------");
        System.out.printf("%-18s %-6s %-9s %-9s%n", "Item", "Qty", "Unit", "Total");
        System.out.println("---------------------------------------------");

        double grandTotal = 0;
        for (OrderDetail line : details) {
            MenuItem item = menuItemDao.findById(line.getMenuItemId());
            String name = (item == null) ? "(removed item)" : item.getName();

            System.out.printf("%-18s %-6d $%-8.2f $%-8.2f%n",
                    name, line.getQuantity(), line.getPrice(), line.getSubtotal());

            grandTotal += line.getSubtotal();
        }

        System.out.println("---------------------------------------------");
        System.out.printf("Final Total: $%.2f%n", grandTotal);
    }

    /** Shows every past order of a user together with what each one cost. */
    public void showOrderHistory(int userId) {

        List<Order> orders = orderDao.findByUserId(userId);

        if (orders.isEmpty()) {
            System.out.println("You have not placed any orders yet.");
            return;
        }

        System.out.println("\n===== ORDER HISTORY =====");
        for (Order order : orders) {
            System.out.printf("Order #%d  |  %s  |  Total: $%.2f%n",
                    order.getId(), order.getCreatedAt(), order.getTotalPrice());
        }
    }

    /** Reads an int safely so bad input does not crash the program. */
    private int readInt() {
        while (!scanner.hasNextInt()) {
            System.out.print("Please enter a number: ");
            scanner.next();  // throw away the bad token
        }
        return scanner.nextInt();
    }

}
