package es.uv.saic.web;

import java.io.IOException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;

import org.springframework.beans.factory.annotation.Autowired;
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.DeleteMapping;
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 com.fasterxml.jackson.databind.ObjectMapper;

import es.uv.saic.domain.Categoria;
import es.uv.saic.domain.Grafica;
import es.uv.saic.domain.Indicador;
import es.uv.saic.domain.Link;
import es.uv.saic.domain.Usuari;
import es.uv.saic.dto.CategoriaDocumentDTO;
import es.uv.saic.dto.InstanciaGanttDTOImp;
import es.uv.saic.dto.OrganDTO;
import es.uv.saic.feign.DashboardClient;

@Controller
public class DashboardController {

	@Autowired
	private DashboardClient dbc;
	
	@Autowired
    private ObjectMapper objectMapper;

    @GetMapping("/dashboard")
    public String getOrganList(Model model, Authentication auth) {

        HashMap<String, Object> response =
                dbc.getOrganList(((Usuari) auth.getPrincipal()).getUsuari());

        if (response != null) {
            return response.get("organ").toString() == "0" ? "dashboard" : "redirect:/dashboard/" + response.get("organ").toString();
        }

        return "401";
    }

    @GetMapping("/dashboard/{ruct}")
    public String getDashboardOrgan(Model model, Authentication auth, @PathVariable Integer ruct) {
        HashMap<String, Object> response =
                dbc.getDashboardOrgan(ruct, ((Usuari) auth.getPrincipal()).getUsuari());

        if (response != null && response.get("redirect") != null) {
            if (response.containsKey("organ")) {
                Object organRaw = response.get("organ");
                try {
                    OrganDTO organDTO = objectMapper.convertValue(organRaw, OrganDTO.class);
                    response.put("organ", organDTO);
                } catch (Exception ex) {
                    System.err.println("Error reconstruyendo OrganDTO: " + ex.getMessage());
                }
            }

            if (response.containsKey("titulacions")) {
                Object titsRaw = response.get("titulacions");
                try {
                    List<OrganDTO> tits = objectMapper.convertValue(
                            titsRaw,
                            objectMapper.getTypeFactory().constructCollectionType(List.class, OrganDTO.class)
                    );
                    response.put("titulacions", tits);
                } catch (Exception ex) {
                    System.err.println("Error reconstruyendo lista de OrganDTO: " + ex.getMessage());
                }
            }

            model.addAllAttributes(response);

			String status = response.get("redirect").toString();
			if(status.equals("U")) {
				return "dashboardUniversitat";
			} else if (status.equals("C")) {
				return "dashboardCentre";
			} else if (status.equals("T")){
				return "dashboardTitulacio";
			}
        }

        return "401";
    }
	
	// GET para conseguir todos los procedimiento a partir del idTitulacio
	@GetMapping("/dashboard/procedures/{idTitulacio}")
	@ResponseBody
	public List<?> loadReports(Model model, Authentication auth, @PathVariable Integer idTitulacio) {
		return dbc.loadReports(idTitulacio);
	}

	@GetMapping("/dashboard/graphs/inds/{ruct}/{tambit}")
	@ResponseBody
	public List<Indicador> getGraphDataByRuctTambit(@PathVariable Integer ruct, @PathVariable String tambit) throws ParserConfigurationException {
		return dbc.getGraphDataByRuctTambit(ruct, tambit);
	}

    @GetMapping("/dashboard/graphs/inds/{ruct}")
	@ResponseBody
	public List<Indicador> getGraphDataByRuct(@PathVariable Integer ruct) throws ParserConfigurationException {
		return dbc.getGraphDataByRuct(ruct);
	}
	
	// GET para conseguir la documentación ya a aportada a partir del id de la tituación
	@GetMapping("/dashboard/documents/{idTitulacio}")
	@ResponseBody
	public List<CategoriaDocumentDTO> loadDocuments(Model model, @PathVariable Integer idTitulacio){
		List<CategoriaDocumentDTO> a = dbc.loadDocuments(idTitulacio);
		for (CategoriaDocumentDTO categoriaDocumentDTO : a) {
			System.out.println("Categoria: " + categoriaDocumentDTO);
		}
		return a;
	}

	// GET para conseguir el diagrama de gantt a partir del ruct
	@GetMapping("/dashboard/gantt/{ruct}")
	@ResponseBody
	public List<InstanciaGanttDTOImp> loadGantt(Model model, @PathVariable Integer ruct){
		return dbc.loadGantt(ruct);
	}
		
	@GetMapping("/dashboard/documents/cats/{idCategoria}/{tambit}")
	@ResponseBody
	public List<Categoria> getDocumentChildCats(@PathVariable Integer idCategoria, @PathVariable String tambit) {
		return dbc.getDocumentChildCats(idCategoria, tambit);
	}

	@GetMapping("/dashboard/documents/catsu/{idCategoria}/{tambit}")
	@ResponseBody
	public List<Categoria> getDocumentChildCatsU(@PathVariable Integer idCategoria, @PathVariable String tambit) {
		return  dbc.getDocumentChildCatsU(idCategoria, tambit);
	}
	
	// POST para guardar un documento en el sistema
	@PostMapping("/dashboard/documents")
	@ResponseBody
	public void uploadDocument(Model model, @RequestParam MultipartFile file, @RequestParam Integer idCategoria, 
							   @RequestParam Integer lugar, @RequestParam String tlugar) throws IllegalStateException, IOException {
		dbc.uploadDocument(file, idCategoria, lugar, tlugar);
	}

	// POST para añadir un documento a un centro cocncreto
	@PostMapping("/dashboard/documents/archive")
	@ResponseBody
	public void archiveDocuments(Model model, @RequestParam Integer lugar, @RequestParam String tlugar) {
		dbc.archiveDocuments(lugar, tlugar);
	}

	// GET para conseguir todos los graficos a partir de un RUCT
	@GetMapping("/dashboard/graphs/list/{ruct}")
	@ResponseBody
	public List<Grafica> getGraphDataList(@PathVariable Integer ruct) throws ParserConfigurationException {
		return dbc.getGraphDataList(ruct);
	}
	
	//GET para conseguir todos los datos concretos de tasas para las tablas
	@GetMapping("/dashboard/graphs/rates/{lugar}")
	@ResponseBody
	public List<Indicador> getGraphDataTaxes(@PathVariable Integer lugar) throws ParserConfigurationException {
		return dbc.getGraphDataTaxes(lugar);
	}

	@GetMapping("/dashboard/links/{ruct}")
	@ResponseBody
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public List<Link> getLinks(@PathVariable Integer ruct) {
		return dbc.getLinks(ruct);
	}

	@PostMapping("/dashboard/links/{ruct}")
	@ResponseBody
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public Link createLink(@PathVariable Integer ruct, @RequestParam String dataExp) throws ParseException {
		return dbc.createLink(ruct, dataExp);
	}

	@DeleteMapping("/dashboard/links/{id}")
	@ResponseBody
	@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
	public Integer deleteLink(@PathVariable Integer id) {
		return dbc.deleteLink(id);
	}
}
