/*
 * Copyright (c) 2024 codvision.com All Rights Reserved.
 */

package com.codvision.basic.service.impl.inspection;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.codvision.auth.entity.vo.SysUserVO;
import com.codvision.auth.support.UserContext;
import com.codvision.basic.entity.Address;
import com.codvision.basic.entity.Enterprise;
import com.codvision.basic.entity.Person;
import com.codvision.basic.entity.dto.InspectionTaskDTO;
import com.codvision.basic.entity.inspection.InspectionTarget;
import com.codvision.basic.entity.inspection.InspectionTask;
import com.codvision.basic.entity.inspection.InspectionTaskInventoryMapper;
import com.codvision.basic.entity.vo.inspection.InspectionTargetVO;
import com.codvision.basic.entity.vo.inspection.InspectionTaskVO;
import com.codvision.basic.mapper.AddressMapper;
import com.codvision.basic.mapper.EnterpriseMapper;
import com.codvision.basic.mapper.PersonMapper;
import com.codvision.basic.mapper.inspection.InspectionTargetMapper;
import com.codvision.basic.mapper.inspection.InspectionTaskInventoryMapperMapper;
import com.codvision.basic.mapper.inspection.InspectionTaskMapper;
import com.codvision.basic.service.inspection.InspectionTaskService;
import com.codvision.commoncore.utils.DateUtil;
import com.codvision.commoncore.utils.Preconditions;
import com.codvision.webcore.bean.QueryPage;
import com.codvision.webcore.util.QueryPageUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @author codvision
 */
@Service
@RequiredArgsConstructor
public class InspectionTaskServiceImpl extends ServiceImpl<InspectionTaskMapper, InspectionTask> implements InspectionTaskService {

    private final InspectionTaskInventoryMapperMapper taskInventoryMapperMapper;
    private final InspectionTargetMapper inspectionTargetMapper;
    private final PersonMapper personMapper;
    private final AddressMapper addressMapper;
    private final EnterpriseMapper enterpriseMapper;

    @Override
    public IPage<InspectionTaskVO> getPageResult(QueryPage<Map<String, Object>> queryPage) {
        SysUserVO user = UserContext.get();
        IPage<InspectionTaskVO> pageResult = getBaseMapper().getPageResult(queryPage.getPage(), QueryPageUtil.queryMap(queryPage));
        List<InspectionTaskVO> records = pageResult.getRecords();
        if (CollectionUtils.isNotEmpty(records)) {
            for (InspectionTaskVO task : records) {
                Map<String, Object> param = new HashMap<>(16);
                param.put("taskId", task.getId());
                param.put("oid", user.getActiveOid());
                Date startTime = DateUtil.toDate(task.getStartTime());
                Date endTime = DateUtil.toDate(task.getEndTime());
                Date nowTime = new Date();
                if (nowTime.after(endTime)) {
                    nowTime = endTime;
                }
                param.put("nowTime", DateUtil.sdf(nowTime));
                param.put("startTime", DateUtil.sdf(startTime));
                Map<String, Integer> map = getBaseMapper().getTargetCount(param);
                task.setAll(Integer.valueOf(String.valueOf(map.get("all"))));
                task.setChecked(Integer.valueOf(String.valueOf(map.get("checked"))));
                task.setUnChecked(Integer.valueOf(String.valueOf(map.get("unchecked"))));
            }
        }
        return pageResult;
    }

    @Override
    public IPage<InspectionTargetVO> getTargets(QueryPage<Map<String, Object>> queryPage) {
        Map<String, Object> paraMap = QueryPageUtil.queryMap(queryPage);
        Integer taskId = (Integer) paraMap.get("taskId");
        Preconditions.checkArgument(taskId!= null, "taskId不能为空");

        InspectionTask task = getBaseMapper().selectById(taskId);
        Preconditions.checkArgument(task != null, "检查任务不存在");

        Integer checked = (Integer) paraMap.get("checked");
        if (checked != null) {
            Date startTime = DateUtil.toDate(task.getStartTime());
            Date endTime = DateUtil.toDate(task.getEndTime());
            Date nowTime = new Date();
            if (nowTime.after(endTime)) {
                nowTime = endTime;
            }

            paraMap.put("startTime", DateUtil.sdf(startTime));
            paraMap.put("nowTime", DateUtil.sdf(nowTime));
        }

        return getBaseMapper().getTargets(queryPage.getPage(), paraMap);
    }

    @Override
    public Map<String, Integer> getTargetCount(Integer taskId, String checkTag, String oid) {
        Preconditions.checkArgument(taskId!= null, "taskId不能为空");
        Map<String, Object> params = new HashMap<>(16);
        params.put("taskId", taskId);
        if (StringUtils.isNotBlank(oid)) {
            params.put("oid", oid);
        }

        InspectionTask task = getBaseMapper().selectById(taskId);
        Date endTime = DateUtil.toDate(task.getEndTime());
        Date startTime = DateUtil.toDate(task.getStartTime());
        Date nowTime = new Date();
        if (nowTime.after(endTime)) {
            nowTime = endTime;
        }
        params.put("startTime", DateUtil.sdf(startTime));
        params.put("nowTime", DateUtil.sdf(nowTime));
        if (StringUtils.isNotBlank(checkTag)) {
            params.put("checkTag", checkTag);
        }

        return getBaseMapper().getTargetCount(params);
    }

