package com.yx.face.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yx.face.boot.component.security.JWTUtils;
import com.yx.face.boot.core.Constants;
import com.yx.face.boot.restful.*;
import com.yx.face.boot.uitls.*;
import com.yx.face.dao.AdminDao;
import com.yx.face.dao.AdminTagDao;
import com.yx.face.dao.AreaCodeDao;
import com.yx.face.dao.SystemConfigDao;
import com.yx.face.model.dto.AdminDTO;
import com.yx.face.model.entity.Admin;
import com.yx.face.model.entity.AdminTag;
import com.yx.face.model.entity.AreaCode;
import com.yx.face.model.excel.AdminInfoExcel;
import com.yx.face.model.search.AdminSearch;
import com.yx.face.model.update.AdminUpdate;
import com.yx.face.model.vo.AdminVO;
import com.yx.face.service.AdminService;
import com.yx.face.service.AreaCodeService;
import com.yx.face.service.PoliceStationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;


/**
 * @description: 管理人员信息表(Admin)表服务实现类 <br>
 * @author: PWB <br>
 * @since: 1.0 <br>
 * @date: 2021-05-06 11:15:50 <br>
 */

@Service
public class AdminServiceImpl implements AdminService {
    @Resource
    private AdminDao adminDao;
    @Resource
    private AreaCodeService areaCodeService;
    @Resource
    private AreaCodeDao areaCodeDao;
    @Resource
    private PoliceStationService policeStationService;
    @Resource
    private AdminTagDao adminTagDao;
    @Resource
    private SystemConfigDao systemConfigDao;
    @Value("${web.address}")
    private String address;

    @Autowired
    private RedisUtil redisUtil;

    private static final String ADMIN_LOGIN = "adminLogin";

    @Override
    public AdminVO login(String name, String password) {
        Admin adminInfo = new Admin();
        //账户名使用的昵称
        adminInfo.setUsername(name);
        adminInfo = adminDao.selectOne(adminInfo);
        if (adminInfo == null) {
            throw new ServiceException("账号或密码输入错误");
        }
        /*
         * redis校验
         * */
        String ipLogin = IPUtils.getIP() + ADMIN_LOGIN + adminInfo.getId();
        Integer adminLogin = (Integer) redisUtil.get(ipLogin);
        if (adminLogin != null && adminLogin >= 5) {
            redisUtil.incr(ipLogin, 1);
            redisUtil.expire(ipLogin, 300);
            throw new ServiceException("连续输错" + adminLogin + "次，账号锁定，请过5分钟后重试!");
        }

        password = PasswordUtils.buildPw(password);
        if (!adminInfo.getPassword().equals(password)) {
            //每次输错便加1，并设置过期时间为5分钟
            redisUtil.incr(ipLogin, 1);
            redisUtil.expire(ipLogin, 300);
            throw new ServiceException("账号或密码输入错误");
        } else {
            //登录成功
            boolean b = redisUtil.hasKey(ipLogin);
            if (b) {
                redisUtil.del(ipLogin);
            }
        }
        AdminVO adminLoginVO = new AdminVO();
        adminLoginVO.setAdminId(adminInfo.getId());
        adminLoginVO.setName(adminInfo.getNickname());
        adminLoginVO.setUsername(adminInfo.getUsername());
        adminLoginVO.setAvatar(adminInfo.getAvatar());
        /*adminLoginVO.setPhone();
        adminLoginVO.setEmail();
        adminLoginVO.setGender();*/
        adminLoginVO.setType(adminInfo.getType());
        adminLoginVO.setToken(JWTUtils.sign(adminInfo.getId().toString(), password, DateUtils.addDays(new Date(), 1)));
        /*wxg 2021-11-4 增加省市区详细地址 开始*/
        adminLoginVO.setProvinceId(adminInfo.getProvinceId());
        adminLoginVO.setProvinceName(adminInfo.getProvinceName());
        adminLoginVO.setCityId(adminInfo.getCityId());
        adminLoginVO.setCityName(adminInfo.getCityName());
        adminLoginVO.setAreaId(adminInfo.getAreaId());
        adminLoginVO.setAreaName(adminInfo.getAreaName());
        adminLoginVO.setStreetId(adminInfo.getStreetId());
        adminLoginVO.setStreetName(adminInfo.getStreetName());
        adminLoginVO.setAddress(adminInfo.getAddress());
        adminLoginVO.setPoliceStationCode(adminInfo.getPoliceStationCode());
        adminLoginVO.setPoliceStationName(adminInfo.getPoliceStationName());
        adminLoginVO.setTagId(adminInfo.getTagId());
        adminLoginVO.setIsControlEarlyWarning(adminInfo.getIsControlEarlyWarning());
        if (adminInfo.getTagId() != null) {
            adminLoginVO.setTagName(adminTagDao.selectByPrimaryKey(adminInfo.getTagId()).getName());
        }
//        SystemConfigVO vo = systemConfigDao.sysConfiguration(adminLoginVO.getAdminId());
//        if (vo != null) {
//            adminLoginVO.setSysQueryConfiguration(1);
//            adminLoginVO.setSysQueryConfiguration(vo.getStatus());
//        } else {
//            adminLoginVO.setSysQueryConfiguration(0);
//        }
        /*wxg 2021-11-4 增加省市区详细地址 结束*/
        return adminLoginVO;
    }


    @Override
    public Boolean logout() {
        return null;
    }

    @Override
    public AdminVO getInfo(Integer userId) {
        Admin adminInfo = adminDao.selectByPrimaryKey(userId);
        if (adminInfo == null) {
            throw new ServiceException("无此用户信息");
        }
        AdminVO adminLoginVO = new AdminVO();
        adminLoginVO.setAdminId(userId);
        adminLoginVO.setName(adminInfo.getNickname());
        adminLoginVO.setUsername(adminInfo.getUsername());
        adminLoginVO.setAvatar(adminInfo.getAvatar());
        adminLoginVO.setType(adminInfo.getType());
        adminLoginVO.setPhone(adminInfo.getPhone());
        adminLoginVO.setEmail(adminInfo.getEmail());
        if (adminInfo.getTagId() != null) {
            adminLoginVO.setTagName(adminTagDao.selectByPrimaryKey(adminInfo.getTagId()).getName());
        }
        adminLoginVO.setTagId(adminInfo.getTagId());
        adminLoginVO.setIsOut(adminInfo.getIsOut());
        adminLoginVO.setIsHideImportant(adminInfo.getIsHideImportant());

        /*wxg 2021-11-4 增加省市区详细地址 开始*/
        adminLoginVO.setProvinceId(adminInfo.getProvinceId());
        adminLoginVO.setProvinceName(adminInfo.getProvinceName());
        adminLoginVO.setCityId(adminInfo.getCityId());
        adminLoginVO.setCityName(adminInfo.getCityName());
        adminLoginVO.setAreaId(adminInfo.getAreaId());
        adminLoginVO.setAreaName(adminInfo.getAreaName());
        adminLoginVO.setStreetId(adminInfo.getStreetId());
        adminLoginVO.setStreetName(adminInfo.getStreetName());
        adminLoginVO.setAddress(adminInfo.getAddress());
        adminLoginVO.setPoliceStationCode(adminInfo.getPoliceStationCode());
        adminLoginVO.setPoliceStationName(adminInfo.getPoliceStationName());
        adminLoginVO.setIsControlEarlyWarning(adminInfo.getIsControlEarlyWarning());
        /*wxg 2021-11-4 增加省市区详细地址 结束*/
//        SystemConfigVO vo = systemConfigDao.sysConfiguration(adminLoginVO.getAdminId());
//        if (vo != null) {
//            adminLoginVO.setSysQueryConfiguration(1);
//            adminLoginVO.setSysQueryConfiguration(vo.getStatus());
//        } else {
//            adminLoginVO.setSysQueryConfiguration(0);
//        }
        return adminLoginVO;
    }

    @Transactional
    @Override
    public Boolean editAdmin(AdminDTO dto) {
        Date date = new Date();
        Admin adminInfo = new Admin();
        adminInfo.setId(dto.getAdminId());
        adminInfo.setUsername(dto.getUsername());
        adminInfo.setAvatar(dto.getAvatar());
        adminInfo.setIdNumber(dto.getIdNumber());
        adminInfo.setPhone(dto.getPhone());
        adminInfo.setEmail(dto.getEmail());
        adminInfo.setGender(dto.getGender());
        adminInfo.setUpdateTime(date);
        adminInfo.setNickname(dto.getName());
        adminInfo.setType(dto.getType());
        adminInfo.setIsOut(dto.getIsOut());
        adminInfo.setTagId(dto.getTagId());
        adminInfo.setIsHideImportant(dto.getIsHideImportant());
        /*wxg 2021-11-4 增加省市区详细地址 开始*/
        adminInfo.setProvinceId(dto.getProvinceId() == null ? null : dto.getProvinceId());
        adminInfo.setProvinceName(dto.getProvinceId() == null ? null : areaCodeService.getById(dto.getProvinceId()).getName());
        adminInfo.setCityId(dto.getCityId() == null ? null : dto.getCityId());
        adminInfo.setCityName(dto.getCityId() == null ? null : areaCodeService.getById(dto.getCityId()).getName());
        adminInfo.setAreaId(dto.getAreaId() == null ? null : dto.getAreaId());
        adminInfo.setAreaName(dto.getAreaId() == null ? null : areaCodeService.getById(dto.getAreaId()).getName());
        adminInfo.setStreetId(dto.getStreetId() == null ? null : dto.getStreetId());
        adminInfo.setStreetName(dto.getStreetId() == null ? null : areaCodeService.getById(dto.getStreetId()).getName());
        adminInfo.setAddress(dto.getAddress());
        adminInfo.setIsControlEarlyWarning(dto.getIsControlEarlyWarning());
//        if(dto.getPoliceStationCode()==null||dto.getPoliceStationCode().equals("")){
//            throw new ServiceException("派出所编码不能为空");
//        }
        adminInfo.setPoliceStationName(dto.getPoliceStationName() == null ? null : dto.getPoliceStationName());
        adminInfo.setPoliceStationCode(dto.getPoliceStationCode() == null ? null : dto.getPoliceStationCode());
        /*wxg 2021-11-4 增加省市区详细地址 结束*/
        if (dto.getAdminId() == null) {
            if (!StringUtils.hasText(dto.getPassword())) {
                throw new ServiceException("请输入密码");
            }
            if (!StringUtils.hasText(dto.getName())) {
                throw new ServiceException("请输入账号名称");
            }
            Admin info = new Admin();
            info.setUsername(dto.getUsername());
            info = adminDao.selectOne(info);
            if (info != null) {
                throw new ServiceException("该账号名称已被注册");
            }
            adminInfo.setPassword(PasswordUtils.buildPw(dto.getPassword()));
            adminInfo.setCreateTime(date);
            adminDao.insertSelective(adminInfo);
            try {
                String content = address.substring(0, address.length() - 1).concat("?orgId=") + adminInfo.getId() + "&org=" + dto.getUsername();
                String path = FileUtils.getDirectory(Constants.SYSTEM_FILE) + "/admin_code_" + adminInfo.getId() + ".png";
                QRCodeUtil.encode(content, "", path, true);
                adminInfo.setEmail(address + path);
                adminDao.updateByPrimaryKeySelective(adminInfo);
            } catch (Exception e) {
                throw new ServiceException("生成二维码失败");
            }
            return true;
        } else {
            if (StringUtils.hasText(dto.getPassword())) {
                adminInfo.setPassword(PasswordUtils.buildPw(dto.getPassword()));
            }
            if (StringUtils.hasText(dto.getUsername())) {
                Admin info = new Admin();
                info.setUsername(dto.getUsername());
                info = adminDao.selectOne(info);
                if (info != null) {
                    if (!info.getId().equals(dto.getAdminId())) {
                        throw new ServiceException("该账号名称已被注册");
                    }
                }
            }
            Admin admin = adminDao.selectByPrimaryKey(dto.getAdminId());
            if (admin == null) {
                throw new ServiceException("未发现该账号");
            }
            try {
                String content;
                if (StringUtils.hasText(dto.getUsername())) {
                    content = address.substring(0, address.length() - 1).concat("?orgId=") + admin.getId() + "&org=" + dto.getUsername();
                } else {
                    content = address.substring(0, address.length() - 1).concat("?orgId=") + admin.getId() + "&org=" + admin.getUsername();
                }
                String path = FileUtils.getDirectory(Constants.SYSTEM_FILE) + "/admin_code_" + adminInfo.getId() + ".png";
                QRCodeUtil.encode(content, "", path, true);
                adminInfo.setEmail(address + path);
            } catch (Exception e) {
                throw new ServiceException("生成二维码失败");
            }
            adminDao.updateByPrimaryKeySelective(adminInfo);
            return true;
        }

    }


