package com.xy.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yitter.idgen.YitIdHelper;
import com.xy.device.EnumDeviceCharging;
import com.xy.device.EnumDeviceChargingConfigType;
import com.xy.dto.DeviceChargingConfigDto;
import com.xy.dto.be.MercDto;
import com.xy.entity.DeviceChargingConfig;
import com.xy.error.CommRuntimeException;
import com.xy.mapper.DeviceChargingConfigMapper;
import com.xy.service.be.MercService;
import com.xy.utils.Beans;
import com.xy.utils.MybatisPlusQuery;
import com.xy.utils.R;
import com.xy.utils.SysDictUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static com.xy.utils.Beans.copy;


/**
 * <p>
 * 设备计费配置表 服务实现类
 * </p>
 *
 * @author lijin
 * @since 2023-07-28
 */
@Service
@AllArgsConstructor
@Api(tags = "设备计费配置表")
public class DeviceChargingConfigServiceImpl extends ServiceImpl<DeviceChargingConfigMapper, DeviceChargingConfig> implements DeviceChargingConfigService {

    private MercService mercService;

    private DeviceAlgorithmChargingServiceImpl deviceAlgorithmChargingService;

    @PostMapping("list")
    @ApiOperation("集合查询")
    public R<List<DeviceChargingConfigDto.Vo>> list(@RequestBody @Validated DeviceChargingConfigDto.SelectList selectList) {
        MercDto.Vo merc = mercService.obj(new MercDto.Vo().setId(selectList.getMercId())).getData();
        LambdaQueryWrapper<DeviceChargingConfig> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, DeviceChargingConfig.class)
                .in(DeviceChargingConfig::getDeviceType, selectList.getDeviceTypes())
                .eq(DeviceChargingConfig::getMercCode, merc.getMercCode())
                .build();
        List<DeviceChargingConfig> list = list(lambdaQueryWrapper);
        return R.ok(Beans.copy(DeviceChargingConfigDto.Vo.class, list));
    }


    @PostMapping("listByFeeConfig")
    @ApiOperation("设备管理费用配置查询")
    public R<DeviceChargingConfigDto.DeviceManagerFeeConfigVO> listByFeeConfig(@RequestBody @Validated DeviceChargingConfigDto.ListByFeeConfigDTO dto) {
        DeviceChargingConfigDto.DeviceManagerFeeConfigVO data = new DeviceChargingConfigDto.DeviceManagerFeeConfigVO();
        List<Integer> deviceTypes = dto.getDeviceTypes();
        // 设备管理费-平台默认配置
        List<DeviceChargingConfigDto.DeviceManagerFeePlatformVO> dmFeePlatforms = new ArrayList<>();
        for (Integer type : deviceTypes) {// 默认年费，赠送天数
            DeviceChargingConfigDto.DeviceManagerFeePlatformVO vo = new DeviceChargingConfigDto.DeviceManagerFeePlatformVO();
            int defaultMoney = SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), String.valueOf(type), Integer.class);
            // 默认赠送天数
            int giveDays = SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), EnumDeviceCharging.N_X.getCode(), Integer.class);
            vo.setDefFee(defaultMoney);
            vo.setDefGiveDay(giveDays);
            vo.setDeviceType(type);
            dmFeePlatforms.add(vo);
        }
        MercDto.Vo merc = mercService.obj(new MercDto.Vo().setId(dto.getMercId())).getData();

        // 设备管理费-商家自定义费用
        List<DeviceChargingConfigDto.DeviceManagerFeeMercVO> dmFeeMercs = new ArrayList<>();
        LambdaQueryWrapper<DeviceChargingConfig> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(dto, DeviceChargingConfig.class)
                .in(DeviceChargingConfig::getDeviceType, deviceTypes)
                .eq(DeviceChargingConfig::getMercCode, merc.getMercCode())
                .build();
        // 默认配置 type 2预充 1赠送天数
        List<DeviceChargingConfig> list = list(lambdaQueryWrapper);
        if (CollUtil.isNotEmpty(list)) {
            for (DeviceChargingConfig dcc : list) {
                Integer type = dcc.getType();
                Integer deviceType = dcc.getDeviceType();
                // 预充
                if (String.valueOf(type).equals(EnumDeviceChargingConfigType.N_2.getCode())) {
                    int defaultMoney = SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), String.valueOf(deviceType), Integer.class);
                    // 默认赠送天数
                    int giveDays = SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), EnumDeviceCharging.N_X.getCode(), Integer.class);
                    DeviceChargingConfigDto.DeviceManagerFeeMercVO vo = new DeviceChargingConfigDto.DeviceManagerFeeMercVO();
                    BeanUtil.copyProperties(dcc, vo);
                    vo.setDefFee(defaultMoney);
                    vo.setDefGiveDay(giveDays);
                    vo.setFee(dcc.getConfigValue());
                    Optional<DeviceChargingConfig> dcObj = list.stream()
                            .filter(dc -> String.valueOf(dc.getType()).equals(EnumDeviceChargingConfigType.N_1.getCode()))
                            .filter(dc -> dc.getDeviceType().intValue() == deviceType.intValue())
                            .findFirst();
                    vo.setGiveDay(dcObj.get().getConfigValue());
                    dmFeeMercs.add(vo);
                }
            }
        }

        data.setDmFeeMercs(dmFeeMercs);
        data.setDmFeePlatforms(dmFeePlatforms);
        return R.ok(data);
    }

    @PostMapping("save")
    @ApiOperation("添加")
    public R save(@RequestBody @Validated DeviceChargingConfigDto.Save save) {
        LocalDateTime now = LocalDateTime.now();

        Integer deviceType = save.getDeviceType();
        Long mercId = save.getMercId();
        MercDto.Vo merc = R.feignCheckData(mercService.obj(new MercDto.Vo().setId(mercId)));
        String mercCode = merc.getMercCode();
        DeviceChargingConfig dc = this.getOne(Wrappers.<DeviceChargingConfig>lambdaQuery()
                .eq(DeviceChargingConfig::getMercCode, mercCode)
                .eq(DeviceChargingConfig::getDeviceType, deviceType)
                .eq(DeviceChargingConfig::getType, EnumDeviceChargingConfigType.N_2.getCode())
        );

        if (dc != null) {
            throw new CommRuntimeException("该类型配置已存在，请勿重复添加！");
        }

        // 默认赠送天数
        int giveDays = SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), EnumDeviceCharging.N_X.getCode(), Integer.class);
        // 新增赠送天数
        DeviceChargingConfig newDc = new DeviceChargingConfig().setDeviceType(deviceType).setConfigValue(giveDays).setMercCode(mercCode)
                .setType(Integer.valueOf(EnumDeviceChargingConfigType.N_1.getCode())).setCreateTime(now)
                .setUpdateTime(now).setMercCode(mercCode);
        save(newDc);


        DeviceChargingConfig saveInfo = copy(DeviceChargingConfig.class, save)
                .setCreateTime(now)
                .setUpdateTime(now).setMercCode(mercCode);
        save(saveInfo);
        return R.ok();
    }

    @PostMapping("update")
    @ApiOperation("修改")
    public R update(@RequestBody @Validated DeviceChargingConfigDto.Update update) {
//        DeviceChargingConfig dcc = getById(update.getId());
        DeviceChargingConfig updateInfo = copy(DeviceChargingConfig.class, update)
                .setUpdateTime(LocalDateTime.now());
        updateById(updateInfo);
        return R.ok();
    }

    @PostMapping("delete")
    @ApiOperation("删除")
    @Transactional(rollbackFor = Exception.class)
    public R delete(@RequestBody @Validated DeviceChargingConfigDto.Delete delete) {
        Long id = delete.getId();
        DeviceChargingConfig dcc = getById(delete.getId());
        DeviceChargingConfig one = getOne(Wrappers.<DeviceChargingConfig>lambdaQuery()
                .eq(DeviceChargingConfig::getMercCode, dcc.getMercCode())
                .eq(DeviceChargingConfig::getDeviceType, dcc.getDeviceType())
                .eq(DeviceChargingConfig::getType, Integer.valueOf(EnumDeviceChargingConfigType.N_1.getCode()))
        );
        if (one != null) {
            removeById(one.getId());
        }
        removeById(delete.getId());
        return R.ok();
    }


    @PostMapping("saveOrUpdate")
    @ApiOperation("添加或修改")
    public R saveOrUpdate(@RequestBody @Validated DeviceChargingConfigDto.SaveOrUpdate saveOrUpdate) {
        LocalDateTime now = LocalDateTime.now();
        MercDto.Vo merc = mercService.obj(new MercDto.Vo().setId(saveOrUpdate.getMercId())).getData();
        List<DeviceChargingConfigDto.SaveOrUpdate.ConfigValue> values = saveOrUpdate.getConfigValues();
        for (DeviceChargingConfigDto.SaveOrUpdate.ConfigValue value : values) {
            LambdaQueryWrapper<DeviceChargingConfig> lambdaQueryWrapper = new LambdaQueryWrapper<DeviceChargingConfig>()
                    .eq(DeviceChargingConfig::getMercCode, merc.getMercCode())
                    .eq(DeviceChargingConfig::getDeviceType, saveOrUpdate.getDeviceType())
                    .eq(DeviceChargingConfig::getType, value.getType());
            DeviceChargingConfig deviceChargingConfig = getOne(lambdaQueryWrapper);
            if (deviceChargingConfig == null) {
                if (value.getConfigValue() == -1) {
                    continue;
                }
                deviceChargingConfig = new DeviceChargingConfig()
                        .setId(YitIdHelper.nextId())
                        .setMercCode(merc.getMercCode())
                        .setDeviceType(saveOrUpdate.getDeviceType())
                        .setConfigValue(value.getConfigValue())
                        .setNote(saveOrUpdate.getNote())
                        .setType(value.getType())
                        .setCreateTime(now)
                        .setUpdateTime(now);
                save(deviceChargingConfig);
            } else {
                if (value.getConfigValue() == -1) {
                    removeById(deviceChargingConfig.getId());
                    continue;
                }
                deviceChargingConfig.setConfigValue(value.getConfigValue())
                        .setNote(saveOrUpdate.getNote())
                        .setUpdateTime(now);
                updateById(deviceChargingConfig);
            }
        }
        return R.ok();
    }

    @Override
    @ApiOperation("集合查询2")
    public R<List<DeviceChargingConfigDto.Vo>> list2(DeviceChargingConfigDto.SelectList selectList) {
        MercDto.Vo merc = mercService.obj(new MercDto.Vo().setId(selectList.getMercId())).getData();
        List<String> mercCodes = new ArrayList<>();
        deviceAlgorithmChargingService.getMercCodes(merc.getMercCode(), mercCodes);
        LambdaQueryWrapper<DeviceChargingConfig> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, DeviceChargingConfig.class)
                .in(DeviceChargingConfig::getMercCode, mercCodes)
                .build()
                .orderByDesc(DeviceChargingConfig::getMercCode);
        List<DeviceChargingConfig> list = list(lambdaQueryWrapper);
        return R.ok(Beans.copy(DeviceChargingConfigDto.Vo.class, list));
    }
}
