package es.uv.saic.web;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import jakarta.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.mysql.cj.protocol.x.OkBuilder;

import es.uv.saic.domain.Organ;
import es.uv.saic.domain.Rol;
import es.uv.saic.domain.Usuari;
import es.uv.saic.domain.UsuarisRol;
import es.uv.saic.dto.OrganDTO;
import es.uv.saic.dto.RolDTO;
import es.uv.saic.dto.UsuariDTO;
import es.uv.saic.dto.UsuarisRolDTO;
import es.uv.saic.service.OrganService;
import es.uv.saic.service.RolService;
import es.uv.saic.service.UsuariService;
import es.uv.saic.service.UsuarisRolService;

// Controller for the managers administration page 
@RestController
public class ManagersController {
	
	@Autowired
	private UsuarisRolService urs;
	@Autowired
	private OrganService ors;
	@Autowired
	private UsuariService us;
	@Autowired
	private RolService rs;
	
	/*
	 * Load the managers administration page data into the model
	 * - List of centres and titulacions the logged user can manage
	 * - List of all users
	 * - List of assignable roles
	 * - If there are search results in the session, load them too
	 * - If there is a roleExists attribute in the session, load it too
	 * - The view is managers.html
	 */
	@PostMapping("/managers")
	public HashMap<String, Object> managersForm(@RequestBody String usuari) {
		HashMap<String, Object> model = new HashMap<>();
		Usuari u = us.findByUsername(usuari);
		
		List<OrganDTO> sup_centres = new ArrayList<>();
		List<OrganDTO> sup_titulacions = new ArrayList<>();
		List<Organ> centres;
		List<Organ> titulacions;
		if(u.isGranted()){
			centres = this.ors.getCentres();
			titulacions = this.ors.getTitulacions();
		}
		else {
			centres = this.ors.getUsuariCentres(usuari);
			if(centres != null) {
				if(centres.size() > 0) {
					titulacions = this.ors.getTitulacionsByCentres(centres);
				}
				else {
					titulacions = this.ors.getUsuariTitulacions(usuari);
					for(Organ o : titulacions) {
						centres.add(o.getOrgan());
					}
				}
			}
			else {
				titulacions = this.ors.getUsuariTitulacions(usuari);
			}
		}

		for(Organ o : centres) {
			sup_centres.add(new OrganDTO(o));
		}

		for(Organ o : titulacions) {
			sup_titulacions.add(new OrganDTO(o));
		}

		model.put("sup_centres", sup_centres);
		model.put("sup_titulacions", sup_titulacions);
		
		List<Usuari> sup_users = us.findAll();
		List<Rol> sup_roles = rs.findAssignables();
		List<UsuariDTO> users = new ArrayList<>();
		List<RolDTO> roles = new ArrayList<>();

		for(Usuari usu : sup_users) {
			users.add(new UsuariDTO(usu));
		}

		for(Rol r : sup_roles) {
			roles.add(new RolDTO(r));
		}
		
		model.put("users", users);
		model.put("roles", roles);
	
		return model;
	}
	
	/*
	 * Process the search form submission and load the results into the model
	 * @Param centres List of centre ids to search managers in
	 * @Param titulacions List of titulacion ids to search managers in
	 * @Return The view component list_managers
	 */
	@PostMapping("/managers/search")
	public HashMap<String, Object> managersSearch(@RequestParam("center") List<Integer> centres,
			@RequestParam(name="titulation[]", required=false) List<Integer> titulacions) {
		HashMap<String, Object> map = this.loadManagers(centres, titulacions);
		
		return map;
	}
	
	/*
	 * Load the search results into the model
	 * @Param model The model to load the data into
	 * @Param centres List of centre ids to search managers in
	 * @Param titulacions List of titulacion ids to search managers in
	 */
	public HashMap<String, Object> loadManagers(List<Integer> centres, List<Integer> titulacions) {
		HashMap<String, Object> model = new HashMap<>();
		List<UsuarisRol> centre = urs.findManagerByCentres(centres);
		Collections.sort(centre, new Comparator<UsuarisRol>() {  
		    @Override  
		    public int compare(UsuarisRol a, UsuarisRol b) {  
		          
		        int OrgnomComp = a.getOrgan().getNomVal().compareTo(b.getOrgan().getNomVal()); 
		        if (OrgnomComp != 0) {  
		            return OrgnomComp;  
		        }  
		        int rolComp = a.getRol().getNomRol().compareTo(b.getRol().getNomRol());
		        if (rolComp != 0) {  
		            return rolComp;  
		        }
		        return a.getUsuari().getNom().concat(a.getUsuari().getCognoms()).compareTo(
		        		b.getUsuari().getNom().concat(b.getUsuari().getCognoms()));  
		    }  
		});
		
		List<UsuarisRol> titulacio = new ArrayList<UsuarisRol>();
		if(titulacions.size() > 0) {
			titulacio = urs.findManagerByTitulacions(titulacions);
			Collections.sort(titulacio, new Comparator<UsuarisRol>() {  
			    @Override  
			    public int compare(UsuarisRol a, UsuarisRol b) {  
			          
			        int OrgnomComp = a.getOrgan().getNomVal().compareTo(b.getOrgan().getNomVal()); 
			        if (OrgnomComp != 0) {  
			            return OrgnomComp;  
			        }  
			        int rolComp = a.getRol().getNomRol().compareTo(b.getRol().getNomRol());
			        if (rolComp != 0) {  
			            return rolComp;  
			        }
			        return a.getUsuari().getNom().concat(a.getUsuari().getCognoms()).compareTo(
			        		b.getUsuari().getNom().concat(b.getUsuari().getCognoms()));  
			    }  
			});
		}

		List<UsuarisRolDTO> resp_centre = new ArrayList<>();
		List<UsuarisRolDTO> resp_titulacio = new ArrayList<>();

		for(UsuarisRol ur : centre) {
			resp_centre.add(new UsuarisRolDTO(ur));
		}
		for(UsuarisRol ur : titulacio) {
			resp_titulacio.add(new UsuarisRolDTO(ur));
		}
				
		if(centre == null) {
			model.put("results", false);
		}
		else{
			
			model.put("results", true);
			model.put("resp_centres", resp_centre);
			model.put("resp_titulacions", resp_titulacio);
		}

		return model;
	}
	
}