package es.uv.saic.web;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import jakarta.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import es.uv.saic.domain.DummyDataTransfer;
import es.uv.saic.domain.Instancia;
import es.uv.saic.domain.InstanciaTasca;
import es.uv.saic.domain.InstanciaTransfer;
import es.uv.saic.domain.Organ;
import es.uv.saic.domain.SupervisionSearchParams;
import es.uv.saic.domain.Usuari;
import es.uv.saic.dto.EvidenciaBuscadorDTO;
import es.uv.saic.service.InstanciaService;
import es.uv.saic.service.InstanciaTascaService;
import es.uv.saic.service.OrganService;
import es.uv.saic.service.TascaService;
import es.uv.saic.service.UsuariService;
import es.uv.saic.service.UsuarisRolService;

// Render the supervision page and handle supervision searches
@Controller
public class SupervisionController {
	
	@Autowired
	private UsuariService us;
	@Autowired
	private InstanciaService is;
	@Autowired
	private UsuarisRolService urs;
	@Autowired
	private OrganService ors;
	@Autowired
	private InstanciaTascaService its;
	@Autowired
	private TascaService tas;

	/*
	 * Renders the supervision page
	 * 
	 * @param model The model to pass data to the view
	 * @param auth The authentication object
	 * @param session The HTTP session
	 * @return The name of the view to render
	 */
	@GetMapping("/supervision")
	public String supervisionForm(Model model, Authentication auth, HttpSession session) {
		
		List<DummyDataTransfer> supervisable_procs = new ArrayList<DummyDataTransfer>();
		List<DummyDataTransfer> supervisable_years = new ArrayList<DummyDataTransfer>();
		List<DummyDataTransfer> supervisable_orgs = new ArrayList<DummyDataTransfer>();
		List<DummyDataTransfer> supervisable_cents = new ArrayList<DummyDataTransfer>();
		
		if(urs.isGrantedUser((Usuari) auth.getPrincipal())){ // Admin o UQ
			List<Instancia> i_list = is.findAll();
			for(Instancia inst : i_list) {
				DummyDataTransfer p = new DummyDataTransfer();
				DummyDataTransfer y = new DummyDataTransfer();
				DummyDataTransfer o = new DummyDataTransfer();
				p.setText(inst.getProces().getNomProces());
				p.setValue(inst.getProces().getIdProces());
				y.setText(Integer.toString(inst.getProces().getCursAvaluat()-1) + " - " + Integer.toString(inst.getProces().getCursAvaluat()));
				y.setValue(inst.getProces().getCursAvaluat());
				o.setText(inst.getOrgan().getNomCas());
				o.setText2(inst.getOrgan().getNomVal());
				o.setValue(inst.getOrgan().getId().getLugar());
				o.setText3(inst.getOrgan().getId().getTlugar());
				if(!supervisable_procs.contains(p)) {
					supervisable_procs.add(p);
				}
				if(!supervisable_years.contains(y)) {
					supervisable_years.add(y);
				}
				if(!supervisable_orgs.contains(o) && inst.getOrgan().getId().getTlugar().equals("T") && inst.getOrgan().getId().getLugar() > 2) {
					supervisable_orgs.add(o);
				}
			}
			DummyDataTransfer o = new DummyDataTransfer();
			o = new DummyDataTransfer();
			Organ org = ors.findByID("T", 1);
			o.setText(org.getNomCas());
			o.setText2(org.getNomVal());
			o.setValue(1);
			supervisable_orgs.add(o);
			o = new DummyDataTransfer();
			org = ors.findByID("T", 2);
			o.setText(org.getNomCas());
			o.setText2(org.getNomVal());
			o.setValue(2);
			supervisable_orgs.add(o);
			o = new DummyDataTransfer();
			org = ors.findByID("T", 0);
			o.setText(org.getNomCas());
			o.setText2(org.getNomVal());
			o.setValue(0);
			supervisable_orgs.add(o);
			List<Organ> org_list = ors.findCurrentCentres();
			for(Organ or : org_list) {
				DummyDataTransfer c = new DummyDataTransfer();
				c.setText(or.getNomCas());
				c.setText2(or.getNomVal());
				c.setValue(or.getId().getLugar());
				supervisable_cents.add(c);
			}
			List<DummyDataTransfer> supervisable_evs = new ArrayList<DummyDataTransfer>();
			List<EvidenciaBuscadorDTO> evs_list = tas.getAllEvidencies();
			for(EvidenciaBuscadorDTO e : evs_list) {
				DummyDataTransfer c = new DummyDataTransfer();
				c.setText(e.getCodiEvidencia());
				c.setText2(e.getNomEvidenciaCas());
				c.setText3(e.getNomEvidenciaVal());
				supervisable_evs.add(c);
			}
			supervisable_cents.sort(Comparator.comparing(a -> a.getText()));
			model.addAttribute("granted", true);
			model.addAttribute("sup_evs", supervisable_evs);
			model.addAttribute("sup_cents", supervisable_cents);
		}
		else { // Otros     
			List<BigInteger> i_list = this.us.getSupervisableProcessos(urs.findActiveRols(((Usuari) auth.getPrincipal())));
			for(BigInteger id : i_list) {
				Instancia inst = is.findByID(id);
				DummyDataTransfer p = new DummyDataTransfer();
				DummyDataTransfer y = new DummyDataTransfer();
				DummyDataTransfer o = new DummyDataTransfer();
				p.setText(inst.getProces().getNomProces());
				p.setText2(inst.getProces().getNomProces() + " " + inst.getProces().getTitolCas());
				p.setText3(inst.getProces().getNomProces() + " " + inst.getProces().getTitolVal());
				y.setText(Integer.toString(inst.getProces().getCursAvaluat()-1) + " - " + Integer.toString(inst.getProces().getCursAvaluat()));
				y.setValue(inst.getProces().getCursAvaluat());
				o.setText(inst.getOrgan().getNomCas());
				o.setText2(inst.getOrgan().getNomVal());
				o.setValue(inst.getOrgan().getId().getLugar());
				o.setText3(inst.getOrgan().getId().getTlugar());
				if(!supervisable_procs.contains(p)) {
					supervisable_procs.add(p);
				}
				if(!supervisable_years.contains(y)) {
					supervisable_years.add(y);
				}
				if(!supervisable_orgs.contains(o) && inst.getOrgan().getId().getTlugar().equals("T") && inst.getOrgan().getId().getLugar() > 2) {
					supervisable_orgs.add(o);
				}
			}
			DummyDataTransfer o = new DummyDataTransfer();
			o = new DummyDataTransfer();
			Organ org = ors.findByID("T", 1);
			o.setText(org.getNomCas());
			o.setText2(org.getNomVal());
			o.setValue(1);
			supervisable_orgs.add(o);
			o = new DummyDataTransfer();
			org = ors.findByID("T", 2);
			o.setText(org.getNomCas());
			o.setText2(org.getNomVal());
			o.setValue(2);
			supervisable_orgs.add(o);
			o = new DummyDataTransfer();
			org = ors.findByID("T", 0);
			o.setText(org.getNomCas());
			o.setText2(org.getNomVal());
			o.setValue(0);
			supervisable_orgs.add(o);
			model.addAttribute("granted", false);
		}
		
		supervisable_orgs.sort(Comparator.comparing(a -> a.getText()));
		
		model.addAttribute("sup_procs", supervisable_procs);
		model.addAttribute("sup_years", supervisable_years);
		model.addAttribute("sup_orgs", supervisable_orgs);
		
		if(session.getAttribute("searchParams") != null) {
			SupervisionSearchParams ssp = (SupervisionSearchParams) session.getAttribute("searchParams");
			model.addAttribute("restore", ssp);
			session.removeAttribute("searchParams");
		}
		else {
			model.addAttribute("restore", null);
		}
		
		return "supervision";
	}
	
