import java.util.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.scene.control.TextArea;

/**
 * @Henry Curtis
 * @version 15/07/2025
 */
public class ShopperGUI extends Application {
    private float money = 20f;
    private Stack<Item> basket = new Stack<>();
    private ArrayList<ArrayList<String>> menuItems = new ArrayList<>();

    private Label moneyDisplay = new Label(String.format("%.2f dollary doos", money));
    private TextArea textOutput = new TextArea();

    private GridPane pane = new GridPane();
    
    /**
     * creates the javafx stage and runs the giveInfo function
     */
    @Override
    public void start(Stage stage) {
        System.out.print("\u000C");
        
        pane.setPadding(new Insets(10, 10, 10, 10));
        pane.setMinSize(300, 300);
        pane.setVgap(0);
        pane.setHgap(0);
        pane.setGridLinesVisible(false);

        Scene scene = new Scene(pane, 600, 800);
        stage.setTitle("Shopper GUI");
        stage.setScene(scene);
        stage.show();

        giveInfo();
    }
    
    /**
     * reads the menu csv and creates a table containg each item and the relevant information
     */
    public void readFile() {
        try {
            File file = new File("Menu_Items.csv");
            Scanner scan = new Scanner(file);
    
            if (scan.hasNextLine()) {
                scan.nextLine(); // Skip header
            }
            
            String IDStr = "";
            String priceStr = "";
            
            Integer ID = 1;
            String category = "";
            String name = "";
            float price = 1;
    
            int rowIndex = 3;
            while (scan.hasNextLine()) {
                String nextLine = scan.nextLine().replace("\u00A0", ""); 
                String[] items = nextLine.trim().split(",");
    
                if (items.length < 4) {
                    continue;
                }
                
                ArrayList<String> row = new ArrayList<>();
                
                IDStr = items[0].trim();
                category = items[1].trim();
                name = items[2].trim();
                priceStr = items[3].trim();
                
                ID = Integer.parseInt(IDStr);
                price = Float.parseFloat(priceStr);
    
                row.add(String.valueOf(ID));
                row.add(category);
                row.add(name);
                row.add(String.valueOf(price));
                
                menuItems.add(row);
            
            }
            
            System.out.println(menuItems);
            
            scan.close();
            
        } catch (FileNotFoundException e) {
            System.out.println("File not found. Check the spelling and location of your file.");
        }
    }

