package jumapacelaya.gob.mx.appots.controlador;

import jumapacelaya.gob.mx.appots.dto.dictamenDTO;
import jumapacelaya.gob.mx.appots.dto.empleadoOrigenDTO;
import jumapacelaya.gob.mx.appots.dto.fotoOTDTO;
import jumapacelaya.gob.mx.appots.dto.motivoPreguntaDTO;
import jumapacelaya.gob.mx.appots.dto.noCommMensajeDTO;
import jumapacelaya.gob.mx.appots.dto.origenDTO;
import jumapacelaya.gob.mx.appots.dto.otDTO;
import jumapacelaya.gob.mx.appots.dto.preguntaDTO;
import jumapacelaya.gob.mx.appots.dto.respuestaOTDTO;
import jumapacelaya.gob.mx.appots.dto.transaccionDTO;
import jumapacelaya.gob.mx.appots.servicio.AppOtsServicio;

import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import io.micronaut.core.annotation.Nullable;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.PathVariable;
import io.micronaut.http.annotation.Put;
import io.micronaut.http.exceptions.HttpStatusException;
import jakarta.inject.Inject;
import jumapacelaya.gob.mx.predios.dto.PredioDTO;
import jumapacelaya.gob.mx.predios.servicio.PredioServicio;

@Controller("/appots")
public class AppOtsControlador {

    private final AppOtsServicio servicio;
    private final PredioServicio pServicio;

    @Inject
    public AppOtsControlador(AppOtsServicio servicio, PredioServicio pServicio) {
        this.servicio = servicio;
        this.pServicio = pServicio;
    }

    @Get("/infopredioappots/{vPredContrRefer}")
    public HttpResponse<PredioDTO> obtenerPredioAppOts(@PathVariable String vPredContrRefer) {
        PredioDTO dto = pServicio.obtenerPredioAppOts(vPredContrRefer);
        if (dto == null) {
            return HttpResponse.notFound();
        }
        return HttpResponse.ok(dto);
    }

    @Get("/infopredio/{predioid}")
    public HttpResponse<?> redirigirAConsultaPredio(@PathVariable Long predioid) {
        String redirPath = "/predios/appots/{id}" + predioid;
        return HttpResponse.redirect(URI.create(redirPath));
    }

    @Get("/ots/predio/{predioid}")
    public HttpResponse<List<otDTO>> obtenerOTsPorPredio(@PathVariable Long predioid) {
        List<otDTO> lista = servicio.obtenerOTsPorPredio(predioid);
        return HttpResponse.ok(lista);
    }

    //Consulta OTs Pendientes ↓
    @Get("/todo/ot/{otid}")
    public otDTO obtenerOT(@PathVariable Long otid) {
        List<otDTO> lista = servicio.obtenerInfoGralOT(otid);

        if (lista != null && !lista.isEmpty()) {
            return lista.get(0); // ✅ Solo devolvemos el primer resultado
        } else {
            throw new HttpStatusException(HttpStatus.NOT_FOUND, "No se encontró la OT con ID " + otid);
        }
    }

    //Consulta OTs ↓
    @Get("/todo/prog/cuadrilla/{cuadrillaId}/{motivoId}")
    public HttpResponse<List<otDTO>> obtenerOtsPorCuadrillaYMotivo(@PathVariable String cuadrillaId,
                                                                            @PathVariable String motivoId) {
        List<otDTO> resultado = servicio.obtenerOtsProgramadasPorCuadrillaYMotivo(cuadrillaId, motivoId);
        if (resultado.isEmpty()) {
            throw new HttpStatusException(HttpStatus.NOT_FOUND, "No se encontraron OTs para los filtros dados.");
        }
        return HttpResponse.ok(resultado);
    }

    @Get("/todo/prog/motivo/{origenid}/{motivoid}")
    public HttpResponse<?> obtenerOtsPorOrigenYMotivo(@PathVariable String origenid,
                                                    @PathVariable String motivoid) {
        try {
            List<otDTO> resultado = servicio.obtenerOtsProgramadasPorOrigenYMotivo(origenid, motivoid);

            if (resultado.isEmpty()) {
                return HttpResponse.notFound(
                    Collections.singletonMap("message", "No se encontraron OTs programadas para los parámetros dados")
                );
            }

            return HttpResponse.ok(resultado);

        } catch (Exception e) {
            return HttpResponse.serverError(
                Collections.singletonMap("message", "Error al obtener OTs programadas: " + e.getMessage())
            );
        }
    }

