package com.sckw.manage.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sckw.core.common.enums.enums.DictTypeEnum;
import com.sckw.core.exception.SystemException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.AddressTypeEnum;
import com.sckw.core.model.enums.SystemTypeEnum;
import com.sckw.core.model.page.PageHelperUtil;
import com.sckw.core.model.page.PageResult;
import com.sckw.core.utils.BeanUtils;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.IdWorker;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.excel.utils.ExcelUtil;
import com.sckw.manage.dao.KwmAddressMapper;
import com.sckw.manage.model.entity.KwmAddress;
import com.sckw.manage.model.report.AddressQueryExport;
import com.sckw.manage.model.vo.req.*;
import com.sckw.manage.model.vo.res.AddressDetailResVo;
import com.sckw.manage.model.vo.res.AddressQueryResVo;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.RemoteUserService;
import com.sckw.system.api.model.dto.res.AreaTreeFrontResDto;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.system.api.model.dto.res.SysDictResDto;
import com.sckw.system.api.model.dto.res.UserCacheResDto;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author czh
 * @desc 地址管理service
 * @date 2023/7/10
 */
@Slf4j
@Service
public class KwmAddressService {

    @Autowired
    private KwmAddressMapper kwmAddressMapper;

    @Autowired
    private CommonBusinessService commonBusinessService;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteUserService remoteUserService;


    /**
     * @param reqVo 分页入参
     * @return HttpResult
     * @desc: 分页查询
     * @author: czh
     * @date: 2023/7/12
     */
    public PageResult queryByPage(AddressQueryReqVo reqVo) {
        Integer cityCode = reqVo.getCityCode();
        List<Integer> cityCodeList = new ArrayList<>();
        if (Objects.nonNull(cityCode)) {
            cityCodeList.add(cityCode);
            List<AreaTreeFrontResDto> allArea = remoteUserService.findAllArea(cityCode);
            if (CollectionUtils.isNotEmpty(allArea)) {
                cityCodeList.addAll(allArea.stream().map(AreaTreeFrontResDto::getCode).distinct().toList());
            }
        }
        reqVo.setCityCodeList(cityCodeList);
        PageHelper.startPage(reqVo.getPage(), reqVo.getPageSize());

        //新增客户经理权限过滤
        List<Long> authEntIdList = new ArrayList<>();
        if (SystemTypeEnum.MANAGE.getCode().equals(String.valueOf(LoginUserHolder.getSystemType()))) {
            authEntIdList = LoginUserHolder.getAuthEntIdList();
            if (CollectionUtils.isEmpty(authEntIdList)) {
                List<Long> ids = remoteUserService.findEnterpriseIdsByUserIdIsMain(LoginUserHolder.getUserId());
                if (CollectionUtils.isEmpty(ids)) {
                    PageHelperUtil.getPageResult(new PageInfo<KwmAddress>(), new ArrayList<>(), reqVo.getPageSize());
                }
                authEntIdList.addAll(ids);
            }
        }

        List<KwmAddress> kwmAddressList = findList(reqVo, authEntIdList);
        if (CollectionUtils.isEmpty(kwmAddressList)) {
            return PageHelperUtil.getPageResult(new PageInfo<>());
        }
        List<AddressQueryResVo> list = getAddressQueryResVo(kwmAddressList);
        return PageHelperUtil.getPageResult(new PageInfo<>(list), kwmAddressList, reqVo.getPageSize());
    }

