package com.sckw.manage.service;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageInfo;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.model.constant.Global;
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.CollectionUtils;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.HttpResult;
import com.sckw.excel.utils.DateUtil;
import com.sckw.manage.dao.KwmLineFreightRateMapper;
import com.sckw.manage.model.entity.KwmAddress;
import com.sckw.manage.model.entity.KwmLineFreightRate;
import com.sckw.manage.model.vo.req.*;
import com.sckw.manage.model.vo.res.LineFreightRateDetail;
import com.sckw.manage.model.vo.res.LineFreightRateExport;
import com.sckw.manage.model.vo.res.LineFreightRateFindListResVO;
import com.sckw.manage.model.vo.res.LineFreightRateListResVO;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.RemoteUserService;
import com.sckw.system.api.model.dto.res.UserCacheResDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author: yzc
 * @date: 2024-03-01  09:18
 * @desc: 路径service
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class KwmLineFreightRateService {

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

    private final KwmLineFreightRateMapper lineFreightRateMapper;
    private final KwmAddressService addressService;

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

    /**
     * @param addLineFreightRateParam
     * @return void
     * @desc 新增路径
     * @author yzc
     * @date 2024/3/1 11:14
     */
    public void add(AddLineFreightRateParam addLineFreightRateParam) {
        Long entId = LoginUserHolder.getEntId();
        Long count = countByEntIdAndName(entId, addLineFreightRateParam.getName(), null);
        if (count > 0) {
            throw new BusinessException("路径名称已存在，不可重复！");
        }
        String loadName = addLineFreightRateParam.getLoadName();
        String unloadName = addLineFreightRateParam.getUnloadName();
        if (Objects.equals(loadName, unloadName)) {
            throw new BusinessException("路径起始结束位置不能相同！");
        }
        KwmAddress load = addressService.getByNameAndEntId(loadName, addLineFreightRateParam.getLoadEntId());
        if (Objects.isNull(load)) {
            throw new BusinessException("路径起始位置信息不存在！");
        }
        KwmAddress unload = addressService.getByNameAndEntId(unloadName, addLineFreightRateParam.getUnloadEntId());
        if (Objects.isNull(unload)) {
            throw new BusinessException("路径结束位置信息不存在！");
        }
        KwmLineFreightRate freightRate = BeanUtil.copyProperties(addLineFreightRateParam, KwmLineFreightRate.class);
        freightRate.setEntId(entId).setLoadName(load.getName()).setLoadCityCode(load.getCityCode())
                .setLoadCityName(load.getCityName()).setLoadDetailAddress(load.getDetailAddress())
                .setLoadLng(load.getLng()).setLoadLat(load.getLat())
                .setUnloadName(unload.getName()).setUnloadCityCode(unload.getCityCode())
                .setUnloadCityName(unload.getCityName()).setUnloadDetailAddress(unload.getDetailAddress())
                .setUnloadLng(unload.getLng()).setUnloadLat(unload.getLat());
        lineFreightRateMapper.insert(freightRate);
    }

    /**
     * @param param
     * @return void
     * @desc 编辑路径
     * @author yzc
     * @date 2024/3/1 14:37
     */
    public void update(UpdateLineFreightRateParam param) {
        Long entId = LoginUserHolder.getEntId();
        KwmLineFreightRate lineFreightRate = getById(param.getId());
        if (Objects.isNull(lineFreightRate)) {
            throw new BusinessException("路径信息不存在！");
        }
        Long count = countByEntIdAndName(entId, param.getName(), param.getId());
        if (count > 0) {
            throw new BusinessException("路径名称已存在，不可重复！");
        }
        KwmLineFreightRate freightRate = BeanUtil.copyProperties(param, KwmLineFreightRate.class);
        String loadName = param.getLoadName();
        String unloadName = param.getUnloadName();
        if (Objects.equals(loadName, unloadName)) {
            throw new BusinessException("路径起始结束位置不能相同！");
        }
        if (!Objects.equals(loadName, lineFreightRate.getLoadName())) {
            KwmAddress load = addressService.getByNameAndEntId(param.getLoadName(), param.getLoadEntId());
            if (Objects.isNull(load)) {
                throw new BusinessException("路径起始位置信息不存在！");
            }
            freightRate.setLoadName(load.getName()).setLoadCityCode(load.getCityCode())
                    .setLoadCityName(load.getCityName()).setLoadDetailAddress(load.getDetailAddress())
                    .setLoadLng(load.getLng()).setLoadLat(load.getLat());
        }
        if (!Objects.equals(unloadName, lineFreightRate.getUnloadName())) {
            KwmAddress unload = addressService.getByNameAndEntId(param.getUnloadName(), param.getUnloadEntId());
            if (Objects.isNull(unload)) {
                throw new BusinessException("路径结束位置信息不存在！");
            }
            freightRate.setUnloadName(unload.getName()).setUnloadCityCode(unload.getCityCode())
                    .setUnloadCityName(unload.getCityName()).setUnloadDetailAddress(unload.getDetailAddress())
                    .setUnloadLng(unload.getLng()).setUnloadLat(unload.getLat());
        }
        lineFreightRateMapper.updateById(freightRate);
    }

    /**
     * @param id
     * @return com.sckw.manage.model.vo.res.LineFreightRateDetail
     * @desc 路径详情
     * @author yzc
     * @date 2024/3/1 11:18
     */
    public LineFreightRateDetail detail(Long id) {
        LambdaQueryWrapper<KwmLineFreightRate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(KwmLineFreightRate::getId, id)
                .eq(KwmLineFreightRate::getDelFlag, Global.NO)
                .last("LIMIT 1");
        KwmLineFreightRate freightRate = lineFreightRateMapper.selectOne(queryWrapper);
        if (Objects.isNull(freightRate)) {
            throw new BusinessException("路径信息不存在");
        }
        return BeanUtil.copyProperties(freightRate, LineFreightRateDetail.class);
    }


    /**
     * @param params
     * @return com.sckw.core.model.page.PageResult
     * @desc 路径分页列表
     * @author yzc
     * @date 2024/3/1 16:27
     */
    public PageResult select(SelectLineFreightRateParam params) {
        //新增客户经理权限过滤
        List<Long> authEntIdList = new ArrayList<>();
        if (SystemTypeEnum.MANAGE.getCode().equals(LoginUserHolder.getSystemType())) {
            if (CollectionUtils.isEmpty(authEntIdList)) {
                List<Long> ids = remoteUserService.findEnterpriseIdsByUserIdIsMain(LoginUserHolder.getUserId());
                if (CollectionUtils.isEmpty(ids)){
                    return PageResult.build(params.getPage(), params.getPageSize(), 0L, Collections.emptyList());
                }
                authEntIdList.addAll(ids);
            }
        } else {
            authEntIdList.add(LoginUserHolder.getEntId());
        }
        LambdaQueryWrapper<KwmLineFreightRate> wrapper = buildWrapper(BeanUtil.copyProperties(params, ExportLineFreightRateParam.class), authEntIdList);
        Page<KwmLineFreightRate> page = new Page<>(params.getPage(), params.getPageSize());
        Page<KwmLineFreightRate> ipage = lineFreightRateMapper.selectPage(page, wrapper);
        List<KwmLineFreightRate> list = ipage.getRecords();
        if (CollectionUtils.isEmpty(list)) {
            return PageResult.build(params.getPage(), params.getPageSize(), ipage.getTotal(), Collections.emptyList());
        }
        List<Long> createByIds = list.stream().map(KwmLineFreightRate::getCreateBy).toList();
        Map<Long, UserCacheResDto> userMap = remoteSystemService.queryUserCacheMapByIds(createByIds);
        List<LineFreightRateListResVO> result = new ArrayList<>();
        list.forEach(e -> {
            LineFreightRateListResVO vo = BeanUtil.copyProperties(e, LineFreightRateListResVO.class);
            UserCacheResDto user = userMap.get(e.getCreateBy());
            vo.setCreateByName(Objects.nonNull(user) ? user.getName() : "");
            result.add(vo);
        });
        return PageResult.build(params.getPage(), params.getPageSize(), ipage.getTotal(), result);
    }

    /**
     * @param params
     * @return java.util.List<com.sckw.manage.model.vo.res.LineFreightRateExport>
     * @desc 路径导出
     * @author yzc
     * @date 2024/3/1 16:40
     */
    public List<LineFreightRateExport> export(ExportLineFreightRateParam params) {
        //新增客户经理权限过滤
        List<Long> authEntIdList = new ArrayList<>();
        if (SystemTypeEnum.MANAGE.getCode().equals(LoginUserHolder.getSystemType())) {
            if (CollectionUtils.isEmpty(authEntIdList)) {
                List<Long> ids = remoteUserService.findEnterpriseIdsByUserIdIsMain(LoginUserHolder.getUserId());
                if (CollectionUtils.isEmpty(ids)){
                    return new ArrayList<>();
                }
                authEntIdList.addAll(ids);
            }
        } else {
            authEntIdList.add(LoginUserHolder.getEntId());
        }
        LambdaQueryWrapper<KwmLineFreightRate> wrapper = buildWrapper(params, authEntIdList);
        List<KwmLineFreightRate> list = lineFreightRateMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<Long> createByIds = list.stream().map(KwmLineFreightRate::getCreateBy).toList();
        Map<Long, UserCacheResDto> userMap = remoteSystemService.queryUserCacheMapByIds(createByIds);
        List<LineFreightRateExport> result = new ArrayList<>();
        list.forEach(e -> {
            LineFreightRateExport vo = BeanUtil.copyProperties(e, LineFreightRateExport.class);
            UserCacheResDto user = userMap.get(e.getCreateBy());
            vo.setCreateByName(Objects.nonNull(user) ? user.getName() : "")
                    .setTransportMileage(Objects.isNull(e.getTransportMileage()) ? null : String.valueOf(e.getTransportMileage()))
                    .setTransportMileage(Objects.isNull(e.getTransportPrice()) ? null : String.valueOf(e.getTransportPrice()))
                    .setTransportMileage(Objects.isNull(e.getTransportAmount()) ? null : String.valueOf(e.getTransportAmount()))
                    .setTransportMileage(Objects.isNull(e.getCreateTime()) ? null : String.valueOf(DateUtil.getDateTime(e.getCreateTime())))
                    .setTransportMileage(Objects.isNull(e.getUpdateTime()) ? null : String.valueOf(DateUtil.getDateTime(e.getUpdateTime())));
            result.add(vo);
        });
        return result;
    }

    /**
     * @param params
     * @return com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.sckw.manage.model.entity.KwmLineFreightRate>
     * @desc 构建路径查询条件
     * @author yzc
     * @date 2024/3/1 16:40
     */
    private LambdaQueryWrapper<KwmLineFreightRate>

    buildWrapper(ExportLineFreightRateParam params, List<Long> authEntIdList) {
        LambdaQueryWrapper<KwmLineFreightRate> wrapper = new LambdaQueryWrapper<>();
        if (Objects.nonNull(params.getStartCreateTime())) {
            wrapper.ge(KwmLineFreightRate::getCreateTime, params.getStartCreateTime());
        }
        if (Objects.nonNull(params.getEndCreateTime())) {
            wrapper.le(KwmLineFreightRate::getCreateTime, params.getEndCreateTime());
        }
        if (Objects.nonNull(params.getStartMileage())) {
            wrapper.ge(KwmLineFreightRate::getTransportMileage, params.getStartMileage());
        }
        if (Objects.nonNull(params.getEndMileage())) {
            wrapper.le(KwmLineFreightRate::getTransportMileage, params.getEndMileage());
        }
        if (CollectionUtils.isNotEmpty(authEntIdList)) {
            wrapper.in(KwmLineFreightRate::getEntId, authEntIdList);
        }

        String keywords = params.getKeywords();
        if (StringUtils.isNotBlank(keywords)) {
            wrapper.and(e -> e.like(KwmLineFreightRate::getName, keywords)
                    .or().like(KwmLineFreightRate::getLoadName, keywords)
                    .or().like(KwmLineFreightRate::getUnloadName, keywords));
        }
        wrapper.eq(KwmLineFreightRate::getDelFlag, Global.NO)
                .orderByDesc(KwmLineFreightRate::getCreateTime);
        return wrapper;
    }

    /**
     * @param ids
     * @return void
     * @desc 批量删除
     * @author yzc
     * @date 2024/3/1 16:41
     */
    public void batchDelete(List<Long> ids) {
        //todo 关联托运、承运订单不可删除
        LambdaQueryWrapper<KwmLineFreightRate> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(KwmLineFreightRate::getId, ids)
                .eq(KwmLineFreightRate::getEntId, LoginUserHolder.getEntId())
                .eq(KwmLineFreightRate::getDelFlag, Global.NO);
        List<KwmLineFreightRate> list = lineFreightRateMapper.selectList(wrapper);
        if (!Objects.equals(ids.size(), list.size())) {
            throw new BusinessException("删除数据与数据库数据不一致");
        }
        LambdaUpdateWrapper<KwmLineFreightRate> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(KwmLineFreightRate::getDelFlag, Global.YES).in(KwmLineFreightRate::getId, ids);
        lineFreightRateMapper.update(null, updateWrapper);
    }

    /**
     * @param entId
     * @param name
     * @param id
     * @return java.lang.Long
     * @desc 根据企业ID和路径名称统计
     * @author yzc
     * @date 2024/3/1 14:50
     */
    public Long countByEntIdAndName(Long entId, String name, Long id) {
        LambdaQueryWrapper<KwmLineFreightRate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(KwmLineFreightRate::getEntId, entId)
                .ne(Objects.nonNull(id), KwmLineFreightRate::getId, id)
                .eq(KwmLineFreightRate::getName, name)
                .eq(KwmLineFreightRate::getDelFlag, Global.NO);
        return lineFreightRateMapper.selectCount(queryWrapper);
    }

    /**
     * @param id
     * @return com.sckw.manage.model.entity.KwmLineFreightRate
     * @desc 根据id查询路径信息
     * @author yzc
     * @date 2024/3/1 16:41
     */
    public KwmLineFreightRate getById(Long id) {
        LambdaQueryWrapper<KwmLineFreightRate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(KwmLineFreightRate::getId, id)
                .eq(KwmLineFreightRate::getDelFlag, Global.NO);
        return lineFreightRateMapper.selectOne(queryWrapper);
    }

    /**
     * @param params
     * @return java.util.List<com.sckw.manage.model.vo.res.LineFreightRateFindListResVO>
     * @desc 路径下拉列表查询
     * @author yzc
     * @date 2024/3/4 10:15
     */
    public List<LineFreightRateFindListResVO> findList(LineFreightRateFindListParam params) {
        LambdaQueryWrapper<KwmLineFreightRate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(KwmLineFreightRate::getEntId, LoginUserHolder.getEntId())
                .eq(KwmLineFreightRate::getDelFlag, Global.NO)
                .like(StringUtils.isNotBlank(params.getName()), KwmLineFreightRate::getName, params.getName());
        List<KwmLineFreightRate> list = lineFreightRateMapper.selectList(queryWrapper);
        return BeanUtil.copyToList(list, LineFreightRateFindListResVO.class);
    }

    /**
     * @param param
     * @return java.util.List<com.sckw.manage.model.vo.res.LineFreightRateListResVO>
     * @desc 物流订单路径选择查询
     * @author yzc
     * @date 2024/3/13 16:11
     */
    public List<LineFreightRateListResVO> choose(ChooseLineFreightRateParam param) {
        LambdaQueryWrapper<KwmLineFreightRate> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(KwmLineFreightRate::getLoadName, param.getLoadNames())
                .in(KwmLineFreightRate::getUnloadName, param.getUnloadNames())
                .eq(KwmLineFreightRate::getDelFlag, Global.NO);
        List<KwmLineFreightRate> list = lineFreightRateMapper.selectList(wrapper);
        return BeanUtil.copyToList(list, LineFreightRateListResVO.class);
    }
}