package com.jasamedika.medifirst2000.controller;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.jasamedika.medifirst2000.constants.Constants;
import com.jasamedika.medifirst2000.logging.hibernate.async.LoggingSystemAsynchronous;
import com.jasamedika.medifirst2000.notification.MessagePublisher;
import com.jasamedika.medifirst2000.security.model.UserAuthentication;
import com.jasamedika.medifirst2000.security.service.TokenAuthenticationService;
import com.jasamedika.medifirst2000.service.ActivityPegawaiService;
import com.jasamedika.medifirst2000.service.AgamaService;
import com.jasamedika.medifirst2000.service.JadwalDokterService;
import com.jasamedika.medifirst2000.service.LoginUserService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.util.DateUtil;
import com.jasamedika.medifirst2000.util.JsonUtil;
import com.jasamedika.medifirst2000.util.rest.RestUtil;
import com.jasamedika.medifirst2000.vo.AgamaVO;
import com.jasamedika.medifirst2000.vo.LoginUserVO;
import com.jasamedika.medifirst2000.vo.custom.AuthVO;

/**
 * Controller class for Authenticate Business
 * 
 * @author Roberto
 */
@RestController
@RequestMapping("/auth")
public class AuthenticateController {

	@Autowired
	private LoginUserService loginUserService;
	
	protected Map<String, String> mapHeaderMessage = new HashMap<String, String>();

	@Autowired
	public AgamaService<AgamaVO> agamaService;

	@Autowired
	private ActivityPegawaiService activityPegawaiServiceImpl;
	
	@Autowired
	public JadwalDokterService jadwalDokterService;
	
	@Autowired
	MessagePublisher<String, Object> messagePublisher;
	
//	@Autowired
//	private DataSource dataSource;
	
	@Autowired
	private TokenAuthenticationService tokenAuthenticationService;
	
//	@Autowired
//	private ObjekModulAplikasiSService objekModulAplikasiSService;
	
	//Alter Syamsu
	@Autowired
	LoggingSystemAsynchronous loggingSystemAsynchronous;

	private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticateController.class);
	
	
	
	@RequestMapping(value = "/history", method = RequestMethod.GET)
	@ResponseBody
	public ResponseEntity<Object> GetHistory(@RequestParam(value = "dateStart", required = false) String dateStart,
			@RequestParam(value = "dateEnd", required = false) String dateEnd,
			@RequestParam(value = "top", required = false,defaultValue="0") Integer top, HttpServletRequest request, 
			 HttpServletResponse httpResponse) {
		if(top ==0)
			top =Integer.MAX_VALUE;
		Date start = DateUtil.toDate(dateStart);
		Date until = DateUtil.toDate(dateEnd);
		Object data =null;
		try {
			data = JsonUtil.ToMaps( activityPegawaiServiceImpl.getData(start, until,top));
		} catch (IllegalArgumentException | IllegalAccessException e) {
			e.printStackTrace();
		}
		
		
		return RestUtil.getJsonResponse(data, HttpStatus.OK, mapHeaderMessage);
	}

	// Alter Syamsu
	@RequestMapping(value = "/sign-in", method = RequestMethod.POST)
	@ResponseBody
	public ResponseEntity<LoginUserVO> signIn(@RequestBody AuthVO vo, HttpServletRequest request, HttpServletResponse httpResponse) {
				

		if (vo.getNamaUser() == null || vo.getKataSandi() == null) {
			this.mapHeaderMessage.put(Constants.MessageInfo.ERROR_MESSAGE, "Username or Password is empty");
			return RestUtil.getJsonHttptatus(HttpStatus.BAD_REQUEST, mapHeaderMessage);
		}

		LOGGER.info("starting logging {}", vo.getNamaUser() + " at " + DateUtil.getIndonesianStringDate(new Date()));

		try {
			mapHeaderMessage = new HashMap<String, String>();
			LoginUserVO loginUserVo = loginUserService.signIn(vo);
			if (loginUserVo == null) {
				this.mapHeaderMessage.put(Constants.MessageInfo.ERROR_MESSAGE, "Invalid Username or Password");
				return RestUtil.getJsonHttptatus(HttpStatus.NOT_ACCEPTABLE, mapHeaderMessage);
			}
			// GrantedAuthority authority = new
			// SimpleGrantedAuthority(loginUserVo
			// .getKelompokUser().getKelompokUser());
			
			GrantedAuthority authority = new SimpleGrantedAuthority("USER");
			
			String token = tokenAuthenticationService.addAuthentication(httpResponse, new UserAuthentication(
					new User(loginUserVo.getNamaUser(), loginUserVo.getKataSandi(), Arrays.asList(authority))));
						
			Boolean isSupervising = request.getHeader(Constants.HttpHeader.SUPERVISING) == null ? false : true;
			
			if (isSupervising) { // supervising login
				mapHeaderMessage.put("X-AUTH-SUPERVISOR-TOKEN", token);
				activityPegawaiServiceImpl.record(loginUserVo.getPegawai(), new Date(), "Supervising Login");
				return RestUtil.getJsonResponse(loginUserVo, HttpStatus.OK, mapHeaderMessage);
			} else { // normal login
				
				Map<String,Object> data = new HashMap<>();
				
				if (loginUserVo.getPegawai().getJenisPegawai() != null && loginUserVo.getPegawai().getJenisPegawai().getId() == Integer.parseInt(GetSettingDataFixed("KdJenisPegawaiDokter"))) {
					Boolean result = jadwalDokterService.CheckJadwalDokter(new Date(), loginUserVo.getPegawai());
					//if (!result) {
					//	mapHeaderMessage.put("message", "Tidak memiliki Jadwal hari ini");
					//} else {
						mapHeaderMessage.put("X-AUTH-TOKEN", token);
						activityPegawaiServiceImpl.record(loginUserVo.getPegawai(), new Date(), "Behasil Login Ke System");
						messagePublisher.sendDirectNotification(data);
						//BroadcastMessage("IKI", "");
					//}
				} else {
					
					mapHeaderMessage.put("X-AUTH-TOKEN", token);
					activityPegawaiServiceImpl.record(loginUserVo.getPegawai(), new Date(), "Behasil Login Ke System");
					messagePublisher.sendDirectNotification(data);
					//BroadcastMessage("IKI", "");
				}
				
				Integer idPegawai = 0;
				if (CommonUtil.isNotNullOrEmpty(loginUserVo.getPegawai())){
					idPegawai = loginUserVo.getPegawai().getId();
				}
				
				loggingSystemAsynchronous.saveSignInLog(0, 0, loginUserVo.getNamaUser(), idPegawai);
				
				return RestUtil.getJsonResponse(loginUserVo, HttpStatus.OK, mapHeaderMessage);
			}

		} catch (Exception ex) {
			ex.printStackTrace();
			LOGGER.error("Signing-in error {}", ex.getMessage());
			return RestUtil.getJsonHttptatus(HttpStatus.UNAUTHORIZED);
		}
	}

	public String GetSettingDataFixed(String prefix) {
		return activityPegawaiServiceImpl.GetSettingDataFixed(prefix);
	}
	