	/*
	 * Handles the supervision search form submission
	 * 
	 * @param model The model to pass data to the view
	 * @param auth The authentication object
	 * @param centres The selected centers
	 * @param cursos The selected years
	 * @param titulacions The selected titulacions
	 * @param procediments The selected procedures
	 * @param evidencies The selected evidences
	 * @param searchType The type of search (by procedures or evidences)
	 * @param session The HTTP session
	 * @return The name of the view to render
	 */
	@PostMapping("/supervision/search")
	public String supervisionSearch(Model model, Authentication auth, 
			@RequestParam(name="centers[]", required=false) List<Integer> centres,
			@RequestParam("years[]") List<Integer> cursos,
			@RequestParam("titulations[]") List<Integer> titulacions,
			@RequestParam(name="procedures[]", required=false) List<String> procediments,
			@RequestParam(name="evidences[]", required=false) List<String> evidencies,
			@RequestParam(name="searchType", required=false) String searchType,
			HttpSession session) {
		session.setAttribute("location", "supervision");
		if(centres == null) { centres = us.getSupervisableCentres((Usuari) auth.getPrincipal()); }
		this.loadResults(model, auth, centres, titulacions, cursos, procediments, evidencies, searchType);
		session.setAttribute("searchParams", new SupervisionSearchParams(centres, titulacions, cursos, procediments, evidencies, searchType));
		
		return "supervisionProcedures";
	}
	
