package com.mortals.xhx.base.login.web;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.ap.CookieService;
import com.mortals.framework.ap.GlobalSysInfo;
import com.mortals.framework.ap.SysConstains;
import com.mortals.framework.common.Rest;
import com.mortals.framework.service.IAuthTokenService;
import com.mortals.framework.service.ICacheService;
import com.mortals.framework.service.IUser;
import com.mortals.framework.util.AESUtil;
import com.mortals.framework.util.DateUtils;
import com.mortals.framework.util.HttpUtil;
import com.mortals.framework.util.StringUtils;
import com.mortals.framework.web.BaseCRUDJsonBodyMappingController;
import com.mortals.xhx.base.system.menu.model.MenuEntity;
import com.mortals.xhx.base.system.menu.service.MenuService;
import com.mortals.xhx.base.system.resource.service.ResourceService;
import com.mortals.xhx.base.system.user.model.UserEntity;
import com.mortals.xhx.base.system.user.service.UserService;
import com.mortals.xhx.base.system.valid.service.ValidCodeService;
import com.mortals.xhx.common.code.GoWorkResultEnum;
import com.mortals.xhx.common.code.OffWorkResultEnum;
import com.mortals.xhx.common.code.ProcessStatusEnum;
import com.mortals.xhx.common.code.SourceType;
import com.mortals.xhx.common.key.RedisKey;
import com.mortals.xhx.common.pdu.HomeStatInfo;
import com.mortals.xhx.common.pdu.user.UserPdu;
import com.mortals.xhx.feign.user.IUserFeign;
import com.mortals.xhx.module.attendance.model.*;
import com.mortals.xhx.module.attendance.service.AttendanceLeaveRecordService;
import com.mortals.xhx.module.attendance.service.AttendanceRecordHikService;
import com.mortals.xhx.module.attendance.service.AttendanceRecordService;
import com.mortals.xhx.module.attendance.service.AttendanceVacationRecordService;
import com.mortals.xhx.module.dept.model.DeptQuery;
import com.mortals.xhx.module.dept.service.DeptService;
import com.mortals.xhx.module.staff.model.StaffQuery;
import com.mortals.xhx.module.staff.service.StaffService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Set;

import static com.mortals.xhx.common.key.ErrorCode.ERROR_TOKEN_EXPIRED;
import static com.mortals.xhx.common.key.ErrorCode.ERROR_TOKEN_EXPIRED_CONTENT;

@RestController
@Slf4j
@RequestMapping("login")
public class LoginController extends BaseCRUDJsonBodyMappingController<UserService, UserEntity, Long> {

    @Autowired
    private UserService userService;
    @Autowired
    private ValidCodeService validCodeService;
    @Autowired
    private ResourceService resourceService;
    @Autowired
    private MenuService menuService;
    //    @Autowired
//    private ITokenService tokenService;
    @Autowired
    private ICacheService cacheService;
    @Autowired
    private IAuthTokenService authTokenService;
    @Autowired
    private AttendanceRecordService recordService;
    @Autowired
    private AttendanceRecordHikService recordHikService;

    @Autowired
    private AttendanceVacationRecordService vacationRecordService;

    @Autowired
    private AttendanceLeaveRecordService leaveRecordService;

    @Autowired
    private StaffService staffService;
    @Autowired
    private DeptService deptService;

    @Autowired
    private IUserFeign userFeign;