    /**
     * @param reqVo 分页入参
     * @return KwmAddress
     * @desc: 全量查询
     * @author: czh
     * @date: 2023/7/12
     */
    private List<KwmAddress> findList(AddressQueryReqVo reqVo, List<Long> authEntIdList) {
        LambdaQueryWrapper<KwmAddress> wrapper = new LambdaQueryWrapper<>();
        if (CollectionUtils.isNotEmpty(authEntIdList)) {
            wrapper.in(KwmAddress::getEntId, authEntIdList);
        }
        wrapper.in(Objects.nonNull(reqVo.getCityCode()), KwmAddress::getCityCode, reqVo.getCityCodeList()).
                eq(Objects.nonNull(reqVo.getType()), KwmAddress::getType, reqVo.getType()).
                eq(KwmAddress::getDelFlag, Global.NO).
                and(StringUtils.isNotBlank(reqVo.getKeywords()),
                        wq -> wq.like(KwmAddress::getDetailAddress, reqVo.getKeywords()).or().
                                like(KwmAddress::getName, reqVo.getKeywords()).or().
                                like(KwmAddress::getContacts, reqVo.getKeywords()).or().
                                like(KwmAddress::getPhone, reqVo.getKeywords())).
                orderByDesc(KwmAddress::getUpdateTime);

        if (Objects.nonNull(reqVo.getStartTime())) {
            wrapper.ge(KwmAddress::getCreateTime, reqVo.getStartTime());
        }

        if (Objects.nonNull(reqVo.getEndTime())) {
            wrapper.le(KwmAddress::getCreateTime, reqVo.getEndTime());
        }

        if (StringUtils.isNotBlank(reqVo.getIds())) {
            wrapper.in(KwmAddress::getId, StringUtils.splitStrToList(reqVo.getIds(), Long.class));
        }

        if (!Objects.equals(LoginUserHolder.getSystemType(), SystemTypeEnum.MANAGE.getCode())) {
            wrapper.eq(KwmAddress::getEntId, LoginUserHolder.getEntId());
        }

        return kwmAddressMapper.selectList(wrapper);
    }


    /**
     * @return AddressQueryResVo
     * @desc: 转换成vo
     * @param: kwmAddresses 实体
     * @author: czh
     * @date 2023/7/18
     */
    private List<AddressQueryResVo> getAddressQueryResVo(List<KwmAddress> kwmAddresses) {
        List<AddressQueryResVo> list = new ArrayList<>();
        List<Long> userIds = kwmAddresses.stream().map(KwmAddress::getCreateBy).distinct().toList();
        List<Integer> types = kwmAddresses.stream().map(KwmAddress::getType).distinct().toList();
        List<Long> endIds = kwmAddresses.stream().map(KwmAddress::getEntId).distinct().toList();
        Map<Long, UserCacheResDto> userCacheResDtoMap = commonBusinessService.queryUserCacheMapByIds(userIds);
        Map<Long, EntCacheResDto> entCacheResDtoMap = commonBusinessService.queryEntCacheMapByIds(endIds);
        StringBuilder keys = new StringBuilder();
        for (Integer type : types) {
            keys.append(DictTypeEnum.ADDRESS_TYPE.getType()).append(Global.POUND).append(type).append(Global.COMMA);
        }

        Map<String, SysDictResDto> stringSysDictResDtoMap = commonBusinessService.queryDictMapByTypeValues(keys.toString());

        kwmAddresses.forEach(item -> {
            AddressQueryResVo addressQueryResVo = new AddressQueryResVo();
            BeanUtils.copyProperties(item, addressQueryResVo);
            addressQueryResVo.setType(item.getType());
            UserCacheResDto userCacheResDto = userCacheResDtoMap.get(item.getCreateBy());
            SysDictResDto sysDictResDto = stringSysDictResDtoMap.get(DictTypeEnum.ADDRESS_TYPE.getType() + Global.POUND + item.getType());
            EntCacheResDto entCacheResDto = entCacheResDtoMap.get(item.getEntId());
            if (Objects.nonNull(sysDictResDto)) {
                addressQueryResVo.setTypeName(sysDictResDto.getLabel());
            }

            if (Objects.nonNull(userCacheResDto)) {
                addressQueryResVo.setCreateByName(userCacheResDto.getName());
            }

            if (Objects.nonNull(sysDictResDto)) {
                addressQueryResVo.setTypeName(sysDictResDto.getLabel());
            }

            if (Objects.nonNull(item.getDefaultType())) {
                addressQueryResVo.setDefaultTypeName(AddressTypeEnum.getName(item.getDefaultType()).getName());
            }

            if (Objects.nonNull(entCacheResDto)) {
                addressQueryResVo.setEntName(entCacheResDto.getFirmName());
            }

            addressQueryResVo.setFenceStatus(StringUtils.isNotBlank(item.getFence()) ? "已设置" : "未设置");
            list.add(addressQueryResVo);
        });
        return list;
    }

