package me.blackphreak.CommandHandling;

import me.blackphreak.CommandHandling.Handlers.SearchStudentCommand;
import me.blackphreak.Database;
import me.blackphreak.Debug.Debug;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static me.blackphreak.Lib.promptQuestion;
import static me.blackphreak.Lib.tryParseUInt;

public class EditStudentCommand extends AbstractCommandHandler {
	private String lastCmd;
	private List<Integer> selectedStudentID;
	private String selectedColumn;
	
	public EditStudentCommand(String desc) {
		super(desc);
	}
	
	@Override
	public boolean handle() {
		boolean nextFlag;
		// reset
		selectedStudentID = new ArrayList<>();
		lastCmd = null;
		selectedColumn = null;
		
		do
		{
			nextFlag = selectStudentByID();
			
			// if lastCmd is set.
			if (lastCmd != null) {
				// in this case, lastCmd should be either "exit" nor "end".
				return lastCmd.equalsIgnoreCase("exit");
			}
		} while (!nextFlag);
		
		do {
			nextFlag = selectColumnToBeModified();
			
			if (lastCmd.equalsIgnoreCase("exit")) {
				return true;
			}
		} while (!nextFlag);
		
		doEdit();
		
		return true;
	}
	
	/**
	 * Ask user to provide student ID before editing the targeted student(s).
	 * @return true when selected at least one student, otherwise, false.
	 */
	private boolean selectStudentByID() {
		do {
			System.out.println("\n** type \"next\" to stop providing StudentID **");
			System.out.println("** type \"exit\" to back to main menu **");
			System.out.println("\nSelected StudentID(#"+selectedStudentID.size()+"): " + Arrays.toString(selectedStudentID.toArray()));
			var inp = promptQuestion("Please provide StudentID: ", false);
			
			if (inp.equalsIgnoreCase("next"))
			{
				if (selectedStudentID.size() <= 0)
					System.out.println("Please provide at least one student ID before edit.");
				else
					return true;
			}
			else if (inp.equalsIgnoreCase("exit"))
			{
				lastCmd = "exit";  // back to main menu
				return false;
			}
			else
			{
				int sid = tryParseUInt(inp);
				if (sid == -1) {
					System.out.println("Invalid StudentID, please try again. [Parser Error]");
					continue;
				}
				
				// query database to confirm that student is exist.
				try {
					if (Database.getInstance()
						.query("SELECT COUNT(*) FROM Student WHERE StudentID = \""+sid+"\";")
						.getInt(1) != 1)
					{
						System.out.println("Invalid StudentID, please try again. [Failed to select (!=1)]");
						continue;
					}
				} catch (SQLException e) {
					Debug.err("Failed to find student. (Database Error)");
					e.printStackTrace();
					lastCmd = "end";  // end the program
					return false;
				}
				
				selectedStudentID.add(sid);
			}
		} while (true);
	}
	
	private boolean selectColumnToBeModified() {
		do {
			System.out.println("\nColumns:");
			for (int i = 0; i < SearchStudentCommand.unmodColNames.size(); i++) {
				System.out.println(String.format(
						"  %2s. %-15s",
						(i+1) + "",
						SearchStudentCommand.unmodColNames.get(i)
				));
			}
			
			// exit option
			System.out.println(String.format(
					"  %2s. %-15s",
					"99",
					"Back to main menu"
			));
			
			var inp = promptQuestion("Please select one column to edit: ");
			var selected = tryParseUInt(inp, "Invalid column index");
			if (selected == -1)
				continue;
			
			if (selected == 99)
			{
				lastCmd = "exit";
				return false;
			}
			
			if (selected <= 0
					|| selected > SearchStudentCommand.unmodColNames.size())
			{
				System.out.println("Invalid column index. [Out of range]");
				continue;
			}
			
			selectedColumn = SearchStudentCommand.unmodColNames.get(selected-1);
			return true;
			
		} while (true);
	}
	
	private void doEdit() {
		var newValue = promptQuestion("The value that you want it to be: ");
		
		var updated = Database.getInstance().update("UPDATE Student SET " + selectedColumn + " = \""+newValue+"\" WHERE StudentID = \""+selectedStudentID+"\";");
		
		if (updated <= 0)
			System.out.println("No changes have been made.");
		else
			System.out.println("Update successfully made to "+updated+" student(s).");
	}
}