    @Get("/todo/prog/areaorigenmotivo/{areaid}/{origenid}/{motivoid}")
    public HttpResponse<?> obtenerOtsProgramadasPorAreaOrigenMotivo(@PathVariable String areaid,
                                                                    @PathVariable String origenid,
                                                                    @PathVariable String motivoid) {
        try {
            List<otDTO> resultado = servicio.obtenerOtsProgramadasPorAreaOrigenMotivo(areaid, origenid, motivoid);
            if (resultado.isEmpty()) {
                return HttpResponse.notFound(Collections.singletonMap("message", "No se encontraron OTs programadas con los parámetros proporcionados"));
            }
            return HttpResponse.ok(resultado);
        } catch (Exception e) {
            return HttpResponse.serverError(
                Collections.singletonMap("message", "Error al obtener OTs programadas por área, origen y motivo: " + e.getMessage())
            );
        }
    }
    //Consulta OTs ↑
    //Consulta OTs Pendientes ↑

    //Consulta Catalogos ↓
    @Get("/catalogos/origenes/{origenid}")
    public HttpResponse<?> obtenerOrigenes(@PathVariable String origenid) {
        List<origenDTO> origenes = servicio.obtenerOrigenes(origenid);
        return HttpResponse.ok(origenes);
    }

    @Get("/catalogos/motivos/{motivoid}")
    public HttpResponse<?> obtenerMotivos(@PathVariable String motivoid) {
        try {
            List<Map<String, Object>> resultado = servicio.obtenerMotivos(motivoid);
            return HttpResponse.ok(resultado);
        } catch (Exception e) {
            return HttpResponse.serverError(
                Collections.singletonMap("message", "Error interno: " + e.getMessage())
            );
        }
    }

    @Get("/catalogos/motivosarea/{areaid}/{motivoid}")
    public HttpResponse<?> obtenerMotivosPorAreaYMotivo(@PathVariable String areaid,
                                                        @PathVariable String motivoid) {
        try {
            List<Map<String, Object>> resultado = servicio.obtenerMotivosPorAreaYMotivo(areaid, motivoid);
            return HttpResponse.ok(resultado);
        } catch (Exception e) {
            return HttpResponse.serverError(Collections.singletonMap("error", e.getMessage()));
        }
    }

    @Get("/catalogos/motivossuspen/{motsusid}")
    public HttpResponse<?> obtenerMotivoSusp(@PathVariable String motsusid) {
        try {
            Integer id = "all".equalsIgnoreCase(motsusid) ? null : Integer.valueOf(motsusid);
            List<Map<String, Object>> resultado = servicio.obtenerMotivoSusp(id);
            return HttpResponse.ok(resultado);
        } catch (Exception e) {
            return HttpResponse.serverError(
                Collections.singletonMap("error", "Error al consultar motivos de suspensión: " + e.getMessage())
            );
        }
    }

    @Get("/catalogos/preguntas/{preguntaid}/{dato}")
    public HttpResponse<?> obtenerPreguntas(@PathVariable String preguntaid,
                                            @PathVariable Optional<String> dato) {
        try {
            List<preguntaDTO> resultado = servicio.obtenerPreguntas(preguntaid, dato.orElse(""));
            return HttpResponse.ok(resultado);
        } catch (Exception e) {
            return HttpResponse.serverError(Collections.singletonMap("error", e.getMessage()));
        }
    }

    @Get("/catalogos/unimed/{umid}")
    public HttpResponse<?> obtenerUnidadMedida(@PathVariable String umid) {
        try {
            List<Map<String, Object>> resultado = servicio.obtenerUnidadesMedida(umid);
            return HttpResponse.ok(resultado);
        } catch (Exception e) {
            return HttpResponse.serverError(
                Map.of("message", "Internal Server Error",
                       "_embedded", Map.of("errors", List.of(Map.of("message", "Error al obtener unidad de medida: " + e.getMessage())))
                )
            );
        }
    }

    @Get("/catalogos/motpreg/{motivoid}/{preguntaid}")
    public HttpResponse<?> obtenerMotivoPreguntas(@PathVariable String motivoid,
                                                @PathVariable String preguntaid) {
        try {
            List<motivoPreguntaDTO> resultado = servicio.obtenerMotivoPreguntas(motivoid, preguntaid);

            return HttpResponse.ok(resultado.isEmpty()
                    ? Collections.singletonMap("message", "No se encontraron resultados")
                    : resultado);

        } catch (Exception e) {
            return HttpResponse.serverError(Collections.singletonMap("message",
                    "Error al consultar motivo-pregunta: " + e.getMessage()));
        }
    }

    @Get("/catalogos/dictamenes/{motivoid}/{dictamenid}")
    public HttpResponse<?> obtenerDictamenes(@PathVariable String motivoid, @PathVariable String dictamenid) {
        try {
            List<dictamenDTO> data = servicio.obtenerDictamenesPorMotivoYDictamen(motivoid, dictamenid);
            return HttpResponse.ok(Collections.singletonMap("data", data));
        } catch (Exception e) {
            return HttpResponse.serverError(Collections.singletonMap("message", "Error interno: " + e.getMessage()));
        }
    }