    @RequestMapping("login")
    public String login(@RequestBody LoginForm loginForm) throws Exception {

        String loginName = loginForm.getLoginName();
        String password = loginForm.getPassword();

        UserPdu userPdu = new UserPdu();
        userPdu.setLoginName(loginName);
        userPdu.setPassword(password);
        userPdu.setSecurityCode("admin");
        String resp = userFeign.portalLogin(userPdu);

        return resp;

/*

        JSONObject ret = new JSONObject();
        String loginName = loginForm.getLoginName();
        String password = loginForm.getPassword();
        String ip = super.getRequestIP(request);
        if (StringUtils.isEmpty(loginName) || StringUtils.isEmpty(password)) {
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, "未获取到用户信息，请重新登录");
            return ret.toJSONString();
        }
        UserEntity userEntity = null;
        try {
            loginForm.validate();
            userEntity = userService.doLogin(loginName, password, ip);
            userEntity.setLastLoginAddress(ip);

            recordSysLog(request, userEntity, "用户登录系统成功!");
            // 返回拥有的菜单数据
            Set<String> urls = resourceService.findUrlSetByUserId(userEntity.getId());
            List<MenuEntity> outlookBarList = menuService.findTreeMenu(userEntity, urls);
            String currUserName = userEntity.getRealName();
            if (currUserName == null || currUserName.trim().length() == 0) {
                currUserName = "管理员";
            }
            JSONObject data = new JSONObject();
            data.put("currUserName", currUserName);
            data.put("barList", outlookBarList);
            data.put("id", userEntity.getId());
            data.put("userType", userEntity.getUserType());
            userEntity.setLoginTime(System.currentTimeMillis());
            userEntity.setToken(IdUtil.fastSimpleUUID());
            userEntity.setExpireTime(DateUtils.addCurrDate(7).getTime());
            userEntity.setMenuUrl(generateMenuUrlCode(urls));

            String token = authTokenService.createToken(userEntity);
            data.put("token", token);
            //设置token 和过期时间
            //data.put("expiresTime", DateUtils.addCurrDate(7).getTime());
            generateMenuUrlCode(urls);
            //this.generateBlackCookie(request, response, loginName, urls);
            ret.put(KEY_RESULT_DATA, data);
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
            ret.put(KEY_RESULT_MSG, "用户登录系统成功!");
            ret.put("resources", urls);
            return ret.toJSONString();
        } catch (Exception e) {
            log.error("login error ", e);
            if (userEntity == null) {
                userEntity = new UserEntity();
                userEntity.setLoginName(loginName);
            }
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, super.convertException(e));
            return ret.toJSONString();
        }*/
    }

    @RequestMapping("logout")
    public void logout(HttpServletRequest request, HttpServletResponse response) throws Exception {
        recordSysLog(request, "退出登录");
        super.removeCurrUser(request);
        this.deleteBlackCookie(request, response);
    }

