package com.web.web_assignment;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@ManagedBean
@SessionScoped
public class ProjectBean implements Serializable {
    private final DatabaseService databaseService = new DatabaseService();
    private List<Project> projects; // List to store all projects
    private int projectIdx;
    private Project project; // Current project being worked on
    private UserInfo userInfo; // User info for the current user
    private String username = "admin";
    private String password;
    private Boolean isLoggedIn = false;
    public String projectKeywords = ""; // String to hold project keywords
    public String newKeyword = "";
    public String projectCollaborators = ""; // String to hold project collaborators

    public List<String> allProjectsKeywords; // List of all unique keywords from all projects

    public List<String> selectedKeywords; // List of selected keywords for the current project

    private static String getJDBCurl() {
        return "jdbc:derby:testDB;create=true";
    }

    private List<String> users;

    @PostConstruct
    public void init() {
        loadProjects(); // Load projects from the database
        System.out.println("Projects loaded: " + projects.size());
        loadAllKeywords(); // Load all unique keywords from all projects
        if (projects.isEmpty()) {
            Project emptyProject = new Project("", "", "", new ArrayList<>(), "", new ArrayList<>(), "", "");
        }
        setProject(projects.get(0)); // Set the first project as the current project
        users = databaseService.getAllUsers();
    }

    @PreDestroy
    public void destroy() {
        databaseService.close();
    }

    public void loadUserInfo() {
        try {
            UserInfo info = databaseService.getUserInfo(username);
            if (info != null) {
                userInfo = info;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void updateUserInfo() {
        try {
            databaseService.updateUserInfo(username, userInfo);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void loadProjects() {
        projects = databaseService.getProjectsByUser(Objects.requireNonNullElse(username, "admin"));
    }

    /**
     * Loads all unique keywords from all projects into the allProjectsKeywords list.
     */

    public void loadAllKeywords() {
        allProjectsKeywords = projects.stream()
                .flatMap(project -> project.getKeywords().stream())
                .distinct()
                .collect(Collectors.toList());
    }

    public void addKeyword() {
        if (!newKeyword.isEmpty() && !allProjectsKeywords.contains(newKeyword)) {
            selectedKeywords.add(newKeyword);
            allProjectsKeywords.add(newKeyword);
        }
    }

    public List<Project> getProjects() {
        return projects;
    }

    public void setProjects(List<Project> projects) {
        this.projects = projects;
    }

    public Project getProject() {
        return project;
    }

    public void setProject(Project project) {
        this.projectIdx = projects.indexOf(project);
        this.project = project;
        this.projectKeywords = getKeywordsAsString(); // Update keywords string
        this.projectCollaborators = getCollaboratorsAsString();
        this.selectedKeywords = new ArrayList<>(project.getKeywords());
    }

    public void addProject() {
        project = new Project("", "", "", new ArrayList<>(), "", new ArrayList<>(), "", "");
        projects.add(project);
    }

    public String loadProject(String title) {
        project = projects.stream().filter(p -> p.getTitle().equals(title)).findFirst().orElse(null);
        return "project.xhtml?faces-redirect=true";
    }

    public String saveProject() {
        FacesContext context = FacesContext.getCurrentInstance();

        // Check for validation errors
        if (context.getMessages().hasNext()) {
            // Validation errors exist, do not save data
            return "edit";
        }

        project.setCollaborators(Arrays.asList(projectCollaborators.split(", ")));
        project.setKeywords(new ArrayList<>(selectedKeywords));

        try {
            ArrayList<Project> newProject = new ArrayList<>();
            newProject.add(project);
            if (projects.isEmpty()) {
                projects.add(project);
            } else {
                projects.set(projectIdx, project);
            }
            databaseService.saveProjects(username, newProject);
            context.addMessage("saveButton", new FacesMessage(FacesMessage.SEVERITY_INFO, "Submission Succeeded", null));
            loadAllKeywords();
        } catch (SQLException e) {
            context.addMessage("saveButton", new FacesMessage(FacesMessage.SEVERITY_ERROR, "Submission Failed", null));
            e.printStackTrace();
        }
        return "project";
    }

    public String register() {
        isLoggedIn = false;
        try {
            databaseService.registerUser(username, password);
        } catch (SQLException e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Registration failed", null));
            return "register";
        }
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Registration succeeded", null));
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("username");
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("password");
        return "login";
    }

    public String login() {
        try {
            if (databaseService.validateUser(username, password)) {
                FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("username", username);
                loadUserInfo();
                loadProjects();
                loadAllKeywords();
                isLoggedIn = true;
                if (projects.isEmpty()){
                    project = new Project("", "", "", new ArrayList<>(), "", new ArrayList<>(), "", "");
                }
                else{
                    setProject(projects.get(0));
                }
                return "index";
            } else {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Login failed", null));
                FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("username");
                isLoggedIn = false;
                return "login";
            }
        } catch (SQLException e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Login failed", null));
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("username");
            isLoggedIn = false;
            e.printStackTrace();
            return "login";
        }
    }

    public String logout() {
        FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
        isLoggedIn = false;
        return "index";
    }

    // Getters and setters for username and password
    public String getUsername() {
        return username;
    }

    public String visitorSetUsername(String username) {
        this.username = username;
        loadProjects();
        if (!projects.isEmpty()) {
            setProject(projects.get(0));
        } else {
            setProject(new Project("", "", "", new ArrayList<>(), "", new ArrayList<>(), "", ""));
        }
        return "project";
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getKeywordsAsString() {
        return project != null ? String.join(", ", project.getKeywords()) : "";
    }

    public String getCollaboratorsAsString() {
        return project != null ? String.join(", ", project.getCollaborators()) : "";
    }

    public String getProjectKeywords() {
        return projectKeywords;
    }

    public void setProjectKeywords(String projectKeywords) {
        this.projectKeywords = projectKeywords;
    }

    public String getProjectCollaborators() {
        return projectCollaborators;
    }

    public void setProjectCollaborators(String projectCollaborators) {
        this.projectCollaborators = projectCollaborators;
    }

    public List<String> getAllProjectsKeywords() {
        return allProjectsKeywords;
    }

    public void setAllProjectsKeywords(List<String> allProjectsKeywords) {
        this.allProjectsKeywords = allProjectsKeywords;
    }

    public UserInfo getUserInfo() {
        return userInfo;
    }

    public void setUserInfo(UserInfo userInfo) {
        this.userInfo = userInfo;
    }

    public List<String> getSelectedKeywords() {
        return selectedKeywords;
    }

    public void setSelectedKeywords(List<String> selectedKeywords) {
        this.selectedKeywords = selectedKeywords;
    }

    public String getNewKeyword() {
        return newKeyword;
    }

    public void setNewKeyword(String newKeyword) {
        this.newKeyword = newKeyword;
    }

    public Boolean getIsLoggedIn() {
        return isLoggedIn;
    }

    public List<String> getUsers() {
        return users;
    }

    public void setUsers(List<String> users) {
        this.users = users;
    }
}
