package org.dromara.work.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.work.domain.TpClient;
import org.dromara.work.domain.TpClientStaff;
import org.dromara.work.domain.TpOrder;
import org.dromara.work.domain.bo.TpClientBo;
import org.dromara.work.domain.vo.ClientSumVo;
import org.dromara.work.domain.vo.OrderRankingVo;
import org.dromara.work.domain.vo.TpClientVo;
import org.dromara.work.mapper.TpClientMapper;
import org.dromara.work.mapper.TpClientStaffMapper;
import org.dromara.work.mapper.TpOrderMapper;
import org.dromara.work.service.ITpClientService;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * 客户Service业务层处理
 *
 * @author Maosw
 * @date 2024-08-12
 */
@RequiredArgsConstructor
@Service
public class TpClientServiceImpl extends MPJBaseServiceImpl<TpClientMapper,TpClient> implements ITpClientService {

    private final TpClientMapper baseMapper;

    private final TpClientStaffMapper staffMapper;

    private final TpOrderMapper orderMapper;

    /**
     * 查询客户
     *
     * @param id 主键
     * @return 客户
     */
    @Override
    public TpClientVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询客户列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 客户分页列表
     */
    @Override
    public TableDataInfo<TpClientVo> queryPageList(TpClientBo bo, PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if(LoginHelper.isSuperAdmin()){
            bo.setIsDel(1);
            MPJLambdaWrapper<TpClient> lqw = buildQueryWrapper(bo)
                .selectAll(TpClient.class)
                .selectAs("(select count(1) from tp_order o where o.kid = t.id and o.is_del = 1 and o.pay_state != 1)",TpClientVo::getCount)
                .selectAs("(select sum(o.khpay) from tp_order o where o.kid = t.id and o.is_del = 1 and o.pay_state != 1)",TpClientVo::getAllPrice)
//                .leftJoin(TpOrder.class,TpOrder::getKid,TpClient::getId)
                .orderByDesc(TpClient::getId);

            IPage<TpClientVo> result = baseMapper.selectJoinPage(new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()), TpClientVo.class, lqw);
            return TableDataInfo.build(result);
        }else {//普通用户
            bo.setIsDel(1);
            MPJLambdaWrapper<TpClientStaff> wrapper = buildQueryMPJWrapper(bo)
                .selectAll(TpClientStaff.class)
                .select("c.code", "c.phone", "c.sex", "c.type", "c.ywtype","c.province","c.city","c.area","c.state","c.vip","c.gt_vip","c.health")
                .selectAs("(select count(1) from tp_order o where o.skid = t.id and o.is_del = 1 and o.pay_state != 1)",TpClientVo::getCount)
                .selectAs("(select sum(o.khpay) from tp_order o where o.skid = t.id and o.is_del = 1 and o.pay_state != 1)",TpClientVo::getAllPrice)
                .eq(loginUser.getIdentity() == 3,TpClientStaff::getSid,loginUser.getUserId())
                .leftJoin("tp_client c on c.id = t.kid")
                .orderByDesc(TpClientStaff::getId);

            //分页查询 （需要启用 mybatis plus 分页插件）
            IPage<TpClientVo> listPage = staffMapper.selectJoinPage(new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()), TpClientVo.class, wrapper);
            return TableDataInfo.build(listPage);
        }
    }

    /**
     * 查询符合条件的客户列表
     *
     * @param bo 查询条件
     * @return 客户列表
     */
    @Override
    public List<TpClientVo> queryList(TpClientBo bo) {
        bo.setIsDel(1);
        MPJLambdaWrapper<TpClient> lqw = buildQueryWrapper(bo)
            .selectAll(TpClient.class)
//            .selectAs("(select count(1) from tp_order o where o.kid = t.id and o.is_del = 1 and o.pay_state != 1)",TpClientVo::getCount)
//            .selectAs("(select sum(o.khpay) from tp_order o where o.kid = t.id and o.is_del = 1 and o.pay_state != 1)",TpClientVo::getAllPrice)
            .orderByDesc(TpClient::getId);
        return baseMapper.selectJoinList(TpClientVo.class,lqw);
    }

    private MPJLambdaWrapper<TpClient> buildQueryWrapper(TpClientBo bo) {
        Map<String, Object> params = bo.getParams();
        MPJLambdaWrapper<TpClient> lqw = new MPJLambdaWrapper<>();

        if(bo.getMulti() != null){
            if(bo.getMulti()== 1){
//                lqw.apply("(SELECT count(1) from tp_client_staff r where r.kid = t.id) > 1");
                lqw.apply("INSTR(t.sname, ',') > 0");
            }else {
                lqw.gt(TpClient::getYue, 0);
                lqw.apply("(SELECT count(1) from tp_client_staff r where r.kid = t.id) > 1");
            }
        }

        lqw.eq(bo.getHealth() != null, TpClient::getHealth, bo.getHealth());
        lqw.eq(bo.getUid() != null, TpClient::getUid, bo.getUid());
        lqw.eq(StringUtils.isNotBlank(bo.getCode()), TpClient::getCode, bo.getCode());
        lqw.eq(StringUtils.isNotBlank(bo.getSname()), TpClient::getSname, bo.getSname());
        lqw.like(StringUtils.isNotBlank(bo.getName()), TpClient::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getPhone()), TpClient::getPhone, bo.getPhone());
        lqw.eq(StringUtils.isNotBlank(bo.getSex()), TpClient::getSex, bo.getSex());
        lqw.eq(bo.getType() != null, TpClient::getType, bo.getType());
        lqw.eq(bo.getYwtype() != null, TpClient::getYwtype, bo.getYwtype());
        lqw.eq(bo.getState() != null, TpClient::getState, bo.getState());
        lqw.eq(bo.getAddTime() != null, TpClient::getAddTime, bo.getAddTime());
        lqw.eq(bo.getIsDel() != null, TpClient::getIsDel, bo.getIsDel());
        lqw.eq(StringUtils.isNotBlank(bo.getAddUser()), TpClient::getAddUser, bo.getAddUser());
        lqw.eq(bo.getVip() != null, TpClient::getVip, bo.getVip());
        lqw.eq(bo.getGtVip() != null, TpClient::getGtVip, bo.getGtVip());
        lqw.eq(bo.getHealth() != null, TpClient::getHealth, bo.getHealth());
        lqw.eq(StringUtils.isNotBlank(bo.getProvince()), TpClient::getProvince, bo.getProvince());
        lqw.eq(StringUtils.isNotBlank(bo.getCity()), TpClient::getCity, bo.getCity());
        lqw.eq(StringUtils.isNotBlank(bo.getArea()), TpClient::getArea, bo.getArea());
        return lqw;
    }

    private MPJLambdaWrapper<TpClientStaff> buildQueryMPJWrapper(TpClientBo bo) {
        Map<String, Object> params = bo.getParams();
        MPJLambdaWrapper<TpClientStaff> lqw = new MPJLambdaWrapper<>();
        lqw.eq(bo.getUid() != null, TpClient::getUid, bo.getUid());
        lqw.eq(bo.getSid() != null, TpClientStaff::getSid, bo.getSid());
        lqw.eq(StringUtils.isNotBlank(bo.getSname()), TpClient::getSname, bo.getSname());
        lqw.eq(StringUtils.isNotBlank(bo.getCode()), TpClient::getCode, bo.getCode());
        lqw.like(StringUtils.isNotBlank(bo.getName()), TpClient::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getPhone()), TpClient::getPhone, bo.getPhone());
        lqw.eq(StringUtils.isNotBlank(bo.getSex()), TpClient::getSex, bo.getSex());
        lqw.eq(bo.getType() != null, TpClient::getType, bo.getType());
        lqw.eq(bo.getYwtype() != null, TpClient::getYwtype, bo.getYwtype());
        lqw.eq(bo.getState() != null, TpClient::getState, bo.getState());
        lqw.eq(bo.getAddTime() != null, TpClient::getAddTime, bo.getAddTime());
        lqw.eq(bo.getIsDel() != null, TpClientStaff::getIsDel, bo.getIsDel());
        lqw.eq(StringUtils.isNotBlank(bo.getAddUser()), TpClient::getAddUser, bo.getAddUser());
        lqw.eq(bo.getVip() != null, TpClient::getVip, bo.getVip());
        lqw.eq(bo.getGtVip() != null, TpClient::getGtVip, bo.getGtVip());
        lqw.eq(bo.getHealth() != null, "c.health", bo.getHealth());
        lqw.eq(StringUtils.isNotBlank(bo.getProvince()), TpClient::getProvince, bo.getProvince());
        lqw.eq(StringUtils.isNotBlank(bo.getCity()), TpClient::getCity, bo.getCity());
        lqw.eq(StringUtils.isNotBlank(bo.getArea()), TpClient::getArea, bo.getArea());
        return lqw;
    }

    /**
     * 新增客户
     *
     * @param bo 客户
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(TpClientBo bo) {
        bo.setAddTime(new Date());
        LoginUser loginUser = LoginHelper.getLoginUser();
        boolean isFlag = false;
        while (!isFlag){
            String code = "KH" + (int)(Math.random()*80000)+1;
            boolean exist = baseMapper.exists(new LambdaQueryWrapper<TpClient>().eq(TpClient::getCode, code));
            if(!exist){
                bo.setCode(code);
                isFlag = true;
            }
        }
        TpClient client = baseMapper.selectOne(new LambdaQueryWrapper<TpClient>().eq(TpClient::getPhone,bo.getPhone()));

        if(LoginHelper.isSuperAdmin()){
            if(ObjectUtil.isNotNull(client)){
                throw new ServiceException("手机号码已存在");
            }
            TpClient add = MapstructUtils.convert(bo, TpClient.class);
            add.setAddUser(String.valueOf(loginUser.getUserId()));
            add.setSname(loginUser.getNickname());
            return baseMapper.insert(add) > 0;
        }else{//客服
            if(loginUser.getIdentity() == 2){
                throw new ServiceException("您无权限添加客户信息");
            } else if(loginUser.getIdentity() == 3){
                TpClientStaff staff = new TpClientStaff();
                if(Objects.isNull(client)){
                    TpClient add = MapstructUtils.convert(bo, TpClient.class);
                    add.setAddUser(String.valueOf(loginUser.getUserId()));
                    add.setSname(loginUser.getNickname());
                    boolean flag = baseMapper.insert(add) > 0;
                    if (!flag) {
                        throw new ServiceException("添加客户信息失败");
                    }
                    staff.setKid(add.getId());
                }else {
                    client.setAddUser(client.getAddUser() + "," + loginUser.getUserId());
                    client.setSname(client.getSname() + ","+ loginUser.getNickname());
                    boolean flag = baseMapper.updateById(client) > 0;
                    if (!flag) {
                        throw new ServiceException("添加客户信息失败");
                    }
                    staff.setKid(client.getId());
                }
                staff.setName(bo.getName());
                staff.setSid(loginUser.getUserId());
                staff.setSname(loginUser.getNickname());
                staff.setRemark(bo.getRemark());
                staff.setAddTime(new Date());
                return staffMapper.insert(staff) >0;
            }
        }
        return false;
    }

    /**
     * 修改客户
     *
     * @param bo 客户
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(TpClientBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if(LoginHelper.isSuperAdmin()){
            //管理员需要传TpClient的ID
            TpClientVo clientVo = baseMapper.selectVoById(bo.getId());
            if(StringUtils.isNotEmpty(bo.getPhone()) && !Objects.equals(bo.getPhone(), clientVo.getPhone())){
                throw new ServiceException("客户手机号码不允许修改");
            }
            if(StringUtils.isNotEmpty(bo.getCode()) && !Objects.equals(bo.getCode(), clientVo.getCode())){
                throw new ServiceException("客户编号不允许修改");
            }
        }else {
            //普通客户ids需要传TpClientStaff的ID
            TpClientStaff staff = staffMapper.selectById(bo.getId());
            TpClientVo clientVo = baseMapper.selectVoById(staff.getKid());
            if(StringUtils.isNotEmpty(bo.getPhone()) && !Objects.equals(bo.getPhone(), clientVo.getPhone())){
                throw new ServiceException("客户手机号码不允许修改");
            }
            if(StringUtils.isNotEmpty(bo.getCode()) && !Objects.equals(bo.getCode(), clientVo.getCode())){
                throw new ServiceException("客户编号不允许修改");
            }
            staff.setName(bo.getName());
            staff.setRemark(bo.getRemark());
            staffMapper.updateById(staff);
        }
        TpClient update = MapstructUtils.convert(bo, TpClient.class);
        return baseMapper.updateById(update) > 0;
    }


    /**
     * 校验并批量删除客户信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if(LoginHelper.isSuperAdmin()){
            //管理员ids需要传TpClient的ID
            List<TpClient> list = baseMapper.selectByIds(ids);
            for(TpClient client : list){
                client.setIsDel(2);
                if(client.getYue().compareTo(BigDecimal.ZERO) > 0) {
                    throw new ServiceException("客户：" + client.getName() + "余额大于0，不可删除");
                }
            }
            return baseMapper.updateBatchById(list);
        }else{
            //普通客户ids需要传TpClientStaff的ID
            if(loginUser.getIdentity() == 2){
                throw new ServiceException("您无权限删除客户信息");
            } else if (loginUser.getIdentity() == 3) {
                List<TpClientStaff> list = staffMapper.selectByIds(ids);
                for(TpClientStaff clientStaff : list){
                    clientStaff.setIsDel(2);
                    if(clientStaff.getYue().compareTo(BigDecimal.ZERO) > 0) {
                        throw new ServiceException("客户：" + clientStaff.getName() + "余额大于0，不可删除");
                    }
                }
                return staffMapper.updateBatchById(list);
            }
        }
        return false;
    }

    /**
     * 查询客户下单金额统计列表
     *
     * @param bo
     * @param pageQuery
     * @return
     */
    @Override
    public TableDataInfo<ClientSumVo> queryPageListChart(TpClientBo bo, PageQuery pageQuery) {
        Map<String, Object> params = bo.getParams();
        MPJLambdaWrapper<TpOrder> wrapper = new MPJLambdaWrapper<TpOrder>();
        if(LoginHelper.isSuperAdmin()){
            wrapper.selectAs(TpOrder::getKid, ClientSumVo::getId)
                .selectSum(TpOrder::getKhpay,ClientSumVo::getAmount);
                wrapper.between(params.get("beginTime") != null && params.get("endTime") != null,
                    TpOrder::getAddTime ,params.get("beginTime"), params.get("endTime"))
                .eq(TpOrder::getIsDel,1)
                .in(bo.getIds() != null,TpOrder::getKid,bo.getIds())
                .groupBy(TpOrder::getKid);

        }else{
            wrapper.selectAs(TpOrder::getSkid, ClientSumVo::getId)
                .selectSum(TpOrder::getKhpay,ClientSumVo::getAmount);
            wrapper.between(params.get("beginTime") != null && params.get("endTime") != null,
                    TpOrder::getAddTime ,params.get("beginTime"), params.get("endTime"))
                .eq(TpOrder::getIsDel,1)
                .in(bo.getIds() != null,TpOrder::getSkid,bo.getIds())
                .groupBy(TpOrder::getSkid);
        }
        IPage<ClientSumVo> listPage = orderMapper.selectJoinPage(new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()), ClientSumVo.class, wrapper);
        return TableDataInfo.build(listPage);
    }

    /**
     * 获取全部客户
     *
     * @return
     */
    @Override
    public List<TpClient> queryAllList() {
        return baseMapper.selectList(new LambdaQueryWrapper<TpClient>().eq(TpClient::getIsDel, 1));
    }
}
