package es.uv.saic.web;

import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import jakarta.mail.MessagingException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.access.annotation.Secured;
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.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import es.uv.saic.domain.Datasource;
import es.uv.saic.domain.IndicadorEnquesta;
import es.uv.saic.domain.IndicadorEnquestaTmp;
import es.uv.saic.domain.IndicadorEnquestaTmpRepository;
import es.uv.saic.domain.Organ;
import es.uv.saic.domain.Usuari;
import es.uv.saic.service.DataService;
import es.uv.saic.service.DatasourceService;
import es.uv.saic.service.IndicadorEnquestaService;
import es.uv.saic.service.IndicadorEnquestaTmpService;
import es.uv.saic.service.OrganService;

@Controller
public class DataController {

	@Autowired
	private DataService ips;
	
	@Autowired 
	private OrganService os;
	
	@Autowired
	private IndicadorEnquestaTmpService iets;
	
	@Autowired
	private IndicadorEnquestaService ies;

	@Autowired
	private DatasourceService das;
	
	@GetMapping("/data/import")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	public String renderImport(Model model, Authentication auth) {
		List<Datasource> sources = this.das.findAll();
		for(Datasource d : sources){
			d.setConn(null);
		}
		model.addAttribute("sources", sources);
		return "dataImport";
	}
	
	@PostMapping("/data/import")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	@ResponseBody
	public String uploadFile(Model model, Authentication auth, MultipartFile file, @RequestParam String enquesta, @RequestParam String ambit,
							@RequestParam String estudi, @RequestParam String clau, @RequestParam String tipus, @RequestParam List<String> ignoredColumns,
							@RequestParam(required = false) String vista, @RequestParam(required = false) String delim, 
							@RequestParam(required = false) Integer curs, @RequestParam(required = false) Integer dstCurs,
							@RequestParam(required = false) Integer dbOrigen) throws IOException, MessagingException, ClassNotFoundException, SQLException { 
		String locale = LocaleContextHolder.getLocale().getLanguage();
		String retval = "";
		if(tipus.equals("file")){
			InputStreamReader in = new InputStreamReader(file.getInputStream());
			retval = this.ips.doImport(in, (Usuari)auth.getPrincipal(), enquesta, ambit, estudi, locale, delim, clau, ignoredColumns);
		}
		else if(tipus.equals("db")){
			retval = this.ips.doDbImport(dbOrigen, vista, curs, dstCurs, (Usuari)auth.getPrincipal(), enquesta, ambit, estudi, locale, clau, ignoredColumns);
		}
		
		return retval;
	}
	
	@PostMapping("/data/delete")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	@ResponseBody
	public String delete(Model model, Authentication auth, @RequestParam String enquesta,
			@RequestParam Integer curs, @RequestParam String ambit, @RequestParam String estudi) throws IOException {  
		String locale = LocaleContextHolder.getLocale().getLanguage();
		String r = Integer.toString(this.iets.deleteByEnquestaCursAmbitEstudi(enquesta, curs, ambit, estudi));
	    String retval = locale.equals("es") ? "[INFO] Se han eliminado "+r+" registros" : "[INFO] S'han esborrat "+r+" registres";
        return retval;
	}
	
	@PostMapping("/data/show")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	@ResponseBody
	public List<IndicadorEnquestaTmp> show(Model model, Authentication auth, @RequestParam String enquesta,
			@RequestParam Integer curs, @RequestParam String ambit, @RequestParam String estudi) throws IOException {    
		List<IndicadorEnquestaTmp> inds = this.iets.findByEnquestaCursAmbitEstudi(enquesta, curs, ambit, estudi);
        return inds;
	}
	
	@GetMapping("/data/current")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	public String current(Model model, Authentication auth) throws IOException {    
		List<Organ> centres = os.getActiveCentres();
		List<Organ> titulacions = os.getTitulacions();
		model.addAttribute("centres", centres);
		model.addAttribute("titulacions", titulacions);
		return "dataCurrent";
	}
	
