package cn.com.qmth.stmms.common.controller;

import java.util.Date;

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

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
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.servlet.ModelAndView;

import cn.com.qmth.stmms.biz.config.service.impl.SystemCache;
import cn.com.qmth.stmms.biz.user.model.User;
import cn.com.qmth.stmms.biz.user.service.UserService;
import cn.com.qmth.stmms.common.annotation.Logging;
import cn.com.qmth.stmms.common.domain.WebUser;
import cn.com.qmth.stmms.common.enums.LogType;
import cn.com.qmth.stmms.common.enums.Role;
import cn.com.qmth.stmms.common.session.model.StmmsSession;
import cn.com.qmth.stmms.common.session.service.SessionService;
import cn.com.qmth.stmms.common.utils.EncryptUtils;
import cn.com.qmth.stmms.common.utils.RequestIPUtil;
import cn.com.qmth.stmms.common.utils.RequestUtils;
import cn.com.qmth.stmms.common.utils.VersionInfo;

@Controller
public class LoginController {

    @Autowired
    private UserService userService;

    @Autowired
    private SessionService sessionService;

    @Autowired
    private SystemCache authCache;

    @Value("${index.logo}")
    private String indexLogo;

    private static final String LOGIN_TYPE_KEY = "loginType";

    private static final String ADMIN_LOGIN = "admin-login";

    private static final String MARK_LOGIN = "mark-login";

    private static final String MARK_LOGIN_ONLY = "mark-login-only";

    @RequestMapping("/")
    public ModelAndView index(HttpServletRequest request) {
        return new ModelAndView("redirect:/login");
    }

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ModelAndView login(HttpServletRequest request) {
        ModelAndView view = new ModelAndView("modules/sys/login");
        view.addObject("indexLogo", indexLogo);
        view.addObject("versionName", VersionInfo.NAME);
        view.addObject("versionDate", VersionInfo.DATE);
        return view;
    }

    @Logging(menu = "登录", type = LogType.QUERY)
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public ModelAndView login(User user, @RequestParam String loginType, HttpServletRequest request,
            HttpServletResponse response) {
        StmmsSession session = RequestUtils.getSession(request);
        User u = userService.findByLoginName(user.getLoginName());
        ModelAndView modelAndView = new ModelAndView("modules/sys/login");
        modelAndView.addObject("indexLogo", indexLogo);
        modelAndView.addObject("versionName", VersionInfo.NAME);
        modelAndView.addObject("versionDate", VersionInfo.DATE);
        modelAndView.addObject(LOGIN_TYPE_KEY, loginType);
        if (u == null) {
            modelAndView.addObject("message", "user.login.error.account");
            return modelAndView;
        }
        if (!u.getPassword().equals(EncryptUtils.md5(user.getPassword()))) {
            modelAndView.addObject("message", "user.login.error.password");
            return modelAndView;
        }
        if (!u.isEnable()) {
            modelAndView.addObject("message", "user.login.error.disabled");
            return modelAndView;
        }
        if (!authCache.isAuth() && u.getRole() != Role.SYS_ADMIN) {
            modelAndView.addObject("message", "user.login.error.auth");
            return modelAndView;
        }
        if (authCache.getExpireTime() != null && new Date(authCache.getExpireTime()).before(new Date())
                && u.getRole() != Role.SYS_ADMIN) {
            modelAndView.addObject("message", "user.login.error.expire");
            return modelAndView;
        }
        if (ADMIN_LOGIN.equals(loginType)) {
            if (u.getRole() == Role.SYS_ADMIN || u.getRole() == Role.SCHOOL_ADMIN || u.getRole() == Role.SUBJECT_HEADER
                    || u.getRole() == Role.SCHOOL_VIEWER || u.getRole() == Role.INSPECTOR
                    || u.getRole() == Role.COLLEGE_ADMIN) {
                if (u.getLastLoginTime() == null
                        && (u.getRole() == Role.SUBJECT_HEADER || u.getRole() == Role.SCHOOL_VIEWER
                                || u.getRole() == Role.INSPECTOR || u.getRole() == Role.COLLEGE_ADMIN)) {
                    u.refreshAccessToken();
                    userService.save(u);
                    WebUser wu = new WebUser(u);
                    session.saveWebUser(wu);
                    sessionService.put(request, response, session);
                    return new ModelAndView("redirect:/admin/reset");
                }
                u.setLastLoginTime(new Date());
                u.setLastLoginIp(RequestIPUtil.getIpAddress(request));
                u.refreshAccessToken();
                u = userService.save(u);

                WebUser wu = new WebUser(u);
                session.saveWebUser(wu);
                sessionService.put(request, response, session);

                modelAndView = new ModelAndView("redirect:admin/home");
                return modelAndView;
            } else {
                modelAndView.addObject("message", "user.login.error.access");
                return modelAndView;
            }
        } else if (MARK_LOGIN.equals(loginType) || MARK_LOGIN_ONLY.equals(loginType)) {
            if (u.getRole() != Role.MARKER) {
                modelAndView.addObject("message", "user.login.error.access");
                return modelAndView;
            }
            if (u.getLastLoginTime() == null) {
                u.refreshAccessToken();
                userService.save(u);
                WebUser wu = new WebUser(u);
                session.saveWebUser(wu);
                sessionService.put(request, response, session);
                return new ModelAndView("redirect:/mark/reset");
            }
            u.setLastLoginTime(new Date());
            u.setLastLoginIp(RequestIPUtil.getIpAddress(request));
            u.refreshAccessToken();
            u = userService.save(u);
            WebUser wu = new WebUser(u);
            session.saveWebUser(wu);
            sessionService.put(request, response, session);
            return new ModelAndView("redirect:/mark/subject-select");
        }
        return modelAndView;
    }

