package RDG;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import javax.sql.DataSource;
import org.postgresql.ds.PGSimpleDataSource;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Marcel
 */

/**
* Data row gateway for bought tickets
*/
public class BoughtTicket {

    boolean canceled;
    int bought_ticket_id, flight_id, class_id, passenger_id, aircraft_type_id, seat_id;

    @Override
    public String toString() {
        return "BoughtTicket{" + "canceled=" + canceled + ", bought_ticket_id=" + bought_ticket_id + ", flight_id=" + flight_id + ", class_id=" + class_id + ", passenger_id=" + passenger_id + ", aircraft_type_id=" + aircraft_type_id + ", seat_id=" + seat_id + '}';
    }

    

    public int getBought_ticket_id() {
        return bought_ticket_id;
    }

    public void setBought_ticket_id(int bought_ticket_id) {
        this.bought_ticket_id = bought_ticket_id;
    }

    public int getAircraft_type_id() {
        return aircraft_type_id;
    }

    public void setAircraft_type_id(int aircraft_type_id) {
        this.aircraft_type_id = aircraft_type_id;
    }

    public int getSeat_id() {
        return seat_id;
    }

    public void setSeat_id(int seat_id) {
        this.seat_id = seat_id;
    }

    public boolean isCanceled() {
        return canceled;
    }

    public void setCanceled(boolean canceled) {
        this.canceled = canceled;
    }

    public int getFlight_id() {
        return flight_id;
    }

    public void setFlight_id(int flight_id) {
        this.flight_id = flight_id;
    }

    public int getClass_id() {
        return class_id;
    }

    public void setClass_id(int class_id) {
        this.class_id = class_id;
    }

    public int getPassenger_id() {
        return passenger_id;
    }

    public void setPassenger_id(int passenger_id) {
        this.passenger_id = passenger_id;
    }
    
    public static boolean can_reserve_ticket(Integer flight_id, Integer class_id) throws SQLException{
        try ( PreparedStatement s = DbContext.getConnection().prepareStatement("SELECT can_reserve_ticket(?,?)")) {
            s.setInt(1, flight_id);
            s.setInt(2, class_id);
            
            ResultSet r = s.executeQuery();

            while(r.next()){
                return r.getBoolean(1);
            }
        }
        return false;
    }

    public static int insert(Integer flight_id, Integer class_id, boolean canceled, Integer passenger_id) throws SQLException, Exception {
        try ( PreparedStatement s = DbContext.getConnection().prepareStatement("INSERT INTO bought_tickets (flight_id, class_id, canceled, passenger_id, seat_id) VALUES (?,?,?,?, null)", Statement.RETURN_GENERATED_KEYS)) {
            s.setInt(1, flight_id);
            s.setInt(2, class_id);
            s.setBoolean(3, canceled);
            s.setInt(4, passenger_id);
            
            s.executeUpdate();

            try (ResultSet r  = s.getGeneratedKeys()) {
                r.next();
                return r.getInt(1);
            }
        }
    }
    
    /**
    * cancel ticket
    * @param id ticket_id to cancel
    * @throws SQLException
    * @throws Exception
    */
    public static void cancel(Integer id) throws SQLException, Exception {
        if(!BoughtTicket.exists(id))
            throw new Exception("Ticket w/ this id don't exists");
        if(BoughtTicket.ticketCanceled(id))
            throw new Exception("Ticket w/ this was already canceled");
        PreparedStatement ps = DbContext.getConnection().prepareStatement("SELECT * FROM bought_tickets INNER JOIN flights ON bought_tickets.flight_id=flights.flight_id WHERE bought_ticket_id=?");
        ps.setInt(1, id);
        ResultSet rs = ps.executeQuery();
        while (rs.next()) {
            Timestamp departure = rs.getTimestamp("departure_time");
            Timestamp day_ago = new Timestamp(System.currentTimeMillis() - 24 * 60 * 60 * 1000);
            if (departure.compareTo(day_ago) > 0) {
                throw new Exception("Let o menej ako 24 hodín, nevieš ho zrušiť");
            }
        }
        try ( PreparedStatement s = DbContext.getConnection().prepareStatement("UPDATE bought_tickets SET canceled=true WHERE bought_ticket_id=?")) {
            s.setInt(1, id);
            s.executeUpdate();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
    /**
    * fill data row gateway variables with data from ticket
    * @param bought_ticket_id ticket
    */
    public void findById(Integer bought_ticket_id) throws Exception {
        if(!BoughtTicket.exists(bought_ticket_id))
            throw new Exception("Ticket w/ this id don't exists");
        try ( PreparedStatement s = DbContext.getConnection().prepareStatement("SELECT * FROM bought_tickets INNER JOIN flights ON flights.flight_id=bought_tickets.flight_id WHERE bought_ticket_id=?")) {
            s.setInt(1, bought_ticket_id);
            ResultSet rs = s.executeQuery();
            while (rs.next()) {
                this.bought_ticket_id = rs.getInt("bought_ticket_id");
                canceled = rs.getBoolean("canceled");
                flight_id = rs.getInt("flight_id");
                class_id = rs.getInt("class_id");
                passenger_id = rs.getInt("passenger_id");
                aircraft_type_id = rs.getInt("aircraft_type_id");
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }
    /**
    * observe if ticket is canceled
    * @param id ticket_id
    * @return true if it is canceled
    */
    public static boolean ticketCanceled(Integer id) throws Exception {
        if(!BoughtTicket.exists(id))
            throw new Exception("Ticket w/ this id don't exists");
        try ( PreparedStatement s = DbContext.getConnection().prepareStatement("SELECT canceled FROM bought_tickets WHERE bought_ticket_id=?")) {
            s.setInt(1, id);
            ResultSet rs = s.executeQuery();
            while (rs.next()) {
                return rs.getBoolean(1);
            }
        } catch (Exception e) {
            System.out.println(e);
        }
        return false;
    }
    public static boolean exists(int ticket_id) throws SQLException {
        PreparedStatement s = DbContext.getConnection().prepareStatement("SELECT * from bought_tickets WHERE bought_ticket_id=?");
        s.setInt(1, ticket_id);
        return s.executeQuery().next();
    }
    /**
    * reserve seat
    * @param seat_id which seat reserve
    * @param ticket_id ticket related to this seat
    */
    public static void reserveSeat(Integer seat_id, Integer ticket_id) throws SQLException, Exception{
        if(!SeatCount.exists(seat_id))
            throw new Exception("Seat w/ this id don't exists");
        if(!BoughtTicket.exists(ticket_id))
            throw new Exception("Ticket w/ this id don't exists");
        if(!SeatCount.valid_seat(seat_id, ticket_id))
            throw new Exception("Seat w/ this id is not valid for this ticket (e.g. had been reserved)");
        
        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        input.readLine();
      
        PreparedStatement s = DbContext.getConnection().prepareStatement("UPDATE bought_tickets SET seat_id=? WHERE bought_ticket_id=? ");
        s.setInt(1, seat_id);
        s.setInt(2, ticket_id);
        s.executeUpdate();
    }
}