    @Override
    public Map<String, Integer> getTaskCount() {
        return getBaseMapper().getTaskCount();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int add(InspectionTaskDTO inspectionTaskDTO) {
        InspectionTask inspectionTask = new InspectionTask();
        BeanUtils.copyProperties(inspectionTaskDTO, inspectionTask);
        getBaseMapper().insert(inspectionTask);
        if (Strings.isNotEmpty(inspectionTaskDTO.getInventoryList())) {
            String[] split = inspectionTaskDTO.getInventoryList().split(",");
            for (String s : split) {
                InspectionTaskInventoryMapper inventoryMapper = new InspectionTaskInventoryMapper();
                inventoryMapper.setInventoryId(Integer.valueOf(s));
                inventoryMapper.setTaskId(inspectionTask.getId());
                taskInventoryMapperMapper.insert(inventoryMapper);
            }
        }
        if ("PERSON".equals(inspectionTaskDTO.getCategory()) && StringUtils.isNotEmpty(inspectionTaskDTO.getCheckTag())) {
            // 人员类型
            addPersonInspectionTarget(inspectionTask.getId(), inspectionTaskDTO.getCheckTag());
        } else if ("ADDRESS".equals(inspectionTask.getCategory())  && StringUtils.isNotEmpty(inspectionTaskDTO.getCheckTag())) {
            // 地址
            addAddressInspectionTarget(inspectionTask.getId(), inspectionTaskDTO.getCheckTag());
        } else if ("ENTERPRISE".equals(inspectionTask.getCategory()) && StringUtils.isNotEmpty(inspectionTaskDTO.getCheckTag())) {
            // 企业
            addEnterpriseInspectionTarget(inspectionTask.getId(), inspectionTaskDTO.getCheckTag());
        }
        return inspectionTask.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTask(InspectionTaskDTO inspectionTaskDTO) {
        InspectionTask inspectionTask = new InspectionTask();
        BeanUtils.copyProperties(inspectionTaskDTO, inspectionTask);
        getBaseMapper().updateById(inspectionTask);
        if (Strings.isNotEmpty(inspectionTaskDTO.getInventoryList())) {
            taskInventoryMapperMapper.delete(Wrappers.<InspectionTaskInventoryMapper>lambdaQuery().eq(InspectionTaskInventoryMapper::getTaskId, inspectionTask.getId()));
            String[] split = inspectionTaskDTO.getInventoryList().split(",");
            for (String s : split) {
                InspectionTaskInventoryMapper inventoryMapper = new InspectionTaskInventoryMapper();
                inventoryMapper.setInventoryId(Integer.valueOf(s));
                inventoryMapper.setTaskId(inspectionTask.getId());
                taskInventoryMapperMapper.insert(inventoryMapper);
            }
        }
        if ("PERSON".equals(inspectionTaskDTO.getCategory()) && StringUtils.isNotEmpty(inspectionTaskDTO.getCheckTag())) {
            // 人员类型
            addPersonInspectionTarget(inspectionTask.getId(), inspectionTaskDTO.getCheckTag());
        } else if ("ADDRESS".equals(inspectionTask.getCategory())  && StringUtils.isNotEmpty(inspectionTaskDTO.getCheckTag())) {
            // 地址
            addAddressInspectionTarget(inspectionTask.getId(), inspectionTaskDTO.getCheckTag());
        } else if ("ENTERPRISE".equals(inspectionTask.getCategory()) && StringUtils.isNotEmpty(inspectionTaskDTO.getCheckTag())) {
            // 企业
            addEnterpriseInspectionTarget(inspectionTask.getId(), inspectionTaskDTO.getCheckTag());
        }
    }

    /**
     * 增加人员检查对象
     * @param taskId 检查任务id
     * @param tagList 检查标签
     */
    public void addPersonInspectionTarget(Integer taskId, String tagList) {
        List<Person> personList = personMapper.getPersonInspectionTarget(UserContext.get().getActiveOid(), tagList);
        for (Person person : personList) {
            InspectionTarget exist = inspectionTargetMapper.selectOne(Wrappers.<InspectionTarget>lambdaQuery().eq(InspectionTarget::getTargetCode, person.getIdCard()).eq(InspectionTarget::getTaskId, taskId));
            if (exist == null) {
                InspectionTarget inspectionTarget = new InspectionTarget();
                inspectionTarget = updateInspectionTarget(inspectionTarget, person);
                inspectionTarget.setTaskId(taskId);
                inspectionTargetMapper.insert(inspectionTarget);
            } else {
                exist = updateInspectionTarget(exist, person);
                exist.setTaskId(taskId);
                inspectionTargetMapper.updateById(exist);
            }
        }
    }

    /**
     * 增加地址库检查对象
     * @param taskId 检查任务id
     * @param tagList 检查标签
     */
    public void addAddressInspectionTarget(Integer taskId, String tagList) {
        List<Address> addressList = addressMapper.getAddressInspectionTarget(UserContext.get().getActiveOid(), tagList);
        for (Address address : addressList) {
            InspectionTarget exist = inspectionTargetMapper.selectOne(Wrappers.<InspectionTarget>lambdaQuery().eq(InspectionTarget::getTargetCode, address.getAddressCode()).eq(InspectionTarget::getTaskId, taskId));
            if (exist == null) {
                InspectionTarget inspectionTarget = new InspectionTarget();
                inspectionTarget = updateInspectionTarget(inspectionTarget, address);
                inspectionTarget.setTaskId(taskId);
                inspectionTargetMapper.insert(inspectionTarget);
            } else {
                exist = updateInspectionTarget(exist, address);
                exist.setTaskId(taskId);
                inspectionTargetMapper.updateById(exist);
            }
        }
    }

    /**
     * 增加企业组织检查对象
     * @param taskId 检查任务id
     * @param tagList 检查标签
     */
    public void addEnterpriseInspectionTarget(Integer taskId, String tagList) {
        List<Enterprise> enterpriseList = enterpriseMapper.getEnterpriseInspectionTarget(UserContext.get().getActiveOid(), tagList);
        for (Enterprise enterprise : enterpriseList) {
            InspectionTarget exist = inspectionTargetMapper.selectOne(Wrappers.<InspectionTarget>lambdaQuery().eq(InspectionTarget::getTargetCode, enterprise.getCreditCode()).eq(InspectionTarget::getTaskId, taskId));
            if (exist == null) {
                InspectionTarget inspectionTarget = new InspectionTarget();
                inspectionTarget = updateInspectionTarget(inspectionTarget, enterprise);
                inspectionTarget.setTaskId(taskId);
                inspectionTargetMapper.insert(inspectionTarget);
            } else {
                exist = updateInspectionTarget(exist, enterprise);
                exist.setTaskId(taskId);
                inspectionTargetMapper.updateById(exist);
            }
        }
    }

    public InspectionTarget updateInspectionTarget(InspectionTarget inspectionTarget, Person person) {
        inspectionTarget.setFlagActive(1);
        inspectionTarget.setCategory("PERSON");
        inspectionTarget.setDataSource("1");
        inspectionTarget.setTargetName(person.getName());
        inspectionTarget.setTargetCode(person.getIdCard());
        inspectionTarget.setTargetAddress(person.getInhabitedAddress());
        inspectionTarget.setTargetAlias(person.getUsedName());
        inspectionTarget.setOid(person.getOid());
        inspectionTarget.setRemark(person.getRemark());
        inspectionTarget.setMobile(person.getPhone());
        inspectionTarget.setTagIdList(person.getPersonTags());
        return inspectionTarget;
    }

    public InspectionTarget updateInspectionTarget(InspectionTarget inspectionTarget, Address address) {
        inspectionTarget.setFlagActive(1);
        inspectionTarget.setCategory("ADDRESS");
        inspectionTarget.setDataSource("1");
        inspectionTarget.setTargetName(address.getSourceAddress());
        inspectionTarget.setTargetAddress(address.getSourceAddress());
        inspectionTarget.setTargetCode(address.getAddressCode());
        inspectionTarget.setTargetAlias(address.getSourceAddress());
        inspectionTarget.setOid(address.getOid());
        inspectionTarget.setRemark(address.getRemark());
        inspectionTarget.setTagIdList(address.getAddressTags());
        return inspectionTarget;
    }
    public InspectionTarget updateInspectionTarget(InspectionTarget inspectionTarget, Enterprise enterprise) {
        inspectionTarget.setFlagActive(1);
        inspectionTarget.setCategory("ENTERPRISE");
        inspectionTarget.setDataSource("1");
        inspectionTarget.setTargetName(enterprise.getName());
        inspectionTarget.setTargetCode(enterprise.getCreditCode());
        inspectionTarget.setTargetAddress(enterprise.getSourceAddress());
        inspectionTarget.setTargetAlias(enterprise.getName());
        inspectionTarget.setOid(enterprise.getOid());
        inspectionTarget.setRemark(enterprise.getRemark());
        inspectionTarget.setTagIdList(enterprise.getEnterpriseTags());
        inspectionTarget.setLegalPersonName(enterprise.getLegalPersonName());
        inspectionTarget.setLegalPersonPhone(enterprise.getLegalPersonPhone());
        return inspectionTarget;
    }
}