    /**
     * @param reqVo 默认地址入参
     * @desc: 设置默认地址
     * @author: czh
     * @date: 2023/7/12
     */
    @Transactional(rollbackFor = {})
    public void bindDefault(BindDefaultReqVo reqVo) {
        KwmAddress kwmAddress = kwmAddressMapper.selectById(reqVo.getId());
        if (Objects.isNull(kwmAddress) || kwmAddress.getDelFlag().equals(Global.YES)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.ADDRESS_NOT_EXISTS);
        }


        Long entId = kwmAddress.getEntId();
        Long userId = LoginUserHolder.getUserId();
        Date date = new Date();
        Integer defaultType = kwmAddress.getDefaultType();
        Integer setDefaultType = reqVo.getDefaultType();

        //当前是收货或者卸货
        if (!defaultType.equals(AddressTypeEnum.NO.getCode()) && !defaultType.equals(AddressTypeEnum.BOTH.getCode())) {
            if (defaultType.equals(setDefaultType)) {
                //相等则取消
                kwmAddress.setDefaultType(AddressTypeEnum.NO.getCode());
            } else {
                kwmAddress.setDefaultType(AddressTypeEnum.BOTH.getCode());
            }

        }

        //当前是收货也是卸货
        if (defaultType.equals(AddressTypeEnum.BOTH.getCode())) {
            if (setDefaultType.equals(AddressTypeEnum.SHIPMENT.getCode())) {
                kwmAddress.setDefaultType(AddressTypeEnum.TAKE.getCode());
            }

            if (setDefaultType.equals(AddressTypeEnum.TAKE.getCode())) {
                kwmAddress.setDefaultType(AddressTypeEnum.SHIPMENT.getCode());
            }
        }