    @RequestMapping("index")
    public String index() throws Exception {
        JSONObject ret = new JSONObject();
        IUser user = this.getCurUser();
        if (user == null) {
            return JSONObject.toJSONString(Rest.fail(ERROR_TOKEN_EXPIRED, ERROR_TOKEN_EXPIRED_CONTENT));
        }
        Set<String> urls = resourceService.findUrlSetByUserId(user.getId());
        List<MenuEntity> outlookBarList = menuService.findTreeMenu(user, urls);
        String currUserName = user.getRealName();
        if (currUserName == null || currUserName.trim().length() == 0) {
            currUserName = "管理员";
        }
        JSONObject data = new JSONObject();
        String token = authTokenService.getToken(request);

        HomeStatInfo homeStatInfo = new HomeStatInfo();


        StaffQuery staffQuery = new StaffQuery();


        int totalPersonNum = staffService.count(staffQuery, this.getContext());
        homeStatInfo.setTotalPersonNum(totalPersonNum);
        staffQuery.setSource(1);

        Integer totalAttendPersonNum = staffService.count(staffQuery, this.getContext());

        int totalDeptNum = deptService.count(new DeptQuery(), getContext());
        homeStatInfo.setTotalDeptNum(totalDeptNum);

        AttendanceRecordHikQuery hikQuery = new AttendanceRecordHikQuery();
/*        hikQuery.setAttendanceDateStart(DateUtil.beginOfMonth(new Date()).toDateStr());
        hikQuery.setAttendanceDateEnd(DateUtil.today());        */
        hikQuery.setAttendanceDateStart(DateUtil.yesterday().toDateStr());
        hikQuery.setAttendanceDateEnd(DateUtil.yesterday().toDateStr());


        AttendanceRecordQuery attendanceRecordQuery = new AttendanceRecordQuery();
       // attendanceRecordQuery.setAttendanceDateStart(DateUtil.beginOfMonth(new Date()).toDateStr());
        //attendanceRecordQuery.setAttendanceDateEnd(DateUtil.today());
        attendanceRecordQuery.setAttendanceDateStart(DateUtil.yesterday().toDateStr());
        attendanceRecordQuery.setAttendanceDateEnd(DateUtil.yesterday().toDateStr());
        List<AttendanceRecordEntity> attendanceRecordEntities = recordService.find(attendanceRecordQuery);


        //获取当月打卡人数，如果存在
/*        Long totalCache = cacheService.hget(RedisKey.KEY_ATTENC_TOTOAL_CACHE, DateUtil.format(new Date(), "yyyy-MM"), Long.class);
        if (ObjectUtils.isEmpty(totalCache)) {
            totalCache = recordHikService.find(hikQuery).parallelStream().map(item -> item.getStaffId()).distinct().count();
            cacheService.hset(RedisKey.KEY_ATTENC_TOTOAL_CACHE, DateUtil.format(new Date(), "yyyy-MM"), totalCache);
        }*/

/*        Long totalCache = cacheService.hget(RedisKey.KEY_ATTENC_TOTOAL_CACHE, DateUtil.yesterday().toDateStr(), Long.class);
        if (ObjectUtils.isEmpty(totalCache)) {
            totalCache = recordHikService.find(hikQuery).parallelStream().map(item -> item.getStaffId()).distinct().count();
            cacheService.hset(RedisKey.KEY_ATTENC_TOTOAL_CACHE, DateUtil.yesterday().toDateStr(), totalCache);
        }*/


        //迟到次数
        long beLate = attendanceRecordEntities.parallelStream()
                .flatMap(item -> item.getAttendanceRecordDetailList().stream())
                .filter(f -> GoWorkResultEnum.迟到.getValue() == f.getGoWorkResult() || OffWorkResultEnum.迟到.getValue() == f.getOffWorkResult())
                .map(i -> i.getStaffId())
                .distinct()
                .count();

        //早退次数
        long leaveEarly = attendanceRecordEntities.parallelStream()
                .flatMap(item -> item.getAttendanceRecordDetailList().stream())
                .filter(f -> GoWorkResultEnum.早退.getValue() == f.getGoWorkResult() || OffWorkResultEnum.早退.getValue() == f.getOffWorkResult())
                .map(i -> i.getStaffId())
                .distinct()
                .count();

        //缺卡次数
        long lackOfCards = attendanceRecordEntities.parallelStream()
                .flatMap(item -> item.getAttendanceRecordDetailList().stream())
                .filter(f -> GoWorkResultEnum.缺卡.getValue() == f.getGoWorkResult() || OffWorkResultEnum.缺卡.getValue() == f.getOffWorkResult())
                .map(i -> i.getStaffId())
                .distinct()
                .count();


/*        AttendanceVacationRecordQuery vacationRecordQuery = new AttendanceVacationRecordQuery();
        vacationRecordQuery.setCreateTimeStart(DateUtil.beginOfMonth(new Date()).toDateStr());
        vacationRecordQuery.setCreateTimeEnd(DateUtil.today());
        int levealPersonNum = vacationRecordService.count(vacationRecordQuery, getContext());*/

        AttendanceLeaveRecordQuery leaveRecordQuery = new AttendanceLeaveRecordQuery();
/*        leaveRecordQuery.setCreateTimeStart(DateUtil.beginOfMonth(new Date()).toDateStr());
        leaveRecordQuery.setCreateTimeEnd(DateUtil.today());*/
        leaveRecordQuery.setCreateTimeStart(DateUtil.yesterday().toDateStr());
        leaveRecordQuery.setCreateTimeEnd(DateUtil.yesterday().toDateStr());
        leaveRecordQuery.setProcessStatus(ProcessStatusEnum.已处理.getValue());
        int levealPersonNum = leaveRecordService.count(leaveRecordQuery, getContext());


        //总打卡记录
/*        long totalAttend = attendanceRecordEntities.parallelStream().flatMap(item -> item.getAttendanceRecordDetailList().parallelStream()).count();

        long lackOfCardsAttend = attendanceRecordEntities.parallelStream()
                .flatMap(item -> item.getAttendanceRecordDetailList().stream())
                .filter(f -> GoWorkResultEnum.缺卡.getValue() == f.getGoWorkResult() || OffWorkResultEnum.缺卡.getValue() == f.getOffWorkResult())
                .count();*/
        //异常考勤记录
        //未考勤
        // long noAtt=lackOfCards;
        long att = totalAttendPersonNum - lackOfCards;
       // long att = totalAttend - lackOfCardsAttend;
        if (att != 0L) {

            BigDecimal bigDecimal = new BigDecimal(att).divide(new BigDecimal(totalAttendPersonNum), 4, BigDecimal.ROUND_CEILING).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_CEILING);
            homeStatInfo.setAttendRadio(bigDecimal.toString() + "%");
        } else {
            homeStatInfo.setAttendRadio("0%");
        }

