package edu.fiu.controllers;

import edu.fiu.repositories.SessionRepository;
import edu.fiu.repositories.UserRepository;
import org.jooby.*;
import org.jooby.mvc.*;
import javax.inject.Inject;
import edu.fiu.models.*;
import java.util.UUID;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import edu.fiu.models.Session;

/***
 * Copied from User Controller Contains Post method to login to a user session
 * Contains a method to check if a user is authorized for each api request
 */
@Path("api/session")
public class SessionController {
    private SessionRepository sessions;
    private UserRepository users;
    private Request req;

    @Inject
    public SessionController(SessionRepository sessions, UserRepository users, Request req) {
        this.sessions = sessions;
        this.users = users;
        this.req = req;
    }

    @POST
    public String Post(@Body LoginDTO[] listUser) {

        String userIds = "";
        String localHost = null;

        try {
            InetAddress address = InetAddress.getByName(req.ip());
            localHost = address.getHostName();
            // System.out.println("localHostname is " + localHost);
        } catch (UnknownHostException error) {
            localHost = "<Unable to get machine name>";
            System.out.println("Unable to get localHost name");
        }

        // authenticates all the users in the machine or returns error
        for (LoginDTO l : listUser) {

            String userName = l.getName();

            User u = users.get(userName);

            if (u == null)
                return "false";

            if (!u.auth(l.getPassword()))
                return "false";

            Integer loggedIn = users.getUserStatus(userName);
            if (loggedIn == 1) {
                String userIP = u.getHost();
                return "User " + userName + " is logged in machine " + userIP;
            }

            // if user exists add him to the userIds
            userIds += u.getId() + ",";
        }

        // set the hostName and status for all users authenticated
        for (LoginDTO l : listUser) {
            String userName = l.getName();
            users.markActive(userName);
            users.setHost(userName, localHost);
        }

        // creates a token
        String token = UUID.randomUUID().toString();

        // creates a date for the token
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formatDateTime = now.format(format);

        // creates the session
        sessions.create(token, userIds, true, formatDateTime);

        return token;
    }

    @GET
    public List<Integer> Get() {
        String session = req.param("session").value();

        try {
            Session s = sessions.get(session);
            return s.getUserIds();
        } catch (Exception ex) {
            // empty
            return new ArrayList<Integer>();
        }

    }

    @GET
    @Path("/setInactive")
    public boolean setInactive() {
        try {
            String sessionToken = req.param("session").value();
            Session s = sessions.get(sessionToken);
            List<Integer> userIDs = s.getUserIds();
            for (Integer id : userIDs) {
                users.markInactive(id);
                users.clearHost(id);
            }
            // sessions.disableSession(sessionToken);
            sessions.removeSession(sessionToken);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    @GET
    @Path("/isSessionValid")
    public boolean isSesssionValid() {
        String sessionToken = req.param("session").value();
        Session s = sessions.get(sessionToken);
        if (s != null) {
            // System.out.println(true);
            return true;
        } else {
            // System.out.println(false);
            return false;
        }
    }

    @POST
    @Path("/kickUser")
    public boolean kickUser() throws Exception {

        String data = req.body().value();
        String[] params = data.split(",", 2);
        String adminToken = params[0];
        Integer userId = Integer.valueOf(params[1]);

        try {

            Integer adminUserId = sessions.get(adminToken).getUserIds().get(0);
            if (users.get(adminUserId).getName().equalsIgnoreCase("admin")) {
                //System.out.println("request came from admin");
                List<Session> sessionList = sessions.list();
                for (Session current : sessionList) {
                    if (current.getUserIds().contains(userId)) {
                        sessions.removeSession(current.getToken());
                        users.markInactive(userId);
                        users.clearHost(userId);
                    }
                }
            }

            return true;

        } catch (Exception e) {
            System.out.println("there was some error kicking the user out. ");
            return false;
        }
    }
}