//	private void BroadcastMessage(final String to, final String data) {
//		final Socket socket;
//		try {
//			socket = IO.socket(GetSettingDataFixed("UrlSocketMessaging"));
//
//			socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
//				@Override
//				public void call(Object... args) {
//					try {
//						JSONObject item=	new JSONObject("{\"to\":\""+to+"\",\"message\":\""+data+"\"}");
//						socket.emit("subscribe", item);
//					} catch (JSONException e) {
//						LOGGER.info(e.getMessage());
//					}
//				}
//
//			});
//			socket.connect();
//		} catch (URISyntaxException e) {
//			e.printStackTrace();
//		}
//		
//	}

	@RequestMapping(value = "/sign-out", method = RequestMethod.POST)
	@ResponseBody
	public ResponseEntity<AuthVO> signOut(@RequestBody AuthVO vo, HttpServletResponse httpResponse) {
		
		LoginUserVO loginUserVO = loginUserService.findById(vo.getId());

		LOGGER.info("starting logout {}", loginUserVO.getNamaUser() + " at " + DateUtil.getIndonesianStringDate(new Date()));
		
		Integer idPegawai = 0;
		if (CommonUtil.isNotNullOrEmpty(loginUserVO.getPegawai())){
			idPegawai = loginUserVO.getPegawai().getId();
		}
		
		loggingSystemAsynchronous.saveSignOutLog(loginUserVO.getNamaUser(), idPegawai);
//		GrantedAuthority authority = new SimpleGrantedAuthority("USER");
//		String token = tokenAuthenticationService.addAuthentication(httpResponse, new UserAuthentication(
//				new User(loginUserVO.getNamaUser(), loginUserVO.getKataSandi(), Arrays.asList(authority))));
//		mapHeaderMessage.put("X-AUTH-SUPERVISOR-TOKEN", token);
		
		return RestUtil.getJsonResponse(vo, HttpStatus.OK);
		

		// misal call service logout dan seterusnya
		// Karena Stateless tidak perlu set " session user " menjadi tidak
		// aktif, return HttpStatus.OK ke client
		//RestUtil.getJsonHttptatus(HttpStatus.OK);
	}
	
	@RequestMapping(value = "/sign-in-mobile", method = RequestMethod.POST)
	@ResponseBody
	public ResponseEntity<Map<String,Object>> signInMobile(@RequestBody AuthVO vo, HttpServletRequest request, HttpServletResponse httpResponse) {
				

		if (vo.getNamaUser() == null || vo.getKataSandi() == null) {
			this.mapHeaderMessage.put(Constants.MessageInfo.ERROR_MESSAGE, "Username or Password is empty");
			return RestUtil.getJsonHttptatus(HttpStatus.BAD_REQUEST, mapHeaderMessage);
		}

		LOGGER.info("starting logging {}", vo.getNamaUser() + " at " + DateUtil.getIndonesianStringDate(new Date()));

		try {
			mapHeaderMessage = new HashMap<String, String>();
			LoginUserVO loginUserVo = loginUserService.signIn(vo);
			if (loginUserVo == null) {
				this.mapHeaderMessage.put(Constants.MessageInfo.ERROR_MESSAGE, "Invalid Username or Password");
				return RestUtil.getJsonHttptatus(HttpStatus.NOT_ACCEPTABLE, mapHeaderMessage);
			}
			// GrantedAuthority authority = new
			// SimpleGrantedAuthority(loginUserVo
			// .getKelompokUser().getKelompokUser());
			
			GrantedAuthority authority = new SimpleGrantedAuthority("USER");
			
			String token = tokenAuthenticationService.addAuthentication(httpResponse, new UserAuthentication(
					new User(loginUserVo.getNamaUser(), loginUserVo.getKataSandi(), Arrays.asList(authority))));
						
			Boolean isSupervising = request.getHeader(Constants.HttpHeader.SUPERVISING) == null ? false : true;
			
			if (isSupervising) { // supervising login
				mapHeaderMessage.put("X-AUTH-SUPERVISOR-TOKEN", token);
				activityPegawaiServiceImpl.record(loginUserVo.getPegawai(), new Date(), "Supervising Login");
				Map<String,Object> result= new HashMap<>();
				 result.put("token", token);
				 result.put("id", loginUserVo.getId());
				 result.put("idPegawai", loginUserVo.getPegawai().getId());
				 result.put("name", loginUserVo.getPegawai().getNamaLengkap());
				return RestUtil.getJsonResponse(result, HttpStatus.OK, mapHeaderMessage);
			} else { // normal login
				
				Map<String,Object> data = new HashMap<>();
				
				if (loginUserVo.getPegawai().getJenisPegawai() != null && loginUserVo.getPegawai().getJenisPegawai().getId() == Integer.parseInt(GetSettingDataFixed("KdJenisPegawaiDokter"))) {
					Boolean result = jadwalDokterService.CheckJadwalDokter(new Date(), loginUserVo.getPegawai());
				//	if (!result) {
					//	mapHeaderMessage.put("message", "Tidak memiliki Jadwal hari ini");
				//	} else {
						mapHeaderMessage.put("X-AUTH-TOKEN", token);
						activityPegawaiServiceImpl.record(loginUserVo.getPegawai(), new Date(), "Behasil Login Ke System");
						messagePublisher.sendDirectNotification(data);
						//BroadcastMessage("IKI", "");
				//	}
				} else {
					
					mapHeaderMessage.put("X-AUTH-TOKEN", token);
					activityPegawaiServiceImpl.record(loginUserVo.getPegawai(), new Date(), "Behasil Login Ke System");
					messagePublisher.sendDirectNotification(data);
					//BroadcastMessage("IKI", "");
				}
				
				Integer idPegawai = 0;
				if (CommonUtil.isNotNullOrEmpty(loginUserVo.getPegawai())){
					idPegawai = loginUserVo.getPegawai().getId();
				}
				
				loggingSystemAsynchronous.saveSignInLog(0, 0, loginUserVo.getNamaUser(), idPegawai);
				Map<String,Object> result= new HashMap<>();
				 result.put("token", token);
				 result.put("id", loginUserVo.getId());
				 result.put("idPegawai", loginUserVo.getPegawai().getId());
				 result.put("name", loginUserVo.getPegawai().getNamaLengkap());
				return RestUtil.getJsonResponse(result, HttpStatus.OK, mapHeaderMessage);
			}

		} catch (Exception ex) {
			ex.printStackTrace();
			LOGGER.error("Signing-in error {}", ex.getMessage());
			return RestUtil.getJsonHttptatus(HttpStatus.UNAUTHORIZED);
		}
	}
	@RequestMapping(value = "/sign-out-mobile", method = RequestMethod.POST)
	@ResponseBody
	public ResponseEntity<AuthVO> signOutMobile(@RequestBody AuthVO vo, HttpServletResponse httpResponse) {
		
		LoginUserVO loginUserVO = loginUserService.findById(vo.getId());

		LOGGER.info("starting logout {}", loginUserVO.getNamaUser() + " at " + DateUtil.getIndonesianStringDate(new Date()));
		
		Integer idPegawai = 0;
		if (CommonUtil.isNotNullOrEmpty(loginUserVO.getPegawai())){
			idPegawai = loginUserVO.getPegawai().getId();
		}
		
		loggingSystemAsynchronous.saveSignOutLog(loginUserVO.getNamaUser(), idPegawai);
//		GrantedAuthority authority = new SimpleGrantedAuthority("USER");
//		String token = tokenAuthenticationService.addAuthentication(httpResponse, new UserAuthentication(
//				new User(loginUserVO.getNamaUser(), loginUserVO.getKataSandi(), Arrays.asList(authority))));
//		mapHeaderMessage.put("X-AUTH-SUPERVISOR-TOKEN", token);
		
		return RestUtil.getJsonResponse(vo, HttpStatus.OK);
		

		// misal call service logout dan seterusnya
		// Karena Stateless tidak perlu set " session user " menjadi tidak
		// aktif, return HttpStatus.OK ke client
		//RestUtil.getJsonHttptatus(HttpStatus.OK);
	}
}