    public static void main(String[] args) throws Exception {
        String address = "http://127.0.0.1:9100/fyzd/";
        String content = address.substring(0, address.length() - 1).concat("?orgId=") + 40 + "&org=" + "吾问无";
        String path = FileUtils.getDirectory(Constants.SYSTEM_FILE) + "/admin_code_" + 40 + ".png";
        QRCodeUtil.encode(content, "", path, true);
    }

    @Override
    public PageInfo<AdminVO> getAdmins(RestDTO<AdminSearch> dto) {
        AdminVO info = getInfo();
        AdminSearch data = dto.getData();
        Map<String, Object> map = new HashMap();
        map.put("type", info.getType());
        map.put("adminVo", info);
        map.put("ads", data);

        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        return new PageInfo<>(adminDao.getAdmins(map));
    }

    @Override
    public Boolean deleteAdmin(Long id) {
        return adminDao.deleteByPrimaryKey(id) == 1;
    }


    @Override
    public AdminVO getAuthInfo(Integer id) {
        return adminDao.getAuthInfo(id);
    }

    @Override
    public AdminVO getInfo() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            throw new CommonException(RestCode.UNAUTHORIZED);
        }
        HttpServletRequest request = requestAttributes.getRequest();
        String token = request.getHeader("Authorization");
        if (token == null || token.equals("")) {
            throw new ServiceException(RestCode.UNAUTHORIZED.code, "缺少token");
        }
        token = JWTUtils.getUserId(token);
        if (org.apache.commons.lang3.StringUtils.isEmpty(token)) {
            throw new CommonException(RestCode.UNAUTHORIZED);
        }
        return getInfo(Integer.parseInt(token));
    }

    @Override
    public RestResult<List<String>> uploadAdminInfoExcel(List<Object> datas) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < datas.size(); i++) {
            try {
                AdminInfoExcel adminInfoExcel = (AdminInfoExcel) datas.get(i);
                if (adminInfoExcel.getUsername() == null) throw new ServiceException("第" + (i + 2) + "行,账号名称不能为空");
                if (adminInfoExcel.getType() == null) throw new ServiceException("第" + (i + 2) + "行,账号级别不能为空");
                if (adminInfoExcel.getName() == null) throw new ServiceException("第" + (i + 2) + "行,管理员姓名不能为空");
                if (adminInfoExcel.getPhone() == null) throw new ServiceException("第" + (i + 2) + "行,管理员手机号不能为空");
                if (adminInfoExcel.getProvinceName() == null) throw new ServiceException("第" + (i + 2) + "行,省不能为空");
                if (adminInfoExcel.getCityName() == null) throw new ServiceException("第" + (i + 2) + "行,市不能为空");
                if (adminInfoExcel.getAreaName() == null) throw new ServiceException("第" + (i + 2) + "行,区/县不能为空");
                if (adminInfoExcel.getStreetName() == null) throw new ServiceException("第" + (i + 2) + "行,街道不能为空");
                if (adminInfoExcel.getAddress() == null) throw new ServiceException("第" + (i + 2) + "行,详细地址不能为空");
                if (adminInfoExcel.getPoliceStationName() == null)
                    throw new ServiceException("第" + (i + 2) + "行,派出所名称不能为空");
                if (adminInfoExcel.getPassword() == null) throw new ServiceException("第" + (i + 2) + "行,密码不能为空");
                if (adminInfoExcel.getTag() == null) throw new ServiceException("第" + (i + 2) + "行,所属部门不能为空");
                if (adminInfoExcel.getIsOut() == null) throw new ServiceException("第" + (i + 2) + "行,是否可以导出不能为空");
                if (adminInfoExcel.getIsHideImportant() == null) throw new ServiceException("第" + (i + 2) + "行,是否脱敏不能为空");
                if (adminInfoExcel.getIsControlEarlyWarning() == null) throw new ServiceException("第" + (i + 2) + "行,是否开启布控不能为空");

                AdminDTO adminDTO = new AdminDTO();
                if (adminInfoExcel.getType().equals("市级")) adminDTO.setType((byte) 4);
                else if (adminInfoExcel.getType().equals("区县级")) adminDTO.setType((byte) 5);
                else if (adminInfoExcel.getType().equals("省级")) adminDTO.setType((byte) 3);
                else throw new ServiceException("第" + (i + 2) + "行,账号级别有误");
                adminDTO.setUsername(adminInfoExcel.getUsername());
                adminDTO.setName(adminInfoExcel.getName());
                adminDTO.setPhone(adminInfoExcel.getPhone());

                AreaCode province = areaCodeDao.getAreaCode(adminInfoExcel.getProvinceName(), 0, null);
                if (province == null) throw new ServiceException("第" + (i + 2) + "行,请核对省的信息");
                adminDTO.setProvinceId(province.getId());

                AreaCode city = areaCodeDao.getAreaCode(adminInfoExcel.getCityName(), 1, province.getCode());
                if (city == null)
                    throw new ServiceException("第" + (i + 2) + "行," + province.getName() + "没有找到" + adminInfoExcel.getCityName());
                adminDTO.setCityId(city.getId());

                AreaCode area = areaCodeDao.getAreaCode(adminInfoExcel.getAreaName(), 2, city.getCode());
                if (area == null)
                    throw new ServiceException("第" + (i + 2) + "行," + province.getName() + adminInfoExcel.getCityName() + "没有找到" + adminInfoExcel.getAreaName());
                adminDTO.setAreaId(area.getId());

                AreaCode street = areaCodeDao.getAreaCode(adminInfoExcel.getStreetName(), 3, area.getCode());
                if (street == null)
                    throw new ServiceException("第" + (i + 2) + "行," + province.getName() + adminInfoExcel.getCityName() + adminInfoExcel.getAreaName() + "没有找到" + adminInfoExcel.getStreetName());
                adminDTO.setStreetId(street.getId());

                adminDTO.setAddress(adminInfoExcel.getAddress());
                adminDTO.setPoliceStationName(adminInfoExcel.getPoliceStationName());
                adminDTO.setPassword(adminInfoExcel.getPassword());

                AdminTag adminTag = new AdminTag();
                adminTag.setName(adminInfoExcel.getTag());
                adminTag.setProvinceId(province.getId());
                AdminTag at = adminTagDao.selectOne(adminTag);
                if (at == null) {
                    throw new ServiceException("第" + (i + 2) + "行,没有该所属部门");
                }
                adminDTO.setTagId(at.getId());
                adminDTO.setIsOut(adminInfoExcel.getIsOut().equals("可以") ? 1 : 2);
                adminDTO.setIsHideImportant(adminInfoExcel.getIsHideImportant().equals("脱敏") ? 1 : 2);
                adminDTO.setIsControlEarlyWarning(adminInfoExcel.getIsControlEarlyWarning().equals("开启") ? 1 : 2);
                adminDTO.setPoliceStationCode(adminInfoExcel.getPoliceStationCode());

                try {
                    this.editAdmin(adminDTO);
                } catch (Exception e) {
                    throw new ServiceException("第" + (i + 2) + "行," + e.getMessage());
                }
            } catch (ServiceException e) {
                list.add(e.getMessage());
                continue;
            }
        }
        datas.clear();//结束后销毁不用的资源
        return RestResponse.ok(list);
    }

    @Override
    public List<AdminVO> getAdminlist(JSONObject type) {
        if (type != null && !type.isEmpty()) {
            return adminDao.getAdminLsit(type.getInteger("type"));
        } else {
            AdminVO info = getInfo();
            return adminDao.getAdminlist(info);
        }
    }

    @Override
    public Boolean updateAdmin(AdminUpdate adminUpdate) {
        AdminVO info = this.getInfo();
        Admin admin = new Admin();
        admin.setId(info.getAdminId());
        admin.setNickname(adminUpdate.getName());
        admin.setPhone(adminUpdate.getPhone());
        if (StringUtils.hasText(adminUpdate.getPassword())) {
            admin.setPassword(PasswordUtils.buildPw(adminUpdate.getPassword()));
        }

        return adminDao.updateByPrimaryKeySelective(admin) == 1;
    }

    @Override
    public AdminVO showDataGetInfo(Integer userId) {
        Admin adminInfo = adminDao.selectByPrimaryKey(userId);
        if (adminInfo == null) {
            throw new ServiceException("无此用户信息");
        }
        AdminVO adminLoginVO = new AdminVO();
        adminLoginVO.setAdminId(userId);
        adminLoginVO.setUsername(adminInfo.getUsername());
        adminLoginVO.setType(adminInfo.getType());
        /*wxg 2021-11-4 增加省市区详细地址 开始*/
        adminLoginVO.setProvinceId(adminInfo.getProvinceId());
        adminLoginVO.setProvinceName(adminInfo.getProvinceName());
        adminLoginVO.setCityId(adminInfo.getCityId());
        adminLoginVO.setCityName(adminInfo.getCityName());
        adminLoginVO.setAreaId(adminInfo.getAreaId());
        adminLoginVO.setAreaName(adminInfo.getAreaName());
        adminLoginVO.setStreetId(adminInfo.getStreetId());
        adminLoginVO.setStreetName(adminInfo.getStreetName());

        return adminLoginVO;
    }

    @Override
    public AdminVO showDataGetInfo() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            throw new CommonException(RestCode.UNAUTHORIZED);
        }
        HttpServletRequest request = requestAttributes.getRequest();
        String token = request.getHeader("Authorization");
        if (token == null || token.equals("")) {
            throw new ServiceException(RestCode.UNAUTHORIZED.code, "缺少token");
        }
        token = JWTUtils.getUserId(token);
        if (org.apache.commons.lang3.StringUtils.isEmpty(token)) {
            throw new CommonException(RestCode.UNAUTHORIZED);
        }
        return showDataGetInfo(Integer.parseInt(token));
    }

    @Override
    public List<Long> getAdminListSearch(Map<String, Object> map) {
        return adminDao.getAdminListSearch(map);
    }

    @Override
    public List<AdminVO> getByAdminlist(List<Long> list) {
        return adminDao.getByAdminlist(list);
    }

}