    /**
     * provides the relevant information to the gui scene eg. Buttons, text areas, etc.
     */
    public void giveInfo() {
        readFile(); //runs the readfile function
        
        ArrayList<String> validCategories = new ArrayList<String>(); //creates a new string arraylist.
        
        for (int i = 1; i < menuItems.size(); i++){
            ArrayList<String> row = menuItems.get(i); //creates a "row" array with the information inside of the menuItems arrylist (takes the next row with every increment of the for loop)
            
            String category = row.get(1).trim();//sets the category variable to the coinciding value in the row arraylist
            
            if(validCategories.contains(category)) {
                continue;//continues to the next increment of the for loop if the valid categories arraylist already contains what is in the category variable
            } else {
                validCategories.add(category);//adds the category to the validCatiegor
            }
            
        }
    
        System.out.println(validCategories);
        System.out.println(validCategories.size());
        
        ArrayList<String> completedCategories = new ArrayList<String>();
        
        int largestCategorySize = 0;
        int categorySize = 0;
        
        for(int i1 = 0; i1 < validCategories.size(); i1++){
            String focusCategory = validCategories.get(i1);
            
            categorySize = 0;
            int rowIndex = 3;
            
            System.out.println("focus Category = " + focusCategory + " this loop");
            for (int i2 = 0; i2 < menuItems.size(); i2++){
                
                ArrayList<String> row = menuItems.get(i2);
                
                String IDStr = row.get(0);
                String category = row.get(1);
                String name = row.get(2);
                String priceStr = row.get(3);
                
                int ID = Integer.parseInt(IDStr);
                Float price = Float.parseFloat(priceStr);
                if (!category.equals(focusCategory)) {
                    continue;
                } else {
                    categorySize++;
                }
                
                if(largestCategorySize < categorySize){
                    largestCategorySize = categorySize;
                }
                System.out.println(category + " " + name);
                
                Item menuItem = new Item(ID, name, price, category);
                Button itemButton = new Button(name + " ($" + price + ")");
                itemButton.setOnAction(e -> handlePurchase(menuItem));
                pane.add(itemButton, completedCategories.size(), rowIndex++);
            }
            
            completedCategories.add(focusCategory);
        }
        
        pane.add(textOutput, 0, 1, validCategories.size(), 2);
        printText("Welcome to the shop!");
        printText("Undo will remove the most recent item on the basket.");
        printText("Clear will empty out the basket.");
        printText("Click finish when you are done and your order will be printed out with a summary of the total!");

        printText("\n--- Menu Items ---");
        for (ArrayList<String> row : menuItems) {
            printText(String.join(" | ", row));
        }
        
        int i = 1;
        
        pane.add(moneyDisplay, validCategories.size() - i, 0);
        
        // Add Undo button
        Button UndoButton = new Button("Undo");
        UndoButton.setOnAction(e -> handleUndo());
        if (validCategories.size() >= 3){
            pane.add(UndoButton, validCategories.size() - i , largestCategorySize + 3);
        } else {
            pane.add(UndoButton, 0, largestCategorySize + 3);
        }
        
        // Add Clear button
        Button ClearButton = new Button("Clear");
        ClearButton.setOnAction(e -> handleClear());
        if (validCategories.size() >= 3){
            pane.add(ClearButton, validCategories.size() - ++i, largestCategorySize + 3);
        } else {
            pane.add(ClearButton, 1, largestCategorySize + 3);
        }

        // Add Finish button
        Button FinishButton = new Button("Finish");
        FinishButton.setOnAction(e -> handleFinish());
        if (validCategories.size() >= 3){
            pane.add(FinishButton, validCategories.size() - ++i, largestCategorySize + 3);
        } else {
            pane.add(FinishButton, 2, largestCategorySize + 3);
        }
    }

    /**
     * 
     */
    private void handlePurchase(Item item) {
        if (money >= item.getPrice()) {
            money -= item.getPrice();
            basket.push(item);
            moneyDisplay.setText(String.format("%.2f dollary doos", money));
            printText("Added to basket: " + item.getName() + " ($" + item.getPrice() + ")");
        } else {
            printText("Not enough money for " + item.getName());
        }
    }

    /**
     * 
     */
    private void handleUndo() {
        if (!basket.isEmpty()) {
            Item item = basket.pop();
            money += item.getPrice();
            moneyDisplay.setText(String.format("%.2f dollary doos", money));
            printText("Removed from basket: " + item.getName() + " ($" + item.getPrice() + ")");
        } else {
            printText("Nothing to undo.");
        }
    }

    /**
     * 
     */
    private void handleClear() {
        if (!basket.isEmpty()) {
            float refund = 0f;
            while (!basket.isEmpty()) {
                Item item = basket.pop();
                refund += item.getPrice();
            }
            money += refund;
            moneyDisplay.setText(String.format("%.2f dollary doos", money));
            printText("Basket cleared. Refunded $" + String.format("%.2f", refund));
        } else {
            printText("Basket is already empty.");
        }
    }

    /**
     * 
     */
    private void handleFinish() {
        if (!basket.isEmpty()) {
            float total = 0f;
            printText("\n--- Order Summary ---");
            for (Item item : basket) {
                printText(item.getName() + " ($" + item.getPrice() + ")");
                total += item.getPrice();
            }
            printText("Total: $" + String.format("%.2f", total));
        } else {
            printText("Basket is empty. Nothing to checkout.");
        }
    }

    /**
     * 
     */
    private void printText(String text) {
        textOutput.setText(textOutput.getText() + text + "\n");
    }
}
