package com.sckw.manage.service;

import java.io.IOException;
import java.util.*;

import cn.hutool.core.date.DateUtil;
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.AddressDefaultTypeEnum;
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.EasyExcelUtil;
import com.sckw.manage.api.model.dto.res.EntAddressResDto;
import com.sckw.manage.dao.KwmAddressMapper;
import com.sckw.manage.dubbo.RemoteManageServiceImpl;
import com.sckw.manage.model.entity.KwmAddress;
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.model.dto.res.SysDictResDto;
import com.sckw.system.api.model.dto.res.UserCacheResDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

    @Autowired
    private KwmAddressMapper kwmAddressMapper;

    @Autowired
    private CommonBusinessService commonBusinessService;

    @Autowired
    private RemoteManageServiceImpl remoteManageService;
    /**
     * @param reqVo 分页入参
     * @return HttpResult
     * @desc: 分页查询
     * @author: czh
     * @date: 2023/7/12
     */
    public PageResult queryByPage(AddressQueryReqVo reqVo) {
        PageHelper.startPage(reqVo.getPage(), reqVo.getPageSize());
        List<KwmAddress> kwmAddressList = findList(reqVo);
        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) {
        LambdaQueryWrapper<KwmAddress> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Objects.nonNull(reqVo.getCityCode()), KwmAddress::getCityCode, reqVo.getCityCode()).
                eq(Objects.nonNull(reqVo.getType()), KwmAddress::getType, reqVo.getType()).
                eq(KwmAddress::getEntId, LoginUserHolder.getEntId()).
                eq(KwmAddress::getDelFlag, Global.NO).
                and(StringUtils.isNotBlank(reqVo.getKeywords()),
                        wq -> wq.like(KwmAddress::getDetailAddress, reqVo.getKeywords()).or().
                                like(KwmAddress::getCityName, reqVo.getKeywords())).
                orderByDesc(KwmAddress::getUpdateTime);

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

        if (Objects.nonNull(reqVo.getEndTime())) {
            wrapper.lt(KwmAddress::getCreateTime, DateUtil.offsetDay(reqVo.getEndTime(), 1));
        }

        if (StringUtils.isNotBlank(reqVo.getIds())) {
            wrapper.in(KwmAddress::getId, Arrays.stream(reqVo.getIds().split(Global.COMMA)).map(Long::parseLong).toList());
        }
        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();
        Map<Long, UserCacheResDto> userCacheResDtoMap = commonBusinessService.queryUserCacheMapByIds(userIds);

        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());
            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(AddressDefaultTypeEnum.getName(item.getDefaultType()).getName());
            }

            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)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.ADDRESS_NOT_EXISTS);
        }

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

        //相等则取消
        if (!defaultType.equals(AddressDefaultTypeEnum.NO.getCode())) {
            if (defaultType.equals(setDefaultType)) {
                kwmAddress.setDefaultType(AddressDefaultTypeEnum.NO.getCode());
            } else {
                kwmAddress.setDefaultType(AddressDefaultTypeEnum.BOTH.getCode());
            }

        }

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

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

        //当前是普通地址，需要把已设置的取消
        if (defaultType.equals(AddressDefaultTypeEnum.NO.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, AddressDefaultTypeEnum.BOTH.getCode()));
            List<KwmAddress> kwmAddressList = kwmAddressMapper.selectList(lambdaQueryWrapper);
            if (CollectionUtils.isNotEmpty(kwmAddressList)) {
                KwmAddress kwmAddress1 = kwmAddressList.get(0);
                if (kwmAddress1.getDefaultType().equals(AddressDefaultTypeEnum.BOTH.getCode())) {
                    if (setDefaultType.equals(AddressDefaultTypeEnum.SHIPMENT.getCode())) {
                        kwmAddress1.setDefaultType(AddressDefaultTypeEnum.TAKE.getCode());
                    }

                    if (setDefaultType.equals(AddressDefaultTypeEnum.TAKE.getCode())) {
                        kwmAddress1.setDefaultType(AddressDefaultTypeEnum.SHIPMENT.getCode());
                    }
                } else {
                    kwmAddress1.setDefaultType(AddressDefaultTypeEnum.NO.getCode());
                }
                kwmAddress1.setUpdateBy(userId);
                kwmAddress1.setUpdateTime(date);
                if (kwmAddressMapper.updateById(kwmAddress1) <= 0) {
                    throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
                }
            }
            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);
        }

        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) {
        LambdaQueryWrapper<KwmAddress> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KwmAddress::getName, reqVo.getName()).
                eq(KwmAddress::getDelFlag, Global.NO).
                eq(KwmAddress::getStatus, Global.NO).
                eq(KwmAddress::getEntId, LoginUserHolder.getEntId());
        if (kwmAddressMapper.selectCount(wrapper).compareTo((long) Global.NUMERICAL_ZERO) > 0) {
            throw new SystemException(HttpStatus.PARAMETERS_MISSING_CODE, HttpStatus.ADDRESS_EXISTS);
        }

        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(AddressDefaultTypeEnum.NO.getCode());
        kwmAddress.setId(new IdWorker(1L).nextId());
        if (kwmAddressMapper.insert(kwmAddress) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }
    }


    /**
     * @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) {
        List<KwmAddress> kwmAddressList = findList(reqVo);
        List<AddressQueryResVo> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(kwmAddressList)) {
            list = getAddressQueryResVo(kwmAddressList);
        }

        try {
            EasyExcelUtil.writeSingleExcel("地址管理.xlsx", "sheet1", list, AddressQueryResVo.class);
        } catch (IOException e) {
            log.error("导出失败:", e);
            throw new SystemException(HttpStatus.CODE_10301, HttpStatus.MSG_014);
        }
    }

    /**
     * @return AddressQueryResVo
     * @desc: 查企业下的地址
     * @param: reqVo 企业id
     * @author: czh
     * @date 2023/7/18
     */
    public List<AddressQueryResVo> queryByEnt(QueryByEntReqVo reqVo) {
        LambdaQueryWrapper<KwmAddress> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KwmAddress::getEntId, reqVo.getId());
        wrapper.eq(KwmAddress::getDelFlag, Global.NO);

        if (StringUtils.isNotBlank(reqVo.getCityName())) {
            wrapper.and(wp -> wp.like(KwmAddress::getCityName, reqVo.getCityName()).or().
                    like(KwmAddress::getDetailAddress, reqVo.getCityName()));
        }
        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;
    }

    public Map<Long, List<EntAddressResDto>> test(Long id) {
        return remoteManageService.queryEntAddressByEntIdList(Collections.singletonList(id));
    }
}
