package es.uv.saic.web;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import es.uv.saic.domain.DummyDataTransfer;
import es.uv.saic.domain.IndicadorEnquesta;
import es.uv.saic.domain.Organ;
import es.uv.saic.domain.Proces;
import es.uv.saic.domain.Usuari;
import es.uv.saic.dto.OrganDTO;
import es.uv.saic.dto.OrganRepositoryDTO;
import es.uv.saic.dto.OrganTransferDTO;
import es.uv.saic.service.IndicadorEnquestaService;
import es.uv.saic.service.OrganService;
import es.uv.saic.service.ProcesService;
import es.uv.saic.service.UsuariService;

@RestController
public class OrganController {
    @Autowired
    private UsuariController uc;

    @Autowired
    private OrganService os;

    @Autowired
    private IndicadorEnquestaService ies;

    @Autowired
    private UsuariService us;

    @Autowired
    private ProcesService ps;

    /*
     * Endpoint for getTitulacions
     */
    @GetMapping("/getTitulacionsWithCentre")
    public List<OrganDTO> getTitulacionsWithCentre() {
        return os.findAllTitulacionsWithCentre();
    }

    /*
     * Endopint for findByRuct
     */
    @GetMapping("/getAllIndsByRuct/{ruct}/{curs}")
    public List<IndicadorEnquesta> getAllIndsByRuct(@PathVariable Integer ruct, @PathVariable Integer curs) {
        Organ o = os.findByRuct(ruct); 
        return ies.getAllInds(o, curs);
    }

    @GetMapping("/getOrgByRuct/{ruct}")
    public OrganDTO getOrgByRuct(@PathVariable Integer ruct) {

		OrganRepositoryDTO organ = os.findByRuctDTO(ruct);
		OrganDTO organDto = new OrganDTO(organ);

        return organDto;
    }

    /*
     * Endpoint para findById
     */
    @GetMapping("/findById/{tlugar}/{idTitulacio}")
    public OrganTransferDTO findByID(@PathVariable String tlugar,  @PathVariable Integer idTitulacio) {
        Organ organ = os.findByID(tlugar, idTitulacio);

        return new OrganTransferDTO(organ);

    }

    /*
     * Endpoint para getTitulacionsByTypeCentre
     */
    @GetMapping("/getTitulacionsByTypeCentre/{lugar}/{type}")
    public ResponseEntity<?> getTitulacionsByTypeCentre(@PathVariable Integer lugar, @PathVariable Integer type) {
        try {
            List<Organ> organList = os.getTitulacionsByTypeCentre(lugar, type);
            List<OrganTransferDTO> organDTOList = new ArrayList<>();
            
            for(Organ org: organList) {
                organDTOList.add(new OrganTransferDTO(org));
            }

            return ResponseEntity.ok(organDTOList);
        } catch(Exception e) {
            return ResponseEntity.badRequest().body("Error al obtener los organos" +
                " por lugar y ambit: " + e.getMessage());
        }
    }

    @GetMapping("/existsOrg/{tlugar}/{idTitulacio}")
    public boolean existsOrg(@PathVariable String tlugar,  @PathVariable Integer idTitulacio) {
        return os.exists(tlugar, idTitulacio);
    }

    @GetMapping("/getTitulacionsByCentreTambit/{centre}/{tambit}")
    public ResponseEntity<?> getTitulacionsByCentreTambit(@PathVariable Integer centre, @PathVariable String tambit) {
        try {
            List<Organ> organList = os.findActiveTitulacionsByCentreTambit(centre, tambit);
            List<OrganTransferDTO> organDTOList = new ArrayList<>();

            for(Organ org: organList) {
				System.out.println(org.getNomCas());
                organDTOList.add(new OrganTransferDTO(org));
            }

            return ResponseEntity.ok(organDTOList);
        } catch(Exception e) {
            return ResponseEntity.badRequest().body("Error al obtener los organos" +
                " por lugar y ambit: " + e.getMessage());
        }
    }

    @GetMapping("/getTitulacions/supervisor")
    public List<OrganDTO> getTitulacionsSupervisor() {
        return os.getTitulacions().stream()
            .filter(o -> o.getOrgan().getId().getLugar() != 99)
            .map(OrganDTO::new)
            .collect(Collectors.toList());
    }
    
    @GetMapping("/getTitulacionsByCentre/{centre}")
    public List<OrganDTO> getTitulacionsByCentre(@PathVariable Integer centre) {
        return os.getTitulacionsByCentre(centre).stream()
            .map(OrganDTO::new)
            .distinct()
            .collect(Collectors.toList());
    }

    @PostMapping("/findOrgansByUsuari")
    public List<OrganDTO> findOrgansByUsuari(@RequestBody Usuari usuari) {
        return uc.findActiveRols(usuari).stream()
            .map(ur -> new OrganDTO(ur.getOrgan()))
            .distinct()
            .collect(Collectors.toList());
    }