    @Get("/catalogos/cortesfisicos/{motivoid}")
    public HttpResponse<List<Map<String, Object>>> obtenerCortesFisicos(@PathVariable String motivoid) {
        List<Map<String, Object>> data = servicio.obtenerCortesFisicos(motivoid);
        return HttpResponse.ok(data);
    }

    @Get(uri = "/catalogos/empleadosorigen/{origenid}{/usuarioid}", produces = MediaType.APPLICATION_JSON)
    public List<empleadoOrigenDTO> obtenerEmpleadosPorOrigenYUsuario(@PathVariable String origenid,
                                                                      @PathVariable @Nullable String usuarioid) {
        return servicio.obtenerEmpleadosPorOrigenYUsuario(origenid, usuarioid);
    }
    //Consulta Catalogos ↑

    //Status OTs ↓
    @Get("/status/enruta/{otid}")
    public HttpResponse<?> marcarEnRuta(@PathVariable Long otid) {
        return manejarActualizacion(otid, "R");
    }

    @Get("/status/ensitio/{otid}")
    public HttpResponse<?> marcarEnSitio(@PathVariable Long otid) {
        return manejarActualizacion(otid, "S");
    }

    @Get("/status/comenzada/{otid}")
    public HttpResponse<?> marcarComenzada(@PathVariable Long otid) {
        return manejarActualizacion(otid, "C");
    }

    @Get("/status/terminada/{otid}")
    public HttpResponse<?> marcarTerminada(@PathVariable Long otid) {
        return manejarActualizacion(otid, "T");
    }

    @Get("/status/reprogramada/{otid}")
    public HttpResponse<?> marcarReprogramada(@PathVariable Long otid) {
        return manejarActualizacion(otid, "D");
    }

    private HttpResponse<?> manejarActualizacion(Long otid, String situacion) {
        try {
            Map<String, Object> result = servicio.actualizarSituacionOT(otid, situacion);
            if ("200".equals(result.get("status"))) {
                return HttpResponse.ok(result);
            } else {
                return HttpResponse.serverError(result);
            }
        } catch (Exception e) {
            return HttpResponse.serverError(Map.of(
                    "status", "500",
                    "message", "Error: " + e.getMessage(),
                    "data", Map.of("OTID", otid)
            ));
        }
    }
    //Status OTs ↑

    @Put("/nocomm/ot/{otid}")
    public HttpResponse<?> registrarNoComm(@PathVariable Long otid, @Body List<noCommMensajeDTO> mensajes) {
        Map<String, Object> result = servicio.registrarAvisoNoComm(otid, mensajes);
        if ("200".equals(result.get("status"))) {
            return HttpResponse.ok(result);
        } else if ("404".equals(result.get("status"))) {
            return HttpResponse.notFound(result);
        } else {
            return HttpResponse.serverError(result);
        }
    }

    //Guardar información ↓
    @Put("/guardaresp/ot/{otid}")
    public HttpResponse<?> guardarRespuestas(@PathVariable Long otid, @Body List<respuestaOTDTO> otList) {
        try {
            servicio.guardarRespuestas(otList);
            return HttpResponse.ok(new RespuestaOKDTO(
                200,
                "Respuestas guardadas exitosamente.",
                otid
            ));
        } catch (Exception e) {
            return HttpResponse.serverError(new RespuestaErrorDTO(
                500,
                "Error al guardar respuestas: " + e.getMessage(),
                otid
            ));
        }
    }

    public record RespuestaOKDTO(int status, String message, Long otid) {}
    public record RespuestaErrorDTO(int status, String message, Long otid) {}
    
    @Put("/guardaresp/fotos/{otid}")
    public HttpResponse<?> guardarFotos(@PathVariable Integer otid,
                                        @Body List<fotoOTDTO> fotosOT) {
        try {
            servicio.guardarFotosOT(otid, fotosOT);
            return HttpResponse.ok(Map.of(
                "status", "200",
                "message", "Fotos guardadas exitosamente",
                "data", Map.of("OTID", otid)
            ));
        } catch (Exception e) {
            return HttpResponse.serverError(Map.of(
                "status", "500",
                "message", "Error al guardar las fotos",
                "error", e.getMessage()
            ));
        }
    }

    @Get("/guardaresp/comprueba/{transaccid}")
    public List<transaccionDTO> obtenerPorTransaccionId(@PathVariable String transaccid) {
        return servicio.obtenerPorTransaccionId(transaccid);
    }
    //Guardar información ↑
}
