package main.java.ui;

import main.java.rdg.*;

import java.sql.Timestamp;
import java.time.Instant;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class ReservationMenu {
    public static void run() {
        String menuStr = "" +
                "SELECT OPERATION:\n" +
                "1. Make new reservation\n" +
                "2. Update pending reservation\n" +
                "3. Confirm and pay reservation\n" +
                "4. List customers reservation\n" +
                "5. Find reservation\n" +
                "6. Delete reservation\n" +
                "7. Clear overtime reservations\n" +
                "Press enter to exit";

        String input = UserInput.get(menuStr);

        switch (input) {
            case "1": addReservation(); break;
            case "2": updateReservation(); break;
            case "3": confimReservation(); break;
            case "4": listCustomersReservation(); break;
            case "5": findReservation(); break;
            case "6": deleteReservation(); break;
            case "7": clearOvertime(); break;
            case "": break;
            default: UserInput.badInput();
        }
    }

    public static void addReservation() {
        long customerID = Long.parseLong(UserInput.get("Enter customer ID"));
        Customer customer = Customer.read(customerID);
        if (customer == null) {
            System.out.println("No such customer ID found");
            return;
        }

        long screeningID = Long.parseLong(UserInput.get("Enter screening ID"));
        Screening screening = Screening.read(screeningID);
        if (screening == null){
            System.out.println("No such screening ID found");
            return;
        }

        Timestamp limit = screening.getTimestamp();
        limit.setTime(limit.getTime() - TimeUnit.MINUTES.toMillis(39));

        if (limit.before(Timestamp.from(Instant.now()))){
            System.out.println("Unable to make reservation for this screening, you are only able to make a reservation atleast 40 minutes before the screening!");
            return;
        }
        Reservation reservation = new Reservation();
        long voucherID = 0;
        if (UserInput.get("Would you like to use a voucher? Y/N").equals("Y")){
            String code = UserInput.get("Enter voucher code");

            Set<Voucher> vouchers = Voucher.findByCode(code);

            if (vouchers.size() == 0) {
                System.out.println("No such voucher code found");
                return;
            }

            List<Voucher> lst = vouchers.stream().filter(x -> x.getCustomer() == customerID).collect(Collectors.toList());
            if (lst.size() == 0) {
                System.out.println("No such voucher with given code belonging to customer found");
                return;
            }

            Voucher v = lst.get(0);

            if (v.isUsed()) {
                System.out.println("Voucher already used");
                return;
            }
            reservation.setUsedVoucher(v.getId());
            v.setUsed(true);
            v.update();
        }

        String[] input = UserInput.get("Enter ticket amount (child/student/adult/senior) [2;0;6;1]").split(";");
        int child = Integer.parseInt(input[0]);
        int student = Integer.parseInt(input[1]);
        int adult = Integer.parseInt(input[2]);
        int senior = Integer.parseInt(input[3]);

        if (child + student + adult + senior > Screening.freeTicketCount(screeningID)){
            System.out.println("Not enough tickets available");
            return;
        }


        reservation.setCustomer(customerID);
        reservation.setScreening(screeningID);
        reservation.setChild(child);
        reservation.setStudent(student);
        reservation.setAdult(adult);
        reservation.setSenior(senior);

        UserInput.success(reservation.create());
    }

    public static void updateReservation() {
        long reservationID = Long.parseLong(UserInput.get("Enter reservation ID"));

        Reservation res = Reservation.read(reservationID);

        if (res == null) {
            System.out.println("No such reservation ID found");
            return;
        }

        if (!res.isPending()){
            System.out.println("Cannot update confirmed reservation");
            return;
        }

        if (!checkTime(res)){
            System.out.println("Time to confirm your reservation has passed (10mins)! Reservation has been deleted");
            Ticket.unreserveTickets(reservationID);
            if (res.getUsedVoucher() != null){
                Voucher v = Voucher.read(res.getUsedVoucher());
                v.setUsed(false);
                v.update();
            }
            res.delete();
            return;
        }

        String customerType = UserInput.get("Enter customer type (CHILD/STUDENT/ADULT/SENIOR)");
        int ticketCount = Integer.parseInt(UserInput.get("Enter new ticket count"));

        if (customerType.equals("CHILD"))
            res.setChild(ticketCount);
        if (customerType.equals("STUDENT"))
            res.setStudent(ticketCount);
        if (customerType.equals("ADULT"))
            res.setAdult(ticketCount);
        if (customerType.equals("SENIOR"))
            res.setSenior(ticketCount);

        UserInput.success(res.update());
    }

    public static void confimReservation() {
        long reservationID = Long.parseLong(UserInput.get("Enter reservation ID"));

        Reservation res = Reservation.read(reservationID);

        if (res == null) {
            System.out.println("No such reservation ID found");
            return;
        }

        if (!checkTime(res)){
            System.out.println("Time to confirm your reservation has passed (10mins)! Reservation has been deleted");
            Ticket.unreserveTickets(reservationID);
            if (res.getUsedVoucher() != null){
                Voucher v = Voucher.read(res.getUsedVoucher());
                v.setUsed(false);
                v.update();
            }
            res.delete();
            return;
        }
        Ticket.payTickets(reservationID);
        UserInput.success(Reservation.confirmReservation(reservationID));
    }

    public static void listCustomersReservation() {
        long customerID = Long.parseLong(UserInput.get("Enter customer ID"));
        Customer c = Customer.read(customerID);
        if (c == null) {
            System.out.println("No such customer ID found");
            return;
        }

        Reservation.readCustomersReservations(customerID).forEach(System.out::println);
    }

    public static void findReservation() {
        long reservationID = Long.parseLong(UserInput.get("Enter reservation ID"));

        Reservation res = Reservation.read(reservationID);
        if (res == null) {
            System.out.println("No such reservation ID found");
            return;
        }

        System.out.println(res);
    }

    public static void deleteReservation() {
        long reservationID = Long.parseLong(UserInput.get("Enter reservation ID"));

        Reservation res = Reservation.read(reservationID);
        if (res == null) {
            System.out.println("No such reservation ID found");
            return;
        }

        if (res.isPending()) {
            if (res.getUsedVoucher() != null){
                Voucher v = Voucher.read(res.getUsedVoucher());
                v.setUsed(false);
                v.update();
            }

            Ticket.unreserveTickets(res.getId());
        }

        UserInput.success(res.delete());
    }

    public static boolean checkTime(Reservation res) {
        Timestamp limit = res.getBegin();
        limit.setTime(limit.getTime() + TimeUnit.MINUTES.toMillis(10));

        return limit.after(Timestamp.from(Instant.now()));
    }

    public static void clearOvertime() {
        UserInput.success(Reservation.clearOvertimeReservations());
    }
}
