package com.example.demo.service.impl;

import java.time.LocalDateTime;
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.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import com.example.demo.common.APIResponse;
import com.example.demo.common.ErrorObj;
import com.example.demo.dto.AccessRequestCreateDTO;
import com.example.demo.dto.AccessRequestResponseDTO;
import com.example.demo.dto.AccessRequestUpdateDTO;
import com.example.demo.dto.RequestApproveDTO;
import com.example.demo.entity.AccessRequest;
import com.example.demo.entity.Advertriser;
import com.example.demo.entity.EmailDetails;
import com.example.demo.entity.ManageUser;
import com.example.demo.entity.Publisher;
import com.example.demo.entity.Roles;
import com.example.demo.redisentity.AdvertiserRedis;
import com.example.demo.redisentity.PublisherRedis;
import com.example.demo.repository.AccessRequestRepository;
import com.example.demo.repository.AdvertriserRepo;
import com.example.demo.repository.ManageUserRepository;
import com.example.demo.repository.PublisherRepo;
import com.example.demo.repository.RolesRepository;
import com.example.demo.service.AccessRequestService;

import redis.clients.jedis.Jedis;

@Service
public class AccessRequestServiceImpl implements AccessRequestService {

	@Autowired
	private AccessRequestRepository repo;

	@Autowired
	private PublisherRepo publisherrepo;

	@Autowired
	private ManageUserRepository userrepo;

	@Autowired
	private AdvertriserRepo advertiserrepo;

	@Autowired
	private RolesRepository rolesrepo;

//	@Autowired
//	private EmailServiceImpl emailService;

	@Autowired
	PasswordEncoder passencoder;

	@Autowired
	private Jedis jedis;

	@Override
	public APIResponse create(AccessRequestCreateDTO create) {
		APIResponse api = new APIResponse();

		AccessRequest request = new AccessRequest();

		request.setName(create.getName());
		request.setEmail(create.getEmail());
		request.setWebsite(create.getWebsite());
		request.setRole_type(create.getAccount_type());
		request.setPwd_hash(passencoder.encode(create.getPassword()));
		request.setPostcurrrency(create.getPostcurrency());
		request.setStatus(0);
		repo.save(request);

		api.setData(request);
		api.setMessage("Acccess Request Created Successfully");
		api.setMsgCode("ACCESS REQUEST CREATED SUCCESSFULLY");
		return api;
	}

	@Override
	public APIResponse update(AccessRequestUpdateDTO update, UUID access_id) {
		APIResponse api = new APIResponse();

		AccessRequest request = repo.findById(access_id).orElse(null);
		request.setName(update.getName());
		request.setEmail(update.getEmail());
		request.setWebsite(update.getWebsite());
		request.setRole_type(update.getAccount_type());
		request.setPostcurrrency(update.getPostcurrency());
		request.setPwd_hash(passencoder.encode(update.getPassword()));
		request.setStatus(0);
		repo.save(request);

		api.setData(update);
		api.setMessage("Access Request Updated Successfully");
		api.setMsgCode("ACCESS REQUEST UPDATED SUCCESSFULLY");
		return api;
	}

	@Override
	public APIResponse approve(RequestApproveDTO approve, UUID user_id) {
		APIResponse api = new APIResponse();

		AccessRequest request = repo.findById(approve.getId()).orElse(null);
		Roles role = rolesrepo.findByRoleid(request.getRole_type());
		if (role.getRolename().equals("Publisher")) {
			ManageUser email = userrepo.findbyemail(request.getEmail());
			Publisher publish = publisherrepo.findbyemail(request.getEmail());

			if (email != null || publish != null) {
				ErrorObj error = new ErrorObj();
				error.setCode("Email already exists");
				api.setError(error);
				api.setMessage("Email Alerady Exists");
				api.setMsgCode("EMAIL ALREADY EXISTS");
				return api;
			}

			Publisher pub = new Publisher();
			pub.setName(request.getName());
			pub.setStatus(1);
			pub.setEmail(request.getEmail());
			pub.setWebsite(request.getWebsite());
			pub.setCreated_at(LocalDateTime.now());
			pub.setCreated_by(user_id);
			pub.setUpdated_at(LocalDateTime.now());
			publisherrepo.save(pub);

			ManageUser user = new ManageUser();
			user.setId(pub.getId());
			user.setRoleid(request.getRole_type());
			user.setName(pub.getName());
			user.setPassword(request.getPwd_hash());
			user.setEmail(request.getEmail());
			user.setStatus(1);
			user.setCreated_at(LocalDateTime.now());
			user.setCreated_by(user_id);
			user.setUpdated_at(LocalDateTime.now());
			userrepo.save(user);

			request.setStatus(1);
			repo.save(request);

			PublisherRedis pubredis = new PublisherRedis();

			pubredis.setId(pub.getId());
			UUID id = pubredis.getId();
			String id_str = id.toString();

			pubredis.setName(pub.getName());
			String name_str = pubredis.getName();

			pubredis.setEmail(pub.getEmail());
			String email_str = pubredis.getEmail();

			pubredis.setWebsite(pub.getWebsite());
			String website_str = pubredis.getWebsite();

			pubredis.setStatus(pub.getStatus());
			int status = pubredis.getStatus();
			String status_str = Integer.toString(status);

			pubredis.setCreated_at(pub.getCreated_at());
			LocalDateTime created_at = pubredis.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);

			pubredis.setCreated_by(pub.getCreated_by());
			UUID created_by = pubredis.getCreated_by();
			String created_by_str = created_by.toString();

			pubredis.setUpdated_at(pub.getUpdated_at());
			LocalDateTime updated_at = pubredis.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 = "Publisher_" + pub.getId();
			Map<String, String> map = new HashMap<>();
			map.put("publisher_id", id_str);
			map.put("name", name_str);
			map.put("email", email_str);
			map.put("website", website_str);
			map.put("status", status_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);

		} else if (role.getRolename().equals("Advertiser")) {
			ManageUser email = userrepo.findbyemail(request.getEmail());
			Advertriser add = advertiserrepo.findbyemail(request.getEmail());

			if (add != null || email != null) {
				ErrorObj error = new ErrorObj();
				error.setCode("Email already exists");
				api.setError(error);
				api.setMessage("Email Already Exists");
				api.setMsgCode("EMAIL ALREADY EXISTS");
				return api;
			}

			Advertriser add2 = new Advertriser();
			add2.setAdvertiser_name(request.getName());
			add2.setEmail(request.getEmail());
			add2.setStatus(1);
			add2.setCreated_at(LocalDateTime.now());
			add2.setCreated_by(user_id);
			add2.setUpdated_at(LocalDateTime.now());
			advertiserrepo.save(add2);

			ManageUser user = new ManageUser();
			user.setId(add2.getAdvertiser_id());
			user.setName(add2.getAdvertiser_name());
			user.setCreated_at(LocalDateTime.now());
			user.setRoleid(request.getRole_type());
			user.setCreated_by(user_id);
			user.setUpdated_at(LocalDateTime.now());
			user.setStatus(1);
			user.setEmail(request.getEmail());
			user.setPassword(request.getPwd_hash());
			userrepo.save(user);

			request.setStatus(1);
			repo.save(request);

			AdvertiserRedis addredis = new AdvertiserRedis();

			addredis.setAdvertiser_id(add.getAdvertiser_id());
			UUID id = addredis.getAdvertiser_id();
			String id_str = id.toString();

			addredis.setAdvertiser_name(add.getAdvertiser_name());
			String name_str = addredis.getAdvertiser_name();

			addredis.setEmail(add.getEmail());
			String email_str = addredis.getEmail();

			addredis.setStatus(add.getStatus());
			int status = addredis.getStatus();
			String status_str = Integer.toString(status);

			addredis.setCreated_at(add.getCreated_at());
			LocalDateTime created_at = addredis.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);

			addredis.setCreated_by(add.getCreated_by());
			UUID created_by = addredis.getCreated_by();
			String created_by_str = created_by.toString();

			addredis.setUpdated_at(add.getUpdated_at());
			LocalDateTime updated_at = addredis.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 update_at_str = Arrays.toString(arr);

			String key = "Advertiser_" + add.getAdvertiser_id();
			Map<String, String> map = new HashMap<>();
			map.put("advertiser_id", id_str);
			map.put("name", name_str);
			map.put("email", email_str);
			map.put("status", status_str);
			map.put("created_at", created_at_str);
			map.put("created_by", created_by_str);
			map.put("updated_at", update_at_str);
			jedis.hmset(key, map);

		}

		EmailDetails email = new EmailDetails();

		email.setRecipient(request.getEmail());
		email.setSubject("Request Approved Mail");
		email.setMsgBody(
				"<div style=color:black>Hi " + request.getName() + "<br>" + "<br>" + "Your" + request.getRole_type()
						+ "access request has been approved<br>" + "Admin access details will be shared soon<br>"
						+ "<br>" + "<br>" + "<br>" + "Regards,<br>" + "AdServer</div>");

//		emailService.sendSimpleMail(email);

		api.setMessage("RequestApproved Successfully");
		api.setMsgCode("REQUEST APPROVED SUCCESSFULLY");
		return api;
	}

	@Override
	public APIResponse reject(RequestApproveDTO approve) {
		APIResponse api = new APIResponse();

		AccessRequest request = repo.findById(approve.getId()).orElse(null);
		request.setStatus(2);
		repo.save(request);

		EmailDetails email = new EmailDetails();

		email.setRecipient(request.getEmail());
		email.setSubject("Request Rejected");
		email.setMsgBody("<div style=color:black>Hi " + request.getName() + "<br>" + "<br>" + "Your "
				+ request.getRole_type() + " access request has been rejected<br>" + "<br>" + "<br>" + "<br>"
				+ "Regards,<br>" + "AdMaru</div>");

//		emailService.sendSimpleMail(email);

		api.setMessage("Access Request Successfully");
		api.setMsgCode("ACCESS REQUEST SUCCESSFULLY");
		return api;
	}

	@Override
	public APIResponse getall() {
		APIResponse api = new APIResponse();
		List<AccessRequest> request = repo.findAll();

		List<AccessRequestResponseDTO> response = request.stream().map(use -> MapToDto(use))
				.collect(Collectors.toList());

		api.setData(response);
		api.setMessage("List Of Access Request");
		api.setMsgCode("LIST OF ACCESS REQUEST");
		return api;
	}

	private AccessRequestResponseDTO MapToDto(AccessRequest access) {
		AccessRequestResponseDTO response = new AccessRequestResponseDTO();
		response.setRequest_id(access.getRequest_id());
		response.setName(access.getName());
		response.setEmail(access.getEmail());
		response.setPostcurrency(access.getPostcurrrency());
		response.setWebsite(access.getWebsite());
		Roles role = rolesrepo.findByRoleid(access.getRole_type());
		response.setRole_type(role.getRolename());
		if (access.getStatus() == 0) {
			response.setStatus("Waiting");
		} else if (access.getStatus() == 1) {
			response.setStatus("Approved");
		} else if (access.getStatus() == 2) {
			response.setStatus("Rejected");
		}
		return response;
	}

}