	/*
	 * Restores the previous search results from the session
	 * 
	 * @param model The model to pass data to the view
	 * @param auth The authentication object
	 * @param session The HTTP session
	 * @return The name of the view to render
	 */
	@GetMapping("/supervision/search")
	public String restoreSearch(Model model, Authentication auth, HttpSession session) {
		session.setAttribute("location", "supervision");
		if(session.getAttribute("searchParams") != null) {
			SupervisionSearchParams ssp = (SupervisionSearchParams) session.getAttribute("searchParams");
			this.loadResults(model, auth, ssp.getCentres(), ssp.getTitulacions(), ssp.getCursos(), ssp.getProcediments(), ssp.getEvidencies(), ssp.getSearchType());
		}
		
		return "supervisionProcedures"; 
	}
	
	/*
	 * Loads the search results based on the provided filters
	 * 
	 * @param model The model to pass data to the view
	 * @param auth The authentication object
	 * @param centres The selected centers
	 * @param titulacions The selected titulacions
	 * @param cursos The selected years
	 * @param procediments The selected procedures
	 * @param evidencies The selected evidences
	 * @param searchType The type of search (by procedures or evidences)
	 */
	public void loadResults(Model model, Authentication auth, List<Integer> centres, List<Integer> titulacions, 
			List<Integer> cursos, List<String> procediments, List<String> evidencies, String searchType) {
		List<InstanciaTransfer> plist = new ArrayList<InstanciaTransfer>();
		List<BigInteger> supervisables;
		if(searchType != null) {
			if(searchType.equals("evidences")) {
				supervisables = this.is.filterSupervisablesByEvidencies(centres, titulacions, cursos, evidencies);
			}
			else {
				supervisables = this.is.filterSupervisables(centres, titulacions, cursos, procediments);
			}
		}
		else {
			supervisables = this.is.filterSupervisables(centres, titulacions, cursos, procediments);
		}
		Instancia i;
		InstanciaTransfer it;
		InstanciaTasca itt;
		for(BigInteger p_id: supervisables) {
			i = this.is.findByID(p_id);
			it = new InstanciaTransfer();
			it.setIdInstancia(i.getIdInstancia());
			it.setIdProces(i.getProces().getIdProces());
			it.setNomProces(i.getProces().getNomProces());
			it.setCursAvaluat(i.getProces().getCursAvaluat());
			it.setCursActivacio(i.getProces().getCursActivacio());
			it.setTitolCas(i.getProces().getTitolCas());
			it.setTitolVal(i.getProces().getTitolVal());
			it.setDescripcioCas(i.getProces().getDescripcioCas());
			it.setDescripcioVal(i.getProces().getDescripcioVal());
			it.setEstat(i.getEstat());
			if(i.getOrgan().getId().getTlugar().equals("C")) {
				Organ o = ors.findByID("T", i.getTitulacio());
				it.setTitulacioCas(o.getNomCas());
				it.setTitulacioVal(o.getNomVal());
				it.setCentreCas(i.getOrgan().getNomCas());
				it.setCentreVal(i.getOrgan().getNomVal());
			}
			else {
				it.setTitulacioCas(i.getOrgan().getNomCas());
				it.setTitulacioVal(i.getOrgan().getNomVal());
				it.setCentreCas(i.getOrgan().getOrgan().getNomCas());
				it.setCentreVal(i.getOrgan().getOrgan().getNomVal());
			} 
			if(i.getEstat().equals("A")) {
				itt = its.findActiveByInstancia(i.getIdInstancia());
				it.setDataLimTascaActiva(itt.getTasca().getDataLim());
				it.setDataTascaActiva(itt.getData());
				it.setNomTascaActivaCas(itt.getTasca().getTitolCas());
				it.setNomTascaActivaVal(itt.getTasca().getTitolVal());
				it.setDescTascaActivaCas(itt.getTasca().getDescripcioCas());
				it.setDescTascaActivaVal(itt.getTasca().getDescripcioVal());
				it.setIdTascapActiva(itt.getTasca().getIdTascap());
				it.setTascaActivaExpired(itt.getTasca().isExpired());
				it.setTascaActivaAssignedToUser(its.isUserAuthorized(((Usuari)auth.getPrincipal()), itt.getIdInstanciaTasca()));
			}
			plist.add(it);
		}
		model.addAttribute("procedure_list", plist);
	}
	
}