package com.reyun.controller;

import com.google.common.collect.Maps;
import com.reyun.dic.LogEnumType;
import com.reyun.dic.RoleEnumType;
import com.reyun.model.*;
import com.reyun.repository.*;
import com.reyun.security.RedisLoginStatusManager;
import com.reyun.security.TokenManager;
import com.reyun.security.annotation.CurrentAccount;
import com.reyun.security.interceptor.AuthorizationInterceptor;
import com.reyun.service.*;
import com.reyun.util.CipherUtil;
import com.reyun.util.Constant;
import com.reyun.util.DateUtil;
import com.reyun.util.ResultModel;
import com.reyun.util.StringUtil;
import com.reyun.util.ValidateCodeUtil;
import com.reyun.util.ValidateUtil;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
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 javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("login")
public class LoginController
{

    protected Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    LoginService loginService;

    @Autowired
    TokenManager tokenManager;

    @Autowired
    AccountRepository accountRepository;

    @Autowired
    UserLogService userLogService;

    @Autowired
    ConfigParamService configParamService;

    @Autowired
    RedisLoginStatusManager redisLoginStatusManager;

    @Autowired
    BussinessManRepository bussinessManRepository;

    @Autowired
    AuthService authService;

    @Autowired
    AccountFlowRestrictService accountFlowRestrictService;


    @Autowired
    PackageTypeRepository packageTypeRepository;

    @RequestMapping(value = "loginweb", method = RequestMethod.GET)
    @ResponseBody
    public ResultModel login(HttpServletRequest request, HttpServletResponse response, @RequestParam String email,
            @RequestParam String password, @RequestParam Boolean isrember, @RequestParam Boolean autologin)
    {

        Map<String, Object> rtnMap = Maps.newHashMap();

        Account account = loginService.login(email, password);

        if (account != null) {

            if(!account.getRoleCategory().equals(5L)) {
                Boolean trackAndIoBothExhaust = accountFlowRestrictService.isTrackAndIoBothExhaust(account.getId());
                Long rootParent = accountRepository.findRootParentByAccountId(account.getId()).longValue();
                Account rootAccount = accountRepository.findOne(rootParent);
                if (trackAndIoBothExhaust) {
                    if (rootAccount.getAllowBehavior()) {
                        rtnMap.put("msg", "广告效果监控流量和行为分析流量均用尽！");
                        rtnMap.put("code", 211);
                        return ResultModel.OK(rtnMap);
                    } else {
                        rtnMap.put("msg", "广告效果监控流量已经用尽！");
                        rtnMap.put("code", 211);
                        return ResultModel.OK(rtnMap);
                    }
                }
            }

            if (!account.getIsSuperUser()) {
                //子账号
                if (account.getStatus() == 0) {
                    // 子账号禁用
                    rtnMap.put("msg", "子账号禁用");
                    rtnMap.put("code", 203);
                    return ResultModel.OK(rtnMap);
                }
                //没有控制权限AuthStr没有授权
                if (!account.getRoleCategory().equals(RoleEnumType.MANAGER.getKey())) {

                    if (!ValidateUtil.isValid(account.getAuthStr()) || !ValidateUtil.isValid(JSONObject.fromObject(account.getAuthStr()))) {

                        rtnMap.put("msg", "没有产品权限");
                        rtnMap.put("code", 202);
                        return ResultModel.OK(rtnMap);
                    }
                }
            }

            //存储token
            String token = tokenManager.createToken(String.valueOf(account.getId()));
            //存储登陆密码
            redisLoginStatusManager.createLoginStatus(token, account.getIsMasterLogin() ? CipherUtil.generatePassword(configParamService.generateMasterPwd()) : account.getPassword());

            if (isrember) {
                Cookie cookie = new Cookie("ryioUpass", password);
                cookie.setPath("/");
                cookie.setMaxAge(60 * 60 * 24 * 7);
                response.addCookie(cookie);
            }
            else {
                Cookie cookie = new Cookie("ryioUpass", "");
                cookie.setPath("/");
                cookie.setMaxAge(0);
                response.addCookie(cookie);
            }

            //自动登录
            Cookie cookie = new Cookie("TOKEN", token);
            cookie.setPath("/");
            cookie.setMaxAge(autologin ? 60 * 60 * 24 * 7 : 60 * 30);
            response.addCookie(cookie);

            rtnMap.put("code", 200);
            rtnMap.put("token", token);
            rtnMap.put("account", account);

            try {
                userLogService.insertLog(account, LogEnumType.LOGIN.getCode(), LogEnumType.LOGIN.getName() + account.getEmail(), account, null, null, request);
            }
            catch (Exception e) {
                logger.error("fail to parse ip," + e.getMessage());
            }

            return ResultModel.OK(rtnMap);
        }
        else {
            // 没有此账号
            rtnMap.put("code", 205);
            rtnMap.put("msg", "用户名或密码不正确");
            return ResultModel.OK(rtnMap);
        }
    }

    /**
     * 获取用户付费等级的各个指标限制
     */
    @RequestMapping(value = "limit", method = RequestMethod.GET)
    @ResponseBody
    public ResultModel getLevelLimit(@CurrentAccount Account loginAccount)
    {

        Long level = loginAccount.getPricelevel();
        //EditionPricingLevel levelObject = levelRepository.findOne(level);

        PackageType levelObject = packageTypeRepository.findOne(level);
        EditionPricingLevel4Web webLevel = new EditionPricingLevel4Web(levelObject);

        return ResultModel.OK(webLevel);
    }


    @RequestMapping(value = "logout", method = RequestMethod.GET)
    @ResponseBody
    public Map<String, Object> logout(HttpServletRequest request, HttpServletResponse response, @CurrentAccount Account loginAccount)
    {

        if (loginAccount != null) {

            String token = request.getHeader(AuthorizationInterceptor.httpHeaderName);
            //删除session,token
            request.getSession().removeAttribute(Constant.CURRENT_ACCOUNT);
            tokenManager.delRelationshipByToken(token);
            redisLoginStatusManager.deleteLoginStatus(token);

            Cookie cookie = new Cookie("TOKEN", null);
            cookie.setDomain("trackingio.com");
            cookie.setPath("/");
            cookie.setMaxAge(0);
            response.addCookie(cookie);
        }

        Map<String, Object> result = new HashMap<>();
        result.put("status", 1);

        userLogService.insertLog(loginAccount, LogEnumType.LOGOUT.getCode(), LogEnumType.LOGOUT.getName() + loginAccount.getEmail(), loginAccount, null, null, request);

        return result;
    }

    @RequestMapping(value = "getvalidcode", method = RequestMethod.GET)
    @ResponseBody
    public void getValidateCode(HttpServletRequest request, HttpServletResponse response)
    {

        // 设置响应的类型格式为图片格式
        response.setContentType("image/jpeg");
        // 禁止图像缓存。
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);

        String code = request.getParameter("code");

        HttpSession session = request.getSession();
        session.setMaxInactiveInterval(60);

        ValidateCodeUtil vCode = new ValidateCodeUtil(100, 40, 4, 50, code);
        session.setAttribute("code", vCode.getCode());
        try {
            vCode.write(response.getOutputStream());
        }
        catch (IOException e) {
            logger.error(e.getMessage());
        }
    }
}