        homeStatInfo.setLevealPersonNum(levealPersonNum);
        homeStatInfo.setLatePersonNum(beLate);
        homeStatInfo.setLeftEarlyPersonNum(leaveEarly);
        homeStatInfo.setMissCardPersonNum(lackOfCards);
        homeStatInfo.setAttendPersonNum(totalAttendPersonNum);

        data.put("homeStat", homeStatInfo);
        data.put("token", token);
        data.put("currUserName", currUserName);
        data.put("barList", outlookBarList);
        data.put("id", user.getId());
        data.put("userType", user.getUserType());
        ret.put(KEY_RESULT_DATA, data);
        //this.generateBlackCookie(request, response, user.getLoginName(), urls);
        ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        ret.put(KEY_RESULT_MSG, "用户登录系统成功!");
        ret.put("resources", urls);
        return ret.toJSONString();
    }


    @RequestMapping("validcode")
    public String validCode(HttpServletRequest request, HttpServletResponse response, LoginForm loginForm) {
        JSONObject ret = new JSONObject();
        String loginName = loginForm.getLoginName();
        String password = loginForm.getPassword();
        if (StringUtils.isEmpty(loginName) || StringUtils.isEmpty(password)) {
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, "登录名或密码为空");
        }
        UserEntity user = null;
        try {
            user = userService.doCheckUser(loginName, password);
            if (user == null) {
                ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
                ret.put(KEY_RESULT_MSG, "用户名或密码不正确");
            } else if (StringUtils.isEmpty(user.getMobile())) {
                ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
                ret.put(KEY_RESULT_MSG, "用户无正确的手机号");
            } else {
                String mobile = StringUtils.trim(user.getMobile());
                String sessionId = request.getSession().getId();
                String ip = super.getRequestIP(request);
                boolean result = validCodeService.createSmsValidCode(sessionId, ip, mobile);
                if (result) {
                    ret.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
                } else {
                    ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
                    ret.put(KEY_RESULT_MSG, "验证码发送失败，请稍后在试！");
                }
            }
        } catch (Exception e) {
            ret.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            ret.put(KEY_RESULT_MSG, "验证码发送失败：" + super.convertException(e));
        } finally {
            if (user == null) {
                user = new UserEntity();
                user.setLoginName(loginName);
            }
            recordSysLog(request, user, "用户获取短信验证码");
        }
        return ret.toJSONString();
    }

    protected void deleteBlackCookie(HttpServletRequest request, HttpServletResponse response) {
        try {
            CookieService.deleteCookieForAuth(request, response);
        } catch (Throwable e) {
        }
    }


    public static void main(String[] args) {
        System.out.println(DateUtil.beginOfMonth(new Date()).toDateStr());
    }

}
