package in.cdac.medinfo.csnotk.csnoserv.rest;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import static in.cdac.medinfo.csnotk.csnoserv.CSnoServResource.*;
import in.cdac.medinfo.csnotk.csnoserv.CSnoServResource;
import java.text.DateFormat;
import java.util.Collections;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import in.cdac.medinfo.csnotk.csnolib.icdmap.MapResult;
import in.cdac.medinfo.csnotk.csnolib.icdmap.Record;
import in.cdac.medinfo.csnotk.csnolib.model.SimpleMapRefsetResult;

//Logs
import in.cdac.medinfo.csnotk.csnolib.util.LoggerUtility;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;


@Path("/map")
public class MapController{
    /**
     * Mapping API - SNOMED CT to ICD-10 codes
     */
    @GET
    @Produces({ MediaType.APPLICATION_JSON + ";charset=utf-8" })
    @Path("/icdmap")
    public Response mapTerm(@QueryParam("id") String id, @DefaultValue("") @QueryParam("gender") String gender,
                            @DefaultValue("") @QueryParam("birthdate") String birthdate,
                            @DefaultValue("") @QueryParam("diagnosisdate") String diagnosisdate,
                            @DefaultValue("") @QueryParam("secondary") String secondary, @QueryParam("callback") String callback) {
        CSnoServResource.initICDProperties();
        CSnoServResource.initProperties();
        Logger logger = LogManager.getLogger(MapController.class);
        if (id == null || id.equalsIgnoreCase("") || !id.matches(_0_9)) {
            logger.error(LoggerUtility.MapICDException, INVALID_QUERY_PARAMETER_VALUE_ID , id);
            return CORSHeaderSupport.addCORSHeader(Response.Status.BAD_REQUEST,Response.Status.BAD_REQUEST.toString());
        }

        Record record = new Record();
        String jsonString = "";
        try {
            record.setPrimarySCTID(Long.parseLong(id));
            record.setGender(gender);
            if (birthdate != null && !birthdate.equalsIgnoreCase("")) {
                DateFormat df = new SimpleDateFormat("MM-dd-yyyy");
                Date birthDate = df.parse(birthdate);
                record.setBirthDate(birthDate);
            }
            if (diagnosisdate != null && !diagnosisdate.equalsIgnoreCase("")) {
                DateFormat df = new SimpleDateFormat("MM-dd-yyyy");
                Date diagnosisDate = df.parse(diagnosisdate);
                record.setDiagnosisDate(diagnosisDate);
            }
            secondary = java.net.URLDecoder.decode(secondary, UTF_8).trim().replaceAll(" ", "+");
            if (secondary != null && !secondary.equalsIgnoreCase("")) {
                if ((secondary.length() > 6) && secondary.matches(_0_9)) {
                    record.setSecondarySCTID(secondary);
                } else {
                    logger.error(LoggerUtility.MapICDException,
                            "Invalid Query Parameter Value: secondary: {}, it is not SCTID" , secondary);
                    return CORSHeaderSupport.addCORSHeader(Response.Status.BAD_REQUEST,Response.Status.BAD_REQUEST.toString());
                }
            }
            MapResult mapResult = mapAgent.map(record);
            jsonString = gson.toJson(mapResult);
        } catch (ParseException e) {
            logger.error(LoggerUtility.MapICDException, "Invalid Query Parameter Value: birthdate or diagnosisdate: {} or {}" , birthdate
                    , diagnosisdate);
            return CORSHeaderSupport.addCORSHeader(Response.Status.BAD_REQUEST,Response.Status.BAD_REQUEST.toString());
        } catch (Exception e) {
            // Log the Exception
            logger.error(LoggerUtility.MapICDException, LoggerUtility.createErrorMessage(e));
            return CORSHeaderSupport.addCORSHeader(Response.Status.INTERNAL_SERVER_ERROR
                    ,Response.Status.INTERNAL_SERVER_ERROR.toString() + " : " + LoggerUtility.createErrorMessage(e));
        }
        // if callback in URL and is not just the "?" (e.g. from localhost)
        if (callback != null && callback.length() > 1) {
            return CORSHeaderSupport.addCORSHeader(Response.Status.OK,callback + "(" + jsonString + ");");
        } else {
            return CORSHeaderSupport.addCORSHeader(Response.Status.OK,jsonString);
        }
    }


    /**
     * Return SimpleMapTarget from ConceptId
     *
     * @param callback
     * @return
     */
    @GET
    @Produces({ MediaType.APPLICATION_JSON + ";charset=utf-8" })
    @Consumes({ MediaType.APPLICATION_FORM_URLENCODED })
    @Path("/simplemap")
    public Response getSimpleMapTarget(@QueryParam("id") String id, @QueryParam("callback") String callback) {

        CSnoServResource.initProperties();
        Logger logger = LogManager.getLogger(MapController.class);
        String jsonString = "";
        if (id == null || id.equalsIgnoreCase("") || !id.matches(_0_9)) {
            logger.error(LoggerUtility.Exception, INVALID_QUERY_PARAMETER_VALUE_ID , id);
            return CORSHeaderSupport.addCORSHeader(Response.Status.BAD_REQUEST,Response.Status.BAD_REQUEST.toString());
        }
        try {
            SimpleMapRefsetResult simplemap = agent.searchSimpleMap(id);
            if (simplemap != null)
                jsonString = gson.toJson(simplemap);
            else
                jsonString = gson.toJson(Collections.emptyList());
        } catch (Exception e) { // caches any of the service exceptions
            // Log the Exception
            logger.error(LoggerUtility.Exception, LoggerUtility.createErrorMessage(e));
            return CORSHeaderSupport.addCORSHeader(Response.Status.INTERNAL_SERVER_ERROR,
                    Response.Status.INTERNAL_SERVER_ERROR.toString() + " : " + LoggerUtility.createErrorMessage(e));
        }
        // if callback in URL and is not just the "?" (e.g. from localhost)
        if (callback != null && callback.length() > 1) {
            return CORSHeaderSupport.addCORSHeader(Response.Status.OK,callback + "(" + jsonString + ");");
        } else {
            return CORSHeaderSupport.addCORSHeader(Response.Status.OK,jsonString);
        }

    }



}