package com.example.demo.service.impl;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.common.APIResponse;
import com.example.demo.dto.EndPointUpdateDTO;
import com.example.demo.dto.EndpointCreateDTO;
import com.example.demo.dto.EndpointDeleteDTO;
import com.example.demo.dto.EndpointResponseDTO;
import com.example.demo.entity.Configurations;
import com.example.demo.entity.Dsp;
import com.example.demo.entity.EndPoint;
import com.example.demo.redisentity.EndPointRedis;
import com.example.demo.repository.ConfigurationRepo;
import com.example.demo.repository.DspRepository;
import com.example.demo.repository.EndpointRepository;
import com.example.demo.service.EndPointService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import redis.clients.jedis.Jedis;

@Service
public class EndPointServiceImpl implements EndPointService {

	@Autowired
	private EndpointRepository repo;

	@Autowired
	private ConfigurationRepo configrepo;

	@Autowired
	private DspRepository dsprepo;

	@Autowired
	private Jedis jedis;

	@Override
	public APIResponse createEndpoint(EndpointCreateDTO create) throws JsonProcessingException {
		APIResponse api = new APIResponse();

		EndPoint end = new EndPoint();
		end.setDemand_partner(create.getDemand_partner());
		end.setBid_floor(create.getBidfloor());
		end.setEndpoint_name(create.getEndpoint_name());
		end.setSeller_id(create.getSeller_id());
		end.setAdtype(create.getAdtype());
		
		ObjectMapper mapper = new ObjectMapper();
		String srcstring = mapper.writeValueAsString(create.getDsp_params());
        end.setDsp_params(srcstring);
        
		end.setCreated_at(LocalDateTime.now());
		end.setUpdated_at(LocalDateTime.now());
		end.setCreated_by(create.getCreated_by());
		repo.save(end);

		EndPointRedis endpointredis = new EndPointRedis();

		endpointredis.setEndpoint_id(end.getEndpoint_id());
		UUID id = endpointredis.getEndpoint_id();
		String id_str = id.toString();

		endpointredis.setEndpoint_name(end.getEndpoint_name());
		String name_str = endpointredis.getEndpoint_name();

		endpointredis.setDemand_partner(end.getDemand_partner());
		UUID demand_partner = endpointredis.getDemand_partner();
		String demand_partner_str = demand_partner.toString();

		endpointredis.setBid_floor(end.getBid_floor());
		double bid_floor = endpointredis.getBid_floor();
		String bid_floor_str = Double.toString(bid_floor);

		String seller_id_str = null;
		if (end.getSeller_id() != null) {
			endpointredis.setSeller_id(end.getSeller_id());
			seller_id_str = endpointredis.getSeller_id();
		}

		String adtype_str =null;
		if(end.getAdtype()!=0) {
		endpointredis.setAdtype(end.getAdtype());
		adtype_str = Integer.toString(endpointredis.getAdtype());
		}
		
		String dsp_params_str =null;
		if(end.getDsp_params()!=null) {
		endpointredis.setDsp_params(end.getDsp_params());
		dsp_params_str = endpointredis.getDsp_params();
		}
		endpointredis.setCreated_at(end.getCreated_at());
		LocalDateTime created_at = endpointredis.getCreated_at();

		String[] arr = new String[2];

		arr[0] = created_at.toString();

		arr[1] = created_at.format(DateTimeFormatter.ofPattern("hh:mm:ss a", Locale.ENGLISH));
		String created_at_str = Arrays.toString(arr);

		endpointredis.setCreated_by(end.getCreated_by());
		UUID created_by = endpointredis.getCreated_by();
		String created_by_str = created_by.toString();

		endpointredis.setUpdated_at(end.getUpdated_at());
		LocalDateTime updated_at = endpointredis.getUpdated_at();

		String[] arr1 = new String[2];

		arr1[0] = updated_at.toString();

		arr1[1] = updated_at.format(DateTimeFormatter.ofPattern("hh:mm:ss a", Locale.ENGLISH));
		String updated_at_str = Arrays.toString(arr);

		String Key = "Endpoint_" + end.getEndpoint_id();
		Map<String, String> map = new HashMap<>();
		map.put("endpoint_id", id_str);
		map.put("endpoint_name", name_str);
		map.put("demand_partner", demand_partner_str);
		if(adtype_str!=null) {
		map.put("adtype",adtype_str);
		}
		if(dsp_params_str!=null) {
		map.put("dsp_params",dsp_params_str);
		}
		map.put("bid_floor", bid_floor_str);
		map.put("seller_id", seller_id_str);
		map.put("created_at", created_at_str);
		map.put("created_by", created_by_str);
		map.put("updated_at", updated_at_str);
		jedis.hmset(Key, map);

		api.setData(end);
		api.setMessage("EndPoint Created Successfully");
		api.setMsgCode("ENDPOINT CREATED SUCCESSFULLY");
		return api;
	}

	@Override
	public APIResponse updateEndpoint(EndPointUpdateDTO update, UUID endpoint_id) throws JsonProcessingException {
		APIResponse api = new APIResponse();

		EndPoint end = repo.findById(endpoint_id).orElse(null);
		end.setDemand_partner(update.getDemand_partner());
		end.setEndpoint_name(update.getEndpoint_name());
		end.setBid_floor(update.getBidfloor());
		end.setAdtype(update.getAdtype());
		
		ObjectMapper mapper = new ObjectMapper();
		String srcstring = mapper.writeValueAsString(update.getDsp_params());
        end.setDsp_params(srcstring);

		end.setSeller_id(update.getSeller_id());
		end.setUpdated_at(LocalDateTime.now());
		end.setUpdated_by(update.getUpdated_by());
		repo.save(end);

		EndPointRedis endpointredis = new EndPointRedis();

		endpointredis.setEndpoint_id(end.getEndpoint_id());
		UUID id = endpointredis.getEndpoint_id();
		String id_str = id.toString();

		endpointredis.setEndpoint_name(end.getEndpoint_name());
		String name_str = endpointredis.getEndpoint_name();

		endpointredis.setDemand_partner(end.getDemand_partner());
		UUID demand_partner = endpointredis.getDemand_partner();
		String demand_partner_str = demand_partner.toString();

		String adtype_str=null;
		if(end.getAdtype()!=0) {
		endpointredis.setAdtype(end.getAdtype());
		adtype_str = Integer.toString(endpointredis.getAdtype());
		}

		String dsp_params_str=null;
		if(end.getDsp_params()!=null) {
		endpointredis.setDsp_params(end.getDsp_params());
		dsp_params_str = endpointredis.getDsp_params();
		}
		
		endpointredis.setBid_floor(end.getBid_floor());
		double bid_floor = endpointredis.getBid_floor();
		String bid_floor_str = Double.toString(bid_floor);

		String seller_id_str = null;
		if (end.getSeller_id() != null) {
			endpointredis.setSeller_id(end.getSeller_id());
			seller_id_str = endpointredis.getSeller_id();
		}

		endpointredis.setCreated_at(end.getCreated_at());
		LocalDateTime created_at = endpointredis.getCreated_at();

		String[] arr = new String[2];

		arr[0] = created_at.toString();

		arr[1] = created_at.format(DateTimeFormatter.ofPattern("hh:mm:ss a", Locale.ENGLISH));
		String created_at_str = Arrays.toString(arr);

		endpointredis.setCreated_by(end.getCreated_by());
		UUID created_by = endpointredis.getCreated_by();
		String created_by_str = created_by.toString();

		endpointredis.setUpdated_at(end.getUpdated_at());
		LocalDateTime updated_at = endpointredis.getUpdated_at();

		String[] arr1 = new String[2];

		arr1[0] = updated_at.toString();

		arr1[1] = updated_at.format(DateTimeFormatter.ofPattern("hh:mm:ss a", Locale.ENGLISH));
		String updated_at_str = Arrays.toString(arr);

		endpointredis.setUpdated_by(end.getUpdated_by());
		UUID updated_by = endpointredis.getUpdated_by();
		String updated_by_str = updated_by.toString();

		String Key = "Endpoint_" + end.getEndpoint_id();
		Map<String, String> map = new HashMap<>();
		map.put("endpoint_id", id_str);
		map.put("endpoint_name", name_str);
		map.put("demand_partner", demand_partner_str);
		if(adtype_str!=null) {
			map.put("adtype", adtype_str);
		}
		if(dsp_params_str!=null) {
			map.put("dsp_params",dsp_params_str);
		}
		map.put("bid_floor", bid_floor_str);
		map.put("seller_id", seller_id_str);
		map.put("created_at", created_at_str);
		map.put("created_by", created_by_str);
		map.put("updated_at", updated_at_str);
		map.put("updated_by", updated_by_str);
		jedis.hmset(Key, map);

		api.setData(end);
		api.setMessage("EndPoint Updated Successfully");
		api.setMsgCode("ENDPOINT UPDATED SUCCESSFULLY");
		return api;
	}

	@Override
	public APIResponse getbyid(UUID endpoint_id) {
		APIResponse api = new APIResponse();
		EndPoint end = repo.findById(endpoint_id).orElse(null);
		EndpointResponseDTO response = MapToDTO(end);
		api.setData(response);
		api.setMessage("EndPoint Details Get Successfully");
		api.setMsgCode("ENDPOINT DETAILS GET SUCCESSFULLY");
		return api;
	}

