package com.tsiwebserver.controller;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.tsiwebserver.VO.UserVO;
import com.tsiwebserver.security.TSIEncoder;
import com.tsiwebserver.service.impl.LoginServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.repository.query.Param;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import lombok.RequiredArgsConstructor;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
@RequiredArgsConstructor
@Slf4j
public class LoginController {
	private final LoginServiceImpl loginServiceImpl;
	private final String REDIR2DENY = "redirect:/denied.do";
	private final String REDIR3DENY = "redirect:/gradeFailed.do";

	@GetMapping("/showlogin.do")
	public String showlogin() {
		return "login";
	}

	@GetMapping("/home.do")
	public String goHome() {
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		String home = "redirect:/showlogin.do";
		if (auth.getPrincipal() != null) {
			UserVO vo = (UserVO)auth.getPrincipal();
			if (vo.getUserGrade().equals("B")) {
				home = "redirect:/systemManagement.do";
			}
			else {
				home = "redirect:/dashBoard.do";
			}
		}
		return home;
	}

	@PostMapping("/login.do")
	public String login(UserVO userVO, RedirectAttributes redir, Model model) throws IOException{
		if (userVO == null) {
			return "redirect:/denied.do";
		} else {
			String reqId = userVO.getUserId();
			String reqPw = userVO.getUserPswd();
			if (reqId != null && reqPw != null) {
				String userId = reqId.split(",")[0];
				UserVO userDetails = this.loginServiceImpl.loadUserByUsername(userId);
				if (userDetails == null) {
					return REDIR2DENY;
				} else {
					redir.addFlashAttribute("userVO", userDetails);
					String encodedPw = userDetails.getPassword();
					if (userDetails.getUseyn().equals("N")) {
						return REDIR2DENY;
					} else {
						Boolean bool = TSIEncoder.matches(reqPw, encodedPw);
						if (Boolean.FALSE.equals(bool)) {
							return REDIR2DENY;
						} else {
							this.loginServiceImpl.initFailCnt(userId);
							String grade = userDetails.getUserGrade();
							String[] gradeList = {"I", "N", "M", "B"};
							List<String> gradlist = Arrays.asList(gradeList);
							if (!gradlist.contains(grade)) {
								return REDIR3DENY;
							}
							SecurityContext context = SecurityContextHolder.createEmptyContext();
							UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, encodedPw, userDetails.getAuthorities());
							context.setAuthentication(authentication);
							SecurityContextHolder.setContext(context);
							if (userDetails.getUserGrade().equals("B")) {
								return "redirect:/systemManagement.do";
							}
							else {
								return "redirect:/dashBoard.do";
							}
						}
					}
				}
			} else {
				return REDIR2DENY;
			}
		}
	}
	
//	@GetMapping("/login.do")
//	public String showDashBoard(Model model) {
//		model.addAttribute("menu", "dashboard");
//		return "dashBoard";
//	}

	@GetMapping({"/denied.do"})
	public String denied(HttpServletRequest req, @ModelAttribute("userVO") UserVO userVO) {
		if (userVO.getUserId() != null) {
			String useYN = userVO.getUseyn();
			req.setAttribute("userId", userVO.getUserId());
			req.setAttribute("useYN", useYN);
			req.setAttribute("failCnt", userVO.getFailCnt());
			if (useYN.equals("Y")) {
				this.loginServiceImpl.loginFail(userVO.getUserId());
			}
		}

		log.info("failed : {}",req.getAttribute("fail"));

		return "denied";
	}

	@GetMapping({"/gradeFailed.do"})
	public String gradeFailed() {
		return "gradeFailed";
	}

	@GetMapping("/logout.do")
	public String logout(HttpServletResponse res
						, HttpServletRequest req
						, HttpSession session) {
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		if(auth != null) {
			new SecurityContextLogoutHandler().logout(req, res, auth);
		}
		return "login";
	}
}