    @RequestMapping(value = "/mark-login", method = RequestMethod.GET)
    public ModelAndView markIndex(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView view = new ModelAndView("modules/sys/login");
        view.addObject(LOGIN_TYPE_KEY, MARK_LOGIN_ONLY);
        view.addObject("indexLogo", indexLogo);
        view.addObject("versionName", VersionInfo.NAME);
        view.addObject("versionDate", VersionInfo.DATE);
        return view;
    }

    @Logging(menu = "评卷员登录", type = LogType.QUERY)
    @RequestMapping(value = "/mark-login", method = RequestMethod.POST)
    public ModelAndView markLogin(User user, HttpServletRequest request, HttpServletResponse response) {
        StmmsSession session = RequestUtils.getSession(request);
        User u = userService.findByLoginName(user.getLoginName());
        ModelAndView modelAndView = new ModelAndView("modules/sys/login");
        modelAndView.addObject("indexLogo", indexLogo);
        modelAndView.addObject("versionName", VersionInfo.NAME);
        modelAndView.addObject("versionDate", VersionInfo.DATE);
        modelAndView.addObject(LOGIN_TYPE_KEY, MARK_LOGIN_ONLY);
        if (!authCache.isAuth()
                || (authCache.getExpireTime() != null && new Date(authCache.getExpireTime()).before(new Date()))) {
            modelAndView.addObject("message", "user.login.error.auth");
            return modelAndView;
        }
        if (authCache.getExpireTime() != null && new Date(authCache.getExpireTime()).before(new Date())) {
            modelAndView.addObject("message", "user.login.error.expire");
            return modelAndView;
        }
        if (u == null) {
            modelAndView.addObject("message", "user.login.error.account");
            return modelAndView;
        }
        if (!u.getPassword().equals(EncryptUtils.md5(user.getPassword()))) {
            modelAndView.addObject("message", "user.login.error.password");
            return modelAndView;
        }
        if (!u.isEnable()) {
            modelAndView.addObject("message", "user.login.error.disabled");
            return modelAndView;
        }

        if (u.getRole() != Role.MARKER) {
            modelAndView.addObject("message", "user.login.error.access");
            return modelAndView;
        }
        if (u.getLastLoginTime() == null) {
            u.refreshAccessToken();
            userService.save(u);
            WebUser wu = new WebUser(u);
            session.saveWebUser(wu);
            sessionService.put(request, response, session);
            return new ModelAndView("redirect:/mark/reset");
        }
        u.setLastLoginTime(new Date());
        u.setLastLoginIp(RequestIPUtil.getIpAddress(request));
        u.refreshAccessToken();
        u = userService.save(u);
        WebUser wu = new WebUser(u);
        session.saveWebUser(wu);
        sessionService.put(request, response, session);
        return new ModelAndView("redirect:/mark/subject-select");
    }

    /**
     * 登出
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/logout")
    public ModelAndView logout(HttpServletRequest request, HttpServletResponse response) {
        StmmsSession session = RequestUtils.getSession(request);
        String logoutUrl = session.getWebUserLogoutUrl();
        session.setInvalid(true);
        if (StringUtils.isNotBlank(logoutUrl)) {
            return new ModelAndView("redirect:" + logoutUrl);
        } else {
            return new ModelAndView("redirect:/login");
        }
    }

}