	@Override
	public APIResponse getall() {
		APIResponse api = new APIResponse();
		List<EndPoint> endpoint = repo.findAll();
		List<EndpointResponseDTO> response = endpoint.stream().map(end -> MapToDTO(end)).collect(Collectors.toList());
		api.setData(response);
		api.setMessage("EndPoint List Get Successfully");
		api.setMsgCode("ENDPOINT LIST GET SUCCESSFULLY");
		return api;
	}

	@Override
	public APIResponse deletedEndpoint(EndpointDeleteDTO delete) {
		APIResponse api = new APIResponse();

		EndPoint end = repo.findById(delete.getEndpoint_id()).orElse(null);
		end.setIs_deleted(1);
		end.setDeleted_at(LocalDateTime.now());
		end.setDeleted_by(delete.getDeleted_by());
		repo.save(end);

		EndPointRedis endpointredis = new EndPointRedis();

		endpointredis.setIs_deleted(end.getIs_deleted());
		int is_deleted = endpointredis.getIs_deleted();
		String is_deleted_str = Integer.toString(is_deleted);

		endpointredis.setDeleted_at(end.getDeleted_at());
		LocalDateTime deleted_at = endpointredis.getDeleted_at();

		String[] arr1 = new String[2];

		arr1[0] = deleted_at.toString();

		arr1[1] = deleted_at.format(DateTimeFormatter.ofPattern("hh:mm:ss a", Locale.ENGLISH));
		String deleted_at_str = Arrays.toString(arr1);

		endpointredis.setDeleted_by(end.getDeleted_by());
		UUID deleted_by = endpointredis.getDeleted_by();
		String deleted_by_str = deleted_by.toString();

		String key = "Endpoint_" + end.getEndpoint_id();
		Map<String, String> map = new HashMap<>();
		map.put("is_deleted", is_deleted_str);
		map.put("deleted_at", deleted_at_str);
		map.put("deleted_by", deleted_by_str);
		jedis.hmset(key, map);

		api.setMessage("EndPoint deleted Successfully");
		api.setMsgCode("ENDPOINT DELETED SUCCESSFULLY");
		return api;
	}

	private EndpointResponseDTO MapToDTO(EndPoint endpoint) {
		EndpointResponseDTO response = new EndpointResponseDTO();
		if(endpoint.getDemand_partner()!=null) {
		Dsp dsp = dsprepo.findById(endpoint.getDemand_partner()).orElse(null);
		response.setDemand_partner_name(dsp.getAdExchange_name());
		}
		response.setEndpoint_id(endpoint.getEndpoint_id());
		response.setDemand_partner(endpoint.getDemand_partner());
		response.setEndpoint_name(endpoint.getEndpoint_name());
		response.setBidfloor(endpoint.getBid_floor());
		response.setAdtype(endpoint.getAdtype());
		if(endpoint.getAdtype()==1) {
			response.setAdtype_name("Image");
		}
		if(endpoint.getAdtype()==2) {
			response.setAdtype_name("Video");
		}
		if(endpoint.getAdtype()==3) {
			response.setAdtype_name("Audio");
		}
		if(endpoint.getAdtype()==4) {
			response.setAdtype_name("Native");
		}
		response.setDsp_params(endpoint.getDsp_params());
		response.setSeller_id(endpoint.getSeller_id());
		response.setCreated_by(endpoint.getCreated_by());
		response.setUpdated_by(endpoint.getUpdated_by());
		response.setIs_deleted(endpoint.getIs_deleted());
		response.setDeleted_by(endpoint.getDeleted_by());

		List<Configurations> allconfig = configrepo.findAll();
		Configurations obj = allconfig.get(0);
		DateTimeFormatter newYorkDateFormatter = DateTimeFormatter.ofPattern(obj.getConfigValue());
		String arr1 = newYorkDateFormatter.format(ZonedDateTime.of(endpoint.getCreated_at(), ZoneId.of("UTC-4")));
		response.setCreated_at(arr1);

		String arr2 = newYorkDateFormatter.format(ZonedDateTime.of(endpoint.getUpdated_at(), ZoneId.of("UTC-4")));
		response.setUpdated_at(arr2);

		if (endpoint.getDeleted_at() != null) {
			String arr3 = newYorkDateFormatter.format(ZonedDateTime.of(endpoint.getDeleted_at(), ZoneId.of("UTC-4")));
			response.setDeleted_at(arr3);
		}
        response.setIs_deleted(endpoint.getIs_deleted());
        response.setDeleted_by(endpoint.getDeleted_by());
		return response;
	}
}