    @GetMapping("/getCentres")
    public ResponseEntity<?> getCentres() {
        try {
            List<Organ> organList = os.getCentres();
            List<OrganDTO> organDTOList = new ArrayList<>();
            
            for(Organ org: organList) {
                organDTOList.add(new OrganDTO(org));
            }

            return ResponseEntity.ok(organDTOList);
        } catch(Exception e) {
            return ResponseEntity.badRequest().body("Error al obtener los centros: " + e.getMessage());
        }
    }

    @GetMapping("/getActiveCentres")
    public ResponseEntity<?> getActiveCentres() {
        try {
            List<Organ> organList = os.getActiveCentres();
            List<OrganDTO> organDTOList = new ArrayList<>();
            
            for(Organ org: organList) {
                organDTOList.add(new OrganDTO(org));
            }

            return ResponseEntity.ok(organDTOList);
        } catch(Exception e) {
            return ResponseEntity.badRequest().body("Error al obtener los centros: " + e.getMessage());
        }
    }

    // Funciones ajax
    @PostMapping("/ajax/search/titulations")
	public HashMap<String, Object> getTitulationsByCenter(@RequestParam(name="centers[]", required=false) List<Integer> centres,
        @RequestParam String usuari ) throws IOException {	
        
        HashMap<String, Object> model = new HashMap<>();
        Usuari u = us.findByUsername(usuari);

		if(centres == null) { centres = us.getSupervisableCentres(u); }
		List<Organ> org_list = this.os.findTitulacionsByCentre(centres);

		List<DummyDataTransfer> supervisable_cents = new ArrayList<DummyDataTransfer>();
		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);
		}
		
		DummyDataTransfer o = new DummyDataTransfer();
		o = new DummyDataTransfer();
		Organ org = os.findByID("T", 1);
		o.setText(org.getNomCas());
		o.setText2(org.getNomVal());
		o.setValue(1);
		supervisable_cents.add(o);
		o = new DummyDataTransfer();
		org = os.findByID("T", 2);
		o.setText(org.getNomCas());
		o.setText2(org.getNomVal());
		o.setValue(2);
		supervisable_cents.add(o);
		o = new DummyDataTransfer();
		org = os.findByID("T", 0);
		o.setText(org.getNomCas());
		o.setText2(org.getNomVal());
		o.setValue(0);
		supervisable_cents.add(o);

		Collections.sort(supervisable_cents, (a, b) -> {
			return a.getText2().compareTo(b.getText2());
		});

		model.put("sup_orgs", supervisable_cents);
		return model;
	}

    // POST que recoge toda las titulaciones que contiene un centro para el manager
	@PostMapping("/ajax/search/managers/titulations")
	public HashMap<String, Object> getCenterTitulations(
			@RequestParam("center") Integer centre) {
        
        HashMap<String, Object> model = new HashMap<>();
		List<Organ> sup_titulacions;
		sup_titulacions = this.os.getTitulacionsByCentre(centre);
		model.put("resp_titulacions", sup_titulacions);

		return model;
	}

    @PostMapping("/ajax/find/titulations2")
	public HashMap<String, Object> getTitulationsByCenters(@RequestParam("centers[]") List<Integer> centres, @RequestParam("procedure") Integer idProces) throws IOException {	
		
        HashMap<String, Object> model = new HashMap<>();
        List<DummyDataTransfer> titulations = new ArrayList<DummyDataTransfer>();
		DummyDataTransfer o = new DummyDataTransfer();
		
		if(idProces > 0) {
			Proces p = ps.findByID(idProces);
			if(p.getAmbit().equals("U")) {
				o = new DummyDataTransfer();
				Organ org = os.findByID("T", 0);
				o.setText(org.getNomCas());
				o.setText2(org.getNomVal());
				titulations.add(o);
			}
			else if(p.getAmbit().equals("C")) {
				o = new DummyDataTransfer();
				Organ org = os.findByID("T", 1);
				o.setText(org.getNomCas());
				o.setText2(org.getNomVal());
				o.setValue(1);
				titulations.add(o);
				o = new DummyDataTransfer();
				org = os.findByID("T", 2);
				o.setText(org.getNomCas());
				o.setText2(org.getNomVal());
				o.setValue(2);
				titulations.add(o);
				o = new DummyDataTransfer();
				org = os.findByID("T", 0);
				o.setText(org.getNomCas());
				o.setText2(org.getNomVal());
				o.setValue(0);
				titulations.add(o);
			}
			else if(p.getAmbit().equals("T")) {
				for(Integer centre : centres) {
					List<Organ> org_list = this.os.getTitulacionsByCentre(centre);
					for(Organ or : org_list) {
						DummyDataTransfer c = new DummyDataTransfer();
						c.setText(or.getNomCas());
						c.setText2(or.getNomVal());
						c.setValue(or.getId().getLugar());
						titulations.add(c);
					}
				}	
				Collections.sort(titulations, 
	                    (o1, o2) -> Integer.valueOf(o1.getValue()).compareTo(Integer.valueOf(o2.getValue())));
			}
		}
		else {
			for(Integer centre : centres) {
				List<Organ> org_list = this.os.getTitulacionsByCentre(centre);
				for(Organ or : org_list) {
					DummyDataTransfer c = new DummyDataTransfer();
					c.setText(or.getNomCas());
					c.setText2(or.getNomVal());
					c.setValue(or.getId().getLugar());
					titulations.add(c);
				}
			}	
			Collections.sort(titulations, 
                    (o1, o2) -> Integer.valueOf(o1.getValue()).compareTo(Integer.valueOf(o2.getValue())));
		}
		
		model.put("sup_orgs", titulations);
		return model;
	}
	
	@PostMapping("/ajax/find/titulations")
	public HashMap<String, Object> getTitulationsByCenter(@RequestParam("center") Integer centre, @RequestParam("procedure") Integer idProces) throws IOException {	
		HashMap<String, Object> model = new HashMap<>();
        Proces p = ps.findByID(idProces);
		List<DummyDataTransfer> titulations = new ArrayList<DummyDataTransfer>();
		DummyDataTransfer o = new DummyDataTransfer();
		
		if(p.getAmbit().equals("U")) {
			o = new DummyDataTransfer();
			Organ org = os.findByID("T", 0);
			o.setText(org.getNomCas());
			o.setText2(org.getNomVal());
			titulations.add(o);
		}
		else if(p.getAmbit().equals("C")) {
			o = new DummyDataTransfer();
			Organ org = os.findByID("T", 1);
			o.setText(org.getNomCas());
			o.setText2(org.getNomVal());
			o.setValue(1);
			titulations.add(o);
			o = new DummyDataTransfer();
			org = os.findByID("T", 2);
			o.setText(org.getNomCas());
			o.setText2(org.getNomVal());
			o.setValue(2);
			titulations.add(o);
			o = new DummyDataTransfer();
			org = os.findByID("T", 0);
			o.setText(org.getNomCas());
			o.setText2(org.getNomVal());
			o.setValue(0);
			titulations.add(o);
		}
		else if(p.getAmbit().equals("T")) {
			o = new DummyDataTransfer();
			o.setText("Todos los grados");
			o.setText2("Tots els graus");
			o.setValue(1);
			titulations.add(o);
			o = new DummyDataTransfer();
			o.setText("Todos los másters");
			o.setText2("Tots els màsters");
			o.setValue(2);
			titulations.add(o);
			o = new DummyDataTransfer();
			o.setText("Todas las titulaciones");
			o.setText2("Totes les titulacions");
			o.setValue(0);
			titulations.add(o);
			List<Organ> org_list = this.os.getTitulacionsByCentre(centre);
			for(Organ or : org_list) {
				DummyDataTransfer c = new DummyDataTransfer();
				c.setText(or.getNomCas());
				c.setText2(or.getNomVal());
				c.setValue(or.getId().getLugar());
				titulations.add(c);
			}
		}
		model.put("sup_orgs", titulations);
        return model;
	}

    @PostMapping("/ajax/get/titulations")
	public HashMap<String, Object> getAllTitulationsByCenter(@RequestParam("center") Integer centre) throws IOException {	
		List<DummyDataTransfer> titulations = new ArrayList<DummyDataTransfer>();
		DummyDataTransfer o = new DummyDataTransfer();
		HashMap<String, Object> model = new HashMap<>();

		o = new DummyDataTransfer();
		o.setText("Todos los grados");
		o.setText2("Tots els graus");
		o.setValue(1);
		titulations.add(o);
		o = new DummyDataTransfer();
		o.setText("Todos los másters");
		o.setText2("Tots els màsters");
		o.setValue(2);
		titulations.add(o);
		o = new DummyDataTransfer();
		o.setText("Todas las titulaciones");
		o.setText2("Totes les titulacions");
		o.setValue(0);
		titulations.add(o);
		List<Organ> org_list = this.os.getTitulacionsByCentre(centre);
		for(Organ or : org_list) {
			DummyDataTransfer c = new DummyDataTransfer();
			c.setText(or.getNomCas());
			c.setText2(or.getNomVal());
			c.setValue(or.getId().getLugar());
			titulations.add(c);
		}
		model.put("sup_orgs", titulations);
        return model;
	}

    @PostMapping("/ajax/find/centers")
	public HashMap<String, Object> getAllCentresByAmbit(@RequestParam("procedure") Integer idProces) throws IOException {	
		HashMap<String, Object> model = new HashMap<>();
        List<DummyDataTransfer> centres = new ArrayList<DummyDataTransfer>();
		if(idProces > 0) {
			Proces p = ps.findByID(idProces);
			if(p.getAmbit().equals("C")) {
				DummyDataTransfer o = new DummyDataTransfer();
				o.setText("Todos los centros");
				o.setText2("Tots els centres");
				o.setValue(0);
				centres.add(o);
			}
		}
		List<Organ> org_list = this.os.getActiveCentres();
		for(Organ or : org_list) {
			DummyDataTransfer c = new DummyDataTransfer();
			c.setText(or.getNomCas());
			c.setText2(or.getNomVal());
			c.setValue(or.getId().getLugar());
			centres.add(c);
		}
		model.put("sup_centers", centres);
        return model;
	}
}