        //需要把已设置的取消
        LambdaQueryWrapper<KwmAddress> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(KwmAddress::getEntId, entId).
                eq(KwmAddress::getDelFlag, Global.NO).
                and(wp -> wp.eq(KwmAddress::getDefaultType, setDefaultType).or().
                        eq(KwmAddress::getDefaultType, AddressTypeEnum.BOTH.getCode()));
        List<KwmAddress> kwmAddressList = kwmAddressMapper.selectList(lambdaQueryWrapper);
        if (CollectionUtils.isNotEmpty(kwmAddressList)) {
            KwmAddress kwmAddress1 = kwmAddressList.get(0);
            if (kwmAddress1.getDefaultType().equals(AddressTypeEnum.BOTH.getCode())) {
                if (setDefaultType.equals(AddressTypeEnum.SHIPMENT.getCode())) {
                    kwmAddress1.setDefaultType(AddressTypeEnum.TAKE.getCode());
                }

                if (setDefaultType.equals(AddressTypeEnum.TAKE.getCode())) {
                    kwmAddress1.setDefaultType(AddressTypeEnum.SHIPMENT.getCode());
                }
            } else {
                kwmAddress1.setDefaultType(AddressTypeEnum.NO.getCode());
            }
            kwmAddress1.setUpdateBy(userId);
            kwmAddress1.setUpdateTime(date);
            if (kwmAddressMapper.updateById(kwmAddress1) <= 0) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
            }
        }

        if (defaultType.equals(AddressTypeEnum.NO.getCode())) {
            kwmAddress.setDefaultType(setDefaultType);
        }

        kwmAddress.setUpdateBy(userId);
        kwmAddress.setUpdateTime(date);
        if (kwmAddressMapper.updateById(kwmAddress) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }

    }


    /**
     * @param reqVo 修改入参
     * @desc: 修改地址信息
     * @author: czh
     * @date: 2023/7/12
     */
    public void update(AddressUpdateReqVo reqVo) {
        KwmAddress kwmAddress = kwmAddressMapper.selectById(reqVo.getId());
        if (Objects.isNull(kwmAddress)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.ADDRESS_NOT_EXISTS);
        }

        checkAddressRepeat(reqVo.getName(), reqVo.getDetailAddress(), kwmAddress.getId());

        BeanUtils.copyProperties(reqVo, kwmAddress);
        if (kwmAddressMapper.updateById(kwmAddress) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }

    }


    /**
     * @param reqVo 新增入参
     * @desc: 新增地址
     * @author: czh
     * @date: 2023/7/12
     */
    @Transactional(rollbackFor = {})
    public void add(AddressAddReqVo reqVo) {
        checkAddressRepeat(reqVo.getName(), reqVo.getDetailAddress(), null);
        KwmAddress kwmAddress = new KwmAddress();
        BeanUtils.copyProperties(reqVo, kwmAddress);
        Long userId = LoginUserHolder.getUserId();
        Date date = new Date();
        kwmAddress.setDelFlag(Global.NO);
        kwmAddress.setEntId(LoginUserHolder.getEntId());
        kwmAddress.setStatus(Global.NO);
        kwmAddress.setCreateBy(userId);
        kwmAddress.setUpdateBy(userId);
        kwmAddress.setCreateTime(date);
        kwmAddress.setUpdateTime(date);
        kwmAddress.setDefaultType(AddressTypeEnum.NO.getCode());
        kwmAddress.setId(new IdWorker(1L).nextId());
        if (kwmAddressMapper.insert(kwmAddress) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }
    }

    private void checkAddressRepeat(String name, String detailAddress, Long id) {
        LambdaQueryWrapper<KwmAddress> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KwmAddress::getDelFlag, Global.NO).
                eq(KwmAddress::getStatus, Global.NO).
                eq(KwmAddress::getEntId, LoginUserHolder.getEntId())
                .and(wp -> wp.eq(KwmAddress::getName, name)
                );
        List<KwmAddress> kwmAddressList = kwmAddressMapper.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(kwmAddressList) && Objects.isNull(id)) {
            throw new SystemException(HttpStatus.CODE_10301, HttpStatus.MSG_035);
        }

        if (CollectionUtils.isNotEmpty(kwmAddressList) && Objects.nonNull(id)) {
            List<KwmAddress> kwmAddressList1 = kwmAddressList.stream().filter(item -> !item.getId().equals(id)).toList();
            if (CollectionUtils.isNotEmpty(kwmAddressList1)) {
                throw new SystemException(HttpStatus.CODE_10301, HttpStatus.MSG_035);
            }
        }
    }


    /**
     * @param ids 主键
     * @desc: 删除
     * @author: czh
     * @date: 2023/7/12
     */
    @Transactional(rollbackFor = {})
    public void delete(String ids) {
        List<Long> idList = Arrays.stream(ids.split(Global.COMMA)).map(Long::parseLong).toList();
        List<KwmAddress> kwmAddresses = kwmAddressMapper.selectBatchIds(idList);
        if (CollectionUtils.isEmpty(kwmAddresses)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.ADDRESS_NOT_EXISTS);
        }

        Long userId = LoginUserHolder.getUserId();
        Date date = new Date();
        kwmAddresses.forEach(item -> {
            item.setUpdateTime(date);
            item.setUpdateBy(userId);
            item.setDelFlag(Global.YES);

            if (kwmAddressMapper.updateById(item) <= 0) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.DELETE_FAIL);
            }
        });
    }


    /**
     * @param reqVo 查询入参
     * @desc: 导出
     * @author: czh
     * @date: 2023/7/12
     */
    public void export(AddressQueryReqVo reqVo, HttpServletResponse response) {

        //新增客户经理权限过滤
        List<Long> authEntIdList = new ArrayList<>();
        if (SystemTypeEnum.MANAGE.getCode().equals(String.valueOf(LoginUserHolder.getSystemType()))) {
            authEntIdList = LoginUserHolder.getAuthEntIdList();
            if (CollectionUtils.isEmpty(authEntIdList)) {
                List<Long> ids = remoteUserService.findEnterpriseIdsByUserIdIsMain(LoginUserHolder.getUserId());
                if (CollectionUtils.isEmpty(ids)) {
                    PageHelperUtil.getPageResult(new PageInfo<KwmAddress>(), new ArrayList<>(), reqVo.getPageSize());
                }
                authEntIdList.addAll(ids);
            }
        }
        List<KwmAddress> kwmAddressList = findList(reqVo, authEntIdList);
        if (CollectionUtils.isEmpty(kwmAddressList)) {
            throw new SystemException(HttpStatus.SUCCESS_CODE, "暂无数据，请确认！");
        }
        List<AddressQueryResVo> list = getAddressQueryResVo(kwmAddressList);
        ExcelUtil.downData(response, AddressQueryExport.class, BeanUtils.copyToList(list, AddressQueryExport.class));
    }

    /**
     * @return AddressQueryResVo
     * @desc: 查企业下的地址
     * @param: reqVo 企业id
     * @author: czh
     * @date 2023/7/18
     */
    public List<AddressQueryResVo> queryByEnt(QueryByEntReqVo reqVo) {
        Map<Long, EntCacheResDto> entCacheResDtos = remoteSystemService.queryEntTreeByIds(Collections.singletonList(reqVo.getId()));
        if (entCacheResDtos.isEmpty()) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.ENT_NOT_EXISTS);
        }

        EntCacheResDto entCacheResDto = entCacheResDtos.get(reqVo.getId());
        if (Objects.isNull(entCacheResDto)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.ENT_NOT_EXISTS);
        }

        LambdaQueryWrapper<KwmAddress> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KwmAddress::getDelFlag, Global.NO);
        wrapper.eq(KwmAddress::getEntId, entCacheResDto.getId());
        if (StringUtils.isNotBlank(reqVo.getName())) {
            wrapper.like(KwmAddress::getName, reqVo.getName());
        }
        if (StringUtils.isNotBlank(reqVo.getCityName())) {
            wrapper.and(wp -> wp.like(KwmAddress::getCityName, reqVo.getCityName()).or().
                    like(KwmAddress::getDetailAddress, reqVo.getCityName()));
        }

        if (Objects.nonNull(reqVo.getDefaultType())) {
            wrapper.and(wp -> wp.eq(KwmAddress::getDefaultType, Global.NUMERICAL_THREE).or().
                    eq(KwmAddress::getDefaultType, reqVo.getDefaultType()));
        }
        List<KwmAddress> kwmAddresses = kwmAddressMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(kwmAddresses)) {
            return Collections.emptyList();
        }
        return getAddressQueryResVo(kwmAddresses);
    }

    /**
     * @param id 主键
     * @return AddressDetailResVo
     * @desc: 查详情
     * @author: czh
     * @date: 2023/7/25
     */
    public AddressDetailResVo detail(Long id) {
        KwmAddress kwmAddress = kwmAddressMapper.selectById(id);
        if (Objects.isNull(kwmAddress) || kwmAddress.getDelFlag().equals(Global.YES)) {
            return null;
        }

        AddressDetailResVo addressDetailResVo = new AddressDetailResVo();
        BeanUtils.copyProperties(kwmAddress, addressDetailResVo);
        return addressDetailResVo;
    }

    /**
     * @desc 根据id及企业id查询未删除的地址信息
     * @param name
     * @param entId
     * @return com.sckw.manage.model.entity.KwmAddress
     * @author yzc
     * @date 2024/3/1 10:53
     */
    public KwmAddress getByNameAndEntId(String name, Long entId) {
        LambdaQueryWrapper<KwmAddress> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KwmAddress::getName, name)
                .eq(KwmAddress::getEntId, entId)
                .eq(KwmAddress::getDelFlag, Global.NO)
                .last("LIMIT 1");
        return kwmAddressMapper.selectOne(wrapper);
    }
}