	@GetMapping("/data/consolidate")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	public String consolidate(Model model, Authentication auth) throws IOException {    
		return "dataConsolidate";
	}
	
	@PostMapping("/data/check/{type}")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	@ResponseBody
	public List<IndicadorEnquestaTmpRepository.IndicadorEnquestaTmpDup> check(Model model, Authentication auth, 
			@RequestParam String enquesta, @PathVariable Integer type) throws IOException {   
		if(type == 1) {
			return this.ips.checkDuplicates(enquesta);
		}
		else {
			return this.ips.checkIntegrity(enquesta);
		}
		
	}

	@PostMapping("/data/fix/integrity/{deleteFrom}")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	@ResponseBody
	public Integer fixIntegrityIssues(Model model, Authentication auth, 
			@RequestParam String enquesta, @PathVariable String deleteFrom) throws IOException {   
		if(deleteFrom.equals("current")) {
			return this.iets.deleteFromCurrent(enquesta);
		}
		else if(deleteFrom.equals("new")) {
			return this.iets.deleteFromPending(enquesta);
		}
		return 0;
	}

	@PostMapping("/data/fix/duplication")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	@ResponseBody
	public Integer fixDuplicatesIssues(Model model, Authentication auth, @RequestParam String enquesta) throws IOException {   
		return this.iets.deleteDuplicates(enquesta);
	}
	
	@PostMapping("/data/consolidate")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	@ResponseBody
	public Integer consolidate(Model model, Authentication auth, @RequestParam String enquesta) throws IOException {    
		return this.ips.consolidateByEnquesta(enquesta);
	}
	
	@PostMapping("/data/count")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	@ResponseBody
	public Integer countByEnquesta(Model model, Authentication auth, @RequestParam String enquesta) throws IOException {    
		return this.ips.countByEnquesta(enquesta);
	}

	@PostMapping("/data/view/columns")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	@ResponseBody
	public List<String> listTableColumns(Model model, Authentication auth, @RequestParam Integer dbOrigen, @RequestParam String vista) {    
		String locale = LocaleContextHolder.getLocale().getLanguage();
		try {
			return this.ips.listTableColumns(dbOrigen, vista, locale);
		} catch (ClassNotFoundException | SQLException e) {
			return new ArrayList<String>();
		}
	}
	
	@GetMapping("/data/current/show/{ruct}/{curs}")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	@ResponseBody
	public List<IndicadorEnquesta> show(Model model, Authentication auth, @PathVariable Integer ruct, 
			@PathVariable Integer curs) throws IOException {  
		Organ o = os.findByRuct(ruct);
		List<IndicadorEnquesta> inds = this.ies.getAllInds(o, curs);
        return inds;
	}
	
	@PostMapping("/data/current/show")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	@ResponseBody
	public List<IndicadorEnquesta> currentShow(Model model, Authentication auth, @RequestParam String enquesta,
			@RequestParam Integer curs, @RequestParam String ambit, @RequestParam String estudi,
			@RequestParam Integer centre, @RequestParam Integer titulacio) throws IOException {   
		List<IndicadorEnquesta> inds = new ArrayList<IndicadorEnquesta>();
		if(ambit.equals("U")) {
			inds = this.ies.findByEnquestaCursAmbitEstudi(enquesta, curs, ambit, estudi);
		}
		else if(ambit.equals("C")) {
			inds = this.ies.findByEnquestaCursAmbitEstudiCentre(enquesta, curs, ambit, estudi, centre);
		}
		if(ambit.equals("T")) {
			inds = this.ies.findByEnquestaCursAmbitEstudiCentreTitulacio(enquesta, curs, ambit, estudi, centre, titulacio);
		}
        return inds;
	}

	@GetMapping("/data/sources")
	@Secured({"ROLE_ADMIN", "ROLE_TESTER"})
	@ResponseBody
	public List<Datasource> getDatasources(Model model, Authentication auth) throws IOException {  
		List<Datasource> sources = this.das.findAll();
		for(Datasource d : sources){
			d.setConn(null);
		}
        return sources;
	}
}
