package com.its.op.controller.its;

import com.its.op.config.AppUtils;
import com.its.op.config.JasyptConfig;
import com.its.op.dto.its.LoginDto;
import com.its.op.dto.its.common.UserInfoDto;
import com.its.op.dto.its.oper.UserMenuDto;
import com.its.op.security.WebMvcConfig;
import com.its.op.service.its.LoginService;
import com.its.op.service.its.oper.TbUserInfrService;
import com.its.utils.CookieUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/auth")
@Api(tags = "00.공통-00.로그인/로그아웃")
public class LoginController {

    private final LoginService service;
    private final TbUserInfrService userService;

/*
    @GetMapping(value = "/proxy/xxx", produces = {"application/json; charset=utf8"})
    public String proxy() {
        String url = "http://localhost/api/xxx";

        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.getForObject(url, String.class);
    }
*/

//    @ApiOperation(value = "로그인", response = LoginDto.class)
//    @PostMapping(value = "/login", produces = {"application/json; charset=utf8"})
//    public LoginDto login(@RequestBody @Valid final LoginDto.LoginReqDto req) {
//        return this.service.login(req);
//    }

    /**
     * 로그인
     * @param login
     * @param model
     * @return
     */
    @PostMapping("/login.do")
    public String postLogin(@ModelAttribute LoginDto.LoginReqDto login, Model model) {
        log.error("postLogin: login, {}", login.toString());
        log.error("postLogin: model, {}", model.toString());
        model.addAttribute("login", login);
        return "success";
    }
    @GetMapping({"/login.do"})
    public ModelAndView getLogin(HttpServletRequest request, HttpServletResponse response) {
        //log.error("getLogin3: request, {}", request.toString());
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            //log.error("getLogin3: auth, {}", auth.toString());
            expiredCookie(response, WebMvcConfig.USER_UUID);
            expiredCookie(response, WebMvcConfig.USER_TIME);
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        HttpSession session = request.getSession(false);
        if (session != null) {
            //log.error("getLogin3: session, {}", session.toString());
            session.invalidate();   // session remove
        }
        //log.error("getLogin3: forward:/application/login/login.html");
        //return new ModelAndView("forward:/application/login/login.html");
        return new ModelAndView("redirect:/application/login/login.html");
    }

//    @ApiOperation(value = "로그아웃")
//    @PostMapping(value = "/logout", produces = {"application/json; charset=utf8"})
//    public void logout(@RequestBody @Valid final LoginDto.LogoutReqDto req) {
//        this.service.logout(req);
//    }
    public String getSessionUserId(HttpServletRequest request) {
        String userId = "";
        UserInfoDto userInfo = getSessionUserInfo(request);
        if (userInfo != null) {
             userId = userInfo.getUserId();
        }
        else {
            HttpSession session = request.getSession(false);
            if (session != null) {
                String encUserId = (String)session.getAttribute(WebMvcConfig.USER_UUID);
                if (!"".equals(encUserId)) {
                    userId = WebMvcConfig.decUserId(encUserId);
                }
            }
        }
        return userId;
    }

    public UserInfoDto getSessionUserInfo(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
//        for (int ii = 0; ii < cookies.length; ii++) {
//            log.info("getSessionUserInfo: {}, {}", cookies[ii].getName(), cookies[ii].getValue());
//        }
        String encUserId = "";
        String loginHms = "";
        if (cookies != null && cookies.length > 0) {
            encUserId = CookieUtils.getCookie(request, WebMvcConfig.USER_UUID);
            loginHms = CookieUtils.getCookie(request, WebMvcConfig.USER_TIME);
        }
        if (!"".equals(encUserId)) {
            String userId = WebMvcConfig.decUserId(encUserId);
            LoginDto.LogoutReqDto req = LoginDto.LogoutReqDto.builder()
                    .user_id(WebMvcConfig.decUserId(userId))
                    .login_hms(loginHms)
                    .build();
            log.info("logout: {}", req.toString());
            encUserId = userId;
        }
        return UserInfoDto.builder().userId(encUserId).build();
    }

    @PostMapping({"/userinfo.do"})
    public UserInfoDto getUserInfo(HttpServletRequest request, HttpServletResponse response) {
        return getSessionUserInfo(request);
    }

    /**
     * 로그아웃
     * @param request
     * @param response
     * @return
     */
    @GetMapping({"/logout.do"})
    public ModelAndView getLogout(HttpServletRequest request, HttpServletResponse response) {
        Cookie[] cookies = request.getCookies();
        for (int ii = 0; ii < cookies.length; ii++) {
            log.error("getLogout: {}, {}", cookies[ii].getName(), cookies[ii].getValue());
        }
        String encUserId = "";
        String loginHms = "";
        if (cookies != null && cookies.length > 0) {
            encUserId = CookieUtils.getCookie(request, WebMvcConfig.USER_UUID);
            loginHms = CookieUtils.getCookie(request, WebMvcConfig.USER_TIME);
            expiredCookie(response, WebMvcConfig.USER_UUID);
            expiredCookie(response, WebMvcConfig.USER_TIME);
        }
        if (!"".equals(encUserId)) {
            String userId = WebMvcConfig.decUserId(encUserId);
            LoginDto.LogoutReqDto req = LoginDto.LogoutReqDto.builder()
                    .user_id(WebMvcConfig.decUserId(userId))
                    .login_hms(loginHms)
                    .build();
            log.info("logout: {}", req.toString());
            this.service.logout(req);
        }

//        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
//        if (auth != null) {
//            // 여기로 안들어오네... 나중에 확인.....
//            log.error("Authentication: {}", auth.toString());
//            expiredCookie(response, WebMvcConfig.USER_UUID);
//            expiredCookie(response, WebMvcConfig.USER_TIME);
//            //new SecurityContextLogoutHandler().logout(request, response, auth);
//        }

        HttpSession session = request.getSession(false);
        if (session != null) {
            log.error("session: {}", session.toString());
            session.invalidate();   // session remove
        }
        new SecurityContextLogoutHandler().logout(request, response, SecurityContextHolder.getContext().getAuthentication());

        return new ModelAndView("redirect:/application/login/login.html");
    }

    private void expiredCookie(HttpServletResponse response, String cookieName) {
        Cookie cookie = new Cookie(cookieName, null);
        cookie.setMaxAge(0);
        response.addCookie(cookie);
    }

    @ApiOperation(value = "ENCRYPT", response = String.class)
    @GetMapping(value = "/encrypt/{string}", produces = {"application/json; charset=utf8"})
    public String encrypt(@PathVariable("string") String string) {
        JasyptConfig jasyptConfig = (JasyptConfig) AppUtils.getBean(JasyptConfig.class);
        return jasyptConfig.encrypt(string);
    }

    @ApiOperation(value = "DECRYPT", response = String.class)
    @GetMapping(value = "/decrypt/{string}", produces = {"application/json; charset=utf8"})
    public String decrypt(@PathVariable("string") String string) {
        JasyptConfig jasyptConfig = (JasyptConfig) AppUtils.getBean(JasyptConfig.class);
        return jasyptConfig.decrypt(string);
    }

    @ApiOperation(value = "사용자 접근 메뉴 조회", response = UserMenuDto.class, responseContainer = "ArrayList")
    @GetMapping(value = "/menu-auth/{name}", produces = {"application/json; charset=utf8"})
    public List<UserMenuDto> getUserMenuAuth(@PathVariable("name") String userId) {
        return this.userService.findUserMenuAuth(userId);
    }

}
