package com.fdkankan.platform.agent.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fdkankan.common.constant.ConstantFilePath;
import com.fdkankan.common.constant.ErrorCode;
import com.fdkankan.common.constant.LoginType;
import com.fdkankan.common.constant.ServerCode;
import com.fdkankan.common.constant.TbStatus;
import com.fdkankan.common.exception.BusinessException;
import com.fdkankan.common.user.SSOLoginHelper;
import com.fdkankan.common.util.PasswordUtils;
import com.fdkankan.platform.agent.entity.Agent;
import com.fdkankan.platform.agent.mapper.IAgentMapper;
import com.fdkankan.platform.agent.request.RequestAgent;
import com.fdkankan.platform.agent.service.IAgentService;
import com.fdkankan.platform.agent.vo.AgentDetailTotalAmount;
import com.fdkankan.platform.agent.vo.AgentTotalAmountVo;
import com.fdkankan.platform.agent.vo.AgentVo;
import com.fdkankan.platform.agent.vo.ResponseAgentCamera;
import com.fdkankan.platform.common.ExcelUtil;
import com.fdkankan.platform.goods.entity.Camera;
import com.fdkankan.platform.goods.entity.CameraDetail;
import com.fdkankan.platform.goods.service.ICameraDetailService;
import com.fdkankan.platform.goods.service.ICameraService;
import com.fdkankan.platform.order.service.IVirtualOrderService;
import com.fdkankan.redis.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 代理商表 服务实现类
 * </p>
 *
 * @author
 * @since 2021-12-23
 */
@Service
public class AgentServiceImpl extends ServiceImpl<IAgentMapper, Agent> implements IAgentService {

    @Autowired
    SSOLoginHelper ssoLoginHelper;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    private ICameraService cameraService;
    @Autowired
    private IVirtualOrderService virtualOrderService;
    @Autowired
    private ICameraDetailService cameraDetailService;

    @Override
    public Agent getAgentById(String agentId) {
        QueryWrapper<Agent> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Agent::getAgentId,agentId);
        queryWrapper.lambda().eq(Agent::getTbStatus, TbStatus.VALID.code());
        List<Agent> list = this.list(queryWrapper);
        if(list == null || list.size()<=0){
            throw new BusinessException(ErrorCode.USER_NOT_EXIST);
        }
        return list.get(0);
    }

    @Override
    public JSONObject login(RequestAgent param) {
        if(param.getAgentId() == null || param.getAgentPassword() == null){
            throw new BusinessException(ErrorCode.MISSING_REQUIRED_PARAMETERS);
        }
        Agent agent = this.getAgentById(param.getAgentId());
        String encryptPwd = PasswordUtils.encrypt(param.getAgentId(), param.getAgentPassword(), PasswordUtils.getStaticSalt());
        if (!encryptPwd.equals(agent.getAgentPassword())){
            throw new BusinessException(ErrorCode.PASSWORD_ERROR);
        }
        String token = ssoLoginHelper.login(LoginType.AGENT.code(), agent.getAgentId());
        JSONObject obj = new JSONObject();
        obj.put("token", token);
        return obj;
    }

    @Override
    public Page<AgentVo> getPageList(RequestAgent param) {

        Page<Agent> agentPage = new Page<>();
        agentPage.setCurrent(param.getPageNum());
        agentPage.setSize(param.getPageSize());
        Page<Agent> page = this.page(agentPage, getQueryWrapper(param));

        List<AgentVo> agentVoList =page.getRecords().parallelStream().map(agent -> {
            AgentVo agentVo = new AgentVo();
            BeanUtils.copyProperties(agent, agentVo);
            return agentVo;
        }).collect(Collectors.toList());

        Page<AgentVo> agentVoPage = new Page<>();
        agentVoPage.setCurrent(agentPage.getCurrent());
        agentPage.setSize(agentPage.getSize());
        agentVoPage.setTotal(agentPage.getTotal());
        agentVoPage.setRecords(agentVoList);
        return agentVoPage;
    }

    @Override
    public String saveAgent(RequestAgent param) {
        saveOrUpdate(param);
        if (StringUtils.isNotBlank(param.getUploadFilePath())) {
            List<Map<String, String>> list = ExcelUtil.readExcelForManageAgent(param.getUploadFilePath());
            if (list != null && list.size() > 0) {
                for (Map<String, String> map : list) {
                    String childName = map.get("0");
                    if (org.apache.commons.lang3.StringUtils.isEmpty(childName) || !param.getAgentId().equals(map.get("4"))) {
                        continue;
                    }
                    Camera camera = cameraService.saveByAgent(childName, map.get("2"), param.getAgentId(), map.get("3"));
                    if(camera == null){
                        throw new BusinessException(ErrorCode.NOT_RECORD);
                    }
                    virtualOrderService.saveVirtualOrderByAgent(camera.getId());
                }
            }
        }
        return ServerCode.SUCCESS.message();
    }

    @Override
    public String deleteAgent(Long id) {
        if(!this.removeById(id)){
            throw new BusinessException(ErrorCode.ERROR_MSG);
        }
        return ServerCode.SUCCESS.message();
    }

    @Override
    public String updateAgentStatus(Long id, int status) {
        Agent agent = this.getById(id);
        if(agent == null){
            throw new BusinessException(ErrorCode.NOT_RECORD);
        }
        agent.setState(status);
        if(!this.saveOrUpdate(agent)){
            throw new BusinessException(ErrorCode.ERROR_MSG);
        }
        return ServerCode.SUCCESS.message();
    }

    @Override
    public Page<AgentVo> searchAgentList(RequestAgent param) {
        Page<AgentVo> pageList = this.getPageList(param);
        pageList.getRecords().forEach(agentVo -> {
            Integer count = cameraDetailService.getCountByAgentId(agentVo.getAgentId());
            agentVo.setRepertory(agentVo.getAgentNum() -count);
            virtualOrderService.getByStatusAndCameraId(agentVo, param.getStartDate(), param.getEndDate());
        });
        return pageList;
    }

    @Override
    public AgentTotalAmountVo searchAgentListStatistics(RequestAgent param) {
        if(redisUtil.hasKey("AgentSearchListTotalAmount")){
            String jsonObject = redisUtil.get("AgentSearchListTotalAmount");
            return JSONObject.parseObject(jsonObject, AgentTotalAmountVo.class);
        }
        List<Agent> list = this.list(getQueryWrapper(param));
        if(list == null || list.size()<=0){
            throw new BusinessException(ErrorCode.NOT_RECORD);
        }
        AgentTotalAmountVo totalAmountVo = new AgentTotalAmountVo();
        for (Agent agent : list) {
            Integer countByAgentId = cameraDetailService.getCountByAgentId(agent.getAgentId());
            AgentVo agentVo = new AgentVo();
            agentVo.setAgentId(agent.getAgentId());
            virtualOrderService.getByStatusAndCameraId(agentVo,param.getStartDate(),param.getEndDate());

            totalAmountVo.setTotalRepertory( totalAmountVo.getTotalRepertory() + (agent.getAgentNum() - countByAgentId));
            totalAmountVo.setTotalAgentNum(totalAmountVo.getTotalAgentNum() + agent.getAgentNum());
            totalAmountVo.setTotalSubExpend(totalAmountVo.getTotalSubExpend() + agentVo.getSubExpend());
            totalAmountVo.setTotalSubExtract(totalAmountVo.getTotalSubExtract() + agentVo.getSubExtract());
            totalAmountVo.setTotalSubRecharge(totalAmountVo.getTotalSubRecharge() + agentVo.getSubRecharge());
        }
        redisUtil.set("AgentSearchListTotalAmount",JSONObject.toJSONString(totalAmountVo),7200);
        return totalAmountVo;
    }

    @Override
    public Page<ResponseAgentCamera> searchAgentListDetail(RequestAgent param) {
        return  cameraDetailService.getPageByAgentId(param);
    }

    @Override
    public AgentDetailTotalAmount searchAgentListDetailStatistics(RequestAgent param) {
        if(redisUtil.hasKey("AgentSearchListDetailTotalAmount")){
            String jsonObject = redisUtil.get("AgentSearchListDetailTotalAmount");
            return JSONObject.parseObject(jsonObject, AgentDetailTotalAmount.class);
        }
        AgentDetailTotalAmount totalAmount = new AgentDetailTotalAmount();
        List<CameraDetail> detailList = cameraDetailService.getListByAgentId(param.getAgentId());
        for (CameraDetail entity : detailList) {
            Camera camera = cameraService.getById(entity.getCameraId());
            if(camera == null){
                continue;
            }
            ResponseAgentCamera vo = virtualOrderService.getPointsByCameraId(entity.getCameraId(), param.getStartDate(), param.getEndDate());
            totalAmount.setTotalCharge(totalAmount.getTotalCharge() + vo.getCharge() );
            totalAmount.setTotalExchangePoint(totalAmount.getTotalExchangePoint() + vo.getExchangePoint());
            totalAmount.setTotalLessPoint(totalAmount.getTotalLessPoint() + vo.getLessPoint());
            totalAmount.setTotalExtract(totalAmount.getTotalExtract().add(vo.getExtract()));
        }
        redisUtil.set("AgentSearchListTotalAmount",JSONObject.toJSONString(totalAmount),7200);
        return totalAmount;
    }

    @Override
    public String uploadFile(MultipartFile file) throws Exception{
        if (file.isEmpty()) {
            throw new BusinessException(ErrorCode.EMPTY_FILE);
        }
        File targetFile = new File(ConstantFilePath.AGENT_PATH);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        String fileName = file.getOriginalFilename();
        targetFile = new File(ConstantFilePath.AGENT_PATH + fileName);
        int count = 1;
        while (targetFile.exists()) {
            targetFile = new File(ConstantFilePath.AGENT_PATH + fileName.substring(0, fileName.lastIndexOf(".")) + "(" + count + ")" + fileName.substring(fileName.lastIndexOf(".")));
            ++count;
        }
        file.transferTo(targetFile);
        return ConstantFilePath.AGENT_PATH + targetFile.getName();
    }

    private QueryWrapper<Agent> getQueryWrapper(RequestAgent param){
        QueryWrapper<Agent> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Agent::getTbStatus,TbStatus.VALID.code());
        if(StringUtils.isNotBlank(param.getAgentName())){
            queryWrapper.lambda().like(Agent::getAgentName,param.getAgentName());
        }
        if(StringUtils.isNotBlank(param.getAgentId())){
            queryWrapper.lambda().like(Agent::getAgentId,param.getAgentId());
        }
        if(StringUtils.isNotBlank(param.getStartDate())){
            queryWrapper.lambda().between(Agent::getCreateTime,param.getStartDate()+" 00:00:00",param.getEndDate()+" 23:59:59");
        }
        queryWrapper.lambda().orderByDesc(Agent::getCreateTime);
        return queryWrapper;
    }


    private void saveOrUpdate(RequestAgent param){
        Agent agent = new Agent();
        agent.setId(param.getId());
        agent.setAgentId(param.getAgentId());
        agent.setAgentPassword(param.getAgentPassword());
        agent.setAgentName(param.getAgentName());
        agent.setAgentArea(param.getAgentArea());
        agent.setAgentEmail(param.getAgentEmail());
        agent.setAgentPhone(param.getAgentPhone());
        agent.setAgentCountry(param.getAgentCountry());
        agent.setAgentNum(param.getAgentNum());
        if(!this.saveOrUpdate(agent)){
            throw new BusinessException(ErrorCode.ERROR_MSG);
        }
    }


}
