package com.sunxung.factoring.service.sys.impl;

import java.util.Date;
import java.util.List;

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

import com.google.common.collect.Lists;
import com.sunxung.factoring.component.enums.ClientTypeEnum;
import com.sunxung.factoring.component.util.*;
import com.sunxung.factoring.entity.sys.*;
import com.sunxung.factoring.service.sys.dto.LoginResultDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sunxung.factoring.component.exception.ValidatorException;
import com.sunxung.factoring.dict.impl.LogTypeDict;
import com.sunxung.factoring.mapper.sys.AuthorityMapper;
import com.sunxung.factoring.service.sys.AuthorityService;
import com.sunxung.factoring.service.sys.DictionaryService;
import com.sunxung.factoring.service.sys.LoginLogService;
import com.sunxung.factoring.service.sys.RoleService;
import com.sunxung.factoring.service.sys.SessionService;
import com.sunxung.factoring.service.sys.UserService;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @Description 类
 * @author JiangJing
 * @date 2017年3月13日 上午11:05:54
 * @version 1.0
 */
@Service
public class AuthorityServiceImpl implements AuthorityService {

    @Autowired
    private AuthorityMapper authorityMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private SessionService sessionService;
    @Autowired
    private LoginLogService loginLogService;
    @Autowired
    private DictionaryService dictionaryService;
    @Autowired
    private RoleService roleService;

//    /** 获取IP地址 */
//    private String getIpAddr(HttpServletRequest request) {
//        String ip = request.getHeader("x-forwarded-for");
//        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
//            ip = request.getHeader("Proxy-Client-IP");
//        }
//        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
//            ip = request.getHeader("WL-Proxy-Client-IP");
//        }
//        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
//            ip = request.getRemoteAddr();
//        }
//        return ip;
//    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginResultDto login(String loginName, String password) {
        User entiy = userService.getByLoginName(loginName);
        if(entiy==null){
            throw new ValidatorException(CodeUtil.FAIL, "该用户不存在");
        }
        // 判断是否给分配了角色以及设置管理员角色
        if (null != entiy) {
            List<UserRoleRel> roleIdList = roleService.getUserRoleByUserId(entiy.getId());
            if (null == roleIdList || roleIdList.size() == 0) {
                throw new ValidatorException(CodeUtil.FAIL, "您暂时还无法登录系统，请联系管理分配一个角色");
            }
            List<Role> roles = Lists.newArrayList();
            for (UserRoleRel role : roleIdList) {
                if (role.isAdmin()) {
                    entiy.setAdmin(true);
                    break;
                }else{
                    Role roleDO = roleService.get(role.getRoleId());
                    roles.add(roleDO);
                }
            }
            entiy.setRoles(roles);
        }
        if (entiy == null || !PasswordUtil.validatePassword(password, entiy.getPassword())) {
            throw new ValidatorException(CodeUtil.FAIL, "账号或密码错误");
        }
        if (entiy != null) {
            if (!entiy.isEnabled()) {
                throw new ValidatorException(CodeUtil.FAIL, "账户被禁用");
            }
        }
        //sessionService.deleteByUserId(entiy.getId());
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ipAddr = IpUtil.getIpAddress(request);
       // Session session = sessionService.add(new Session(entiy, remember, ipAddr));
        List<Long> orgIdList = userService.getOrgIdByUserId(entiy.getId());
        entiy.setOrgIdList(orgIdList);
        //ThreadLocalUtil.setSession(session);
        ThreadLocalUtil.setUser(entiy);
//        if (remember) {
//            CookieUtil.addSid(response, String.valueOf(session.getId()));
//            httpRequest.getSession().setAttribute("loginName", loginName);
//            httpRequest.getSession().setAttribute("password", password);
//            httpRequest.getSession().setAttribute("remember", remember);
//        } else {
//            httpRequest.getSession().setAttribute("loginName", null);
//            httpRequest.getSession().setAttribute("password", null);
//            httpRequest.getSession().setAttribute("remember", null);
//        }
        LoginLog log = new LoginLog(entiy, ipAddr);
        log.setLogType(dictionaryService.getByCode(LogTypeDict.ChildEnum.USER_LOGIN.getCode()));
        loginLogService.add(log);
        LoginResultDto tokenAndSession = sessionService.createTokenAndSession(ClientTypeEnum.WEB,
            entiy);
        return tokenAndSession;
    }

    @Override
    public void loginOut(String token) {
        sessionService.destory(token);
    }

    @Override
    public User getUserByToken(String token) {

        return  sessionService.getLoginUserByToken(token);
    }


    @Override
    public boolean sginOut(HttpServletRequest httpRequest, HttpServletResponse response) {
        User user = ThreadLocalUtil.getUser();
        if (null != user) {
            LoginLog log = new LoginLog(user, IpUtil.getIpAddress(httpRequest));
            log.setLogType(dictionaryService.getByCode(LogTypeDict.ChildEnum.USER_SELF_CANCELLATION.getCode()));
            loginLogService.add(log);
        }
        String sid = CookieUtil.getSid(httpRequest);
        String sessionIdStr = (String) httpRequest.getSession().getAttribute(SystemVariable.SESSION_KEY);
        Long sessionId = null;
        if (StringUtil.isNotEmpty(sessionIdStr)) {
            sessionId = Long.valueOf(sessionIdStr);
        }
        Session session = null;
        if (StringUtil.isNotEmpty(sid)) {
            session = sessionService.get(Long.valueOf(sid));
        } else {
            if (null != sessionId) {
                session = sessionService.get(sessionId);
            }
        }
        if (session == null) {
            return false;
        }
        sessionService.delete(Long.valueOf(session.getId()));
        CookieUtil.deleteSid(response);
        ThreadLocalUtil.clearThreadVariable();
        return true;
    }

    @Override
    public boolean isLogin(Long sid, String url) {
        Session session = sessionService.get(sid);
        if (session == null) {
            return false;
        }
        User user = userService.get(session.getUserId());
        if (user == null || session.isSessionTimeOut()) {
            loginInvalid(session);
            sessionService.delete(sid);
            return false;
        }
        List<Long> orgIdList = userService.getOrgIdByUserId(user.getId());
        user.setOrgIdList(orgIdList);
        if (!url.equals("/systemMsg/do_getUnreadMessageNum")) {
            session.setLaterTime(new Date());
        }
        session.setUrl(url);
        // 设置用户是否是管理员
        if (null != user) {
            List<UserRoleRel> roleIdList = roleService.getUserRoleByUserId(user.getId());
            for (UserRoleRel role : roleIdList) {
                if (role.isAdmin()) {
                    user.setAdmin(true);
                    break;
                }
            }
        }
        sessionService.update(session);
        ThreadLocalUtil.setSession(session);
        ThreadLocalUtil.setUser(user);
        return true;
    }

    @Override
    public boolean hasPermission(String ename) {
        User user = ThreadLocalUtil.getUser();
        if (user == null) {
            return false;
        }
        List<UserRoleRel> roleIdList = roleService.getUserRoleByUserId(user.getId());
        for (UserRoleRel role : roleIdList) {
            if (role.isAdmin()) {
                return true;
            }
        }
        // if (null != user.getAdmin() && user.getAdmin()) {
        // return true;
        // }
        return authorityMapper.hasPermission(user.getId(), ename) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean doSginOut(Long id, HttpServletRequest request) {
        Session session = sessionService.get(id);
        if (session == null) {
            return false;
        }
        String sessionIdStr = (String) request.getSession().getAttribute(SystemVariable.SESSION_KEY);
        Long sessionId = null;
        if (StringUtil.isNotEmpty(sessionIdStr)) {
            sessionId = Long.valueOf(sessionIdStr);
        }
        if (null != sessionId) {
            if (sessionId == id) {
                throw new ValidatorException(CodeUtil.FAIL, "不能注销您自己的账号");
            }
        }
        if (null != session.getId()) {
            User user = userService.get(session.getUserId());
            LoginLog log = new LoginLog(user);
            log.setLogType(dictionaryService.getByCode(LogTypeDict.ChildEnum.USER_OFF_BY_ADMIN.getCode()));
            loginLogService.add(log);
        }
        return sessionService.delete(id);
    }

    /**
     * 当session过期，用户自动退出登录时。往登录日志表中添加一条用户失效的记录
     */
    private void loginInvalid(Session session) {
        if (null != session && null != session.getUserId()) {
            User user = userService.get(session.getUserId());
            if (null != user) {
                LoginLog log = new LoginLog(user);
                log.setLogType(dictionaryService.getByCode(LogTypeDict.ChildEnum.USER_FAILED.getCode()));
                loginLogService.add(log);
            }
        }
    }
}
