package com.ruoyi.ss.device.service.impl;

import com.ruoyi.common.core.domain.BaseValidator;
import com.ruoyi.common.core.domain.ValidateResult;
import com.ruoyi.common.enums.ServiceCode;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.ss.bonus.domain.Bonus;
import com.ruoyi.ss.device.domain.DeviceBO;
import com.ruoyi.ss.device.domain.DeviceQuery;
import com.ruoyi.ss.device.domain.enums.DeviceServiceMode;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.device.service.DeviceAssembler;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.device.service.DeviceValidator;
import com.ruoyi.ss.store.service.StoreValidator;
import com.ruoyi.ss.storeStaff.domain.enums.StoreStaffPermissions;
import com.ruoyi.ss.storeStaff.service.StoreStaffValidator;
import com.ruoyi.ss.suit.service.SuitValidator;
import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillType;
import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import com.ruoyi.ss.user.domain.SmUserVO;
import com.ruoyi.ss.user.service.ISmUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;

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

/**
 * @author wjh
 * 2024/4/30
 */
@Service
public class DeviceValidatorImpl extends BaseValidator implements DeviceValidator {

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private StoreValidator storeValidator;

    @Autowired
    private SuitValidator suitValidator;

    @Autowired
    private TransactionBillService transactionBillService;

    @Autowired
    private ISmUserService userService;

    @Autowired
    private DeviceAssembler deviceAssembler;

    @Autowired
    private StoreStaffValidator storeStaffValidator;

    /**
     * 设备编号是否存在
     *
     * @param deviceNos
     */
    @Override
    public boolean isExistNo(List<String> deviceNos) {
        if (CollectionUtils.isEmptyElement(deviceNos)) {
            return true;
        }
        DeviceQuery query = new DeviceQuery();
        query.setDeviceNos(deviceNos);
        return deviceService.selectCount(query) == new HashSet<>(deviceNos).size();
    }

    /**
     * 判断设备是否属于指定用户
     *
     * @param deviceId 设备id
     * @param userId   用户id
     */
    @Override
    public boolean isMch(Long deviceId, Long userId) {
        if (deviceId == null || userId == null) {
            return false;
        }
        DeviceVO device = deviceService.selectById(deviceId);
        return this.isMch(device, userId);
    }

    @Override
    public boolean isMch(Collection<Long> deviceIds, Long userId) {
        if (CollectionUtils.isEmptyElement(deviceIds) || userId == null) {
            return false;
        }
        DeviceQuery query = new DeviceQuery();
        query.setDeviceIds(new ArrayList<>(deviceIds));
        query.setUserId(userId);
        List<DeviceVO> deviceList = deviceService.selectSmDeviceList(query);
        for (DeviceVO device : deviceList) {
            if (!isMch(device, userId)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean isMch(DeviceVO device, Long userId) {
        return device != null && userId != null && Objects.equals(device.getUserId(), userId);
    }

    /**
     * 创建前校验
     *
     * @param data
     * @return
     */
    @Override
    public ValidateResult preCreate(DeviceBO data) {
        if (data == null) {
            return error("数据不允许为空");
        }
        return success();
    }

    /**
     * 更新前校验
     *
     * @param data
     */
    @Override
    public ValidateResult preUpdate(DeviceBO data) {
        if (data == null) {
            return error("数据不允许为空");
        }
        return success();
    }

    /**
     * APP更新前校验
     *
     * @param data
     */
    @Override
    public ValidateResult preUpdateByApp(DeviceBO data) {
        if (data == null) {
            return error("数据不允许为空");
        }

        if (data.getStoreId() != null && !storeValidator.isExist(Collections.singletonList(data.getStoreId()))) {
            return error("店铺不存在");
        }

        return success();
    }

    @Override
    public boolean isRepeatSn(Long deviceId, String sn) {
        if (StringUtils.isBlank(sn)) {
            return false;
        }
        DeviceQuery query = new DeviceQuery();
        query.setEqDeviceNo(sn);
        query.setExcludeDeviceId(deviceId);
        return deviceService.selectCount(query) > 0;
    }

    @Override
    public boolean isRepeatMac(Long deviceId, String mac) {
        if (StringUtils.isBlank(mac)) {
            return false;
        }
        DeviceQuery query = new DeviceQuery();
        query.setAnyMac(mac);
        List<DeviceVO> repeatList = deviceService.selectSmDeviceList(query);
        if (CollectionUtils.isNotEmptyElement(repeatList)) {
            for (DeviceVO device : repeatList) {
                boolean repeat = device != null && !Objects.equals(deviceId, device.getDeviceId());
                if (repeat) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void afterCheck(DeviceVO vo) {
        if (vo == null) {
            return;
        }
        // 校验MAC
        this.checkMac(vo.getDeviceId(), vo.getMac(), vo.getMac2());
        // 校验SN
        this.checkSn(vo.getDeviceId(), vo.getDeviceNo());
        // 校验代理商
        this.checkAgent(vo);
        // 校验分成
        this.checkBonus(vo);

    }

    // 校验代理商
    @Override
    public void checkAgent(DeviceVO vo) {
        if (vo == null) {
            return;
        }
        if (DeviceServiceMode.AGENT.getMode().equals(vo.getServiceMode())) {
            ServiceUtil.assertion(vo.getAgentId() == null, "代理商不允许为空");
            ServiceUtil.assertion(vo.getAgentServiceRate() == null || vo.getAgentUserServiceRate() == null, "设备代理商服务费或平台代理商服务费不允许为空");
            ServiceUtil.assertion(vo.getAgentServiceRate().compareTo(vo.getAgentUserServiceRate()) < 0,
                    "设备服务费不允许小于平台收取代理商的服务费：" + vo.getAgentUserServiceRate() + "%");
            ServiceUtil.assertion(vo.getAgentServiceRate().compareTo(new BigDecimal(100)) > 0, "代理服务费不允许超过100%");
        }
    }

    @Override
    public boolean isAgent(DeviceVO device, Long userId) {
        if (device == null || userId == null) {
            return false;
        }
        return Objects.equals(device.getAgentId(), userId);
    }

    @Override
    public boolean hasUsingBill(Long deviceId) {
        if (deviceId == null) {
            return false;
        }
        TransactionBillQuery query = new TransactionBillQuery();
        query.setDeviceId(deviceId);
        query.setType(TransactionBillType.RECHARGE.getType());
        query.setIsUsing(true);
        int count = transactionBillService.selectSimpleCount(query);
        return count > 0;
    }

    @Override
    public void checkMac(Long deviceId, String mac, String mac2) {
        if (StringUtils.hasText(mac) && StringUtils.hasText(mac2)) {
            ServiceUtil.assertion(Objects.equals(mac, mac2), "MAC-1和MAC-2不允许相同");
        }
        ServiceUtil.assertion(this.isRepeatMac(deviceId, mac), "MAC-1重复:" + mac, ServiceCode.DEVICE_MAC_REPEAT.getCode());
        ServiceUtil.assertion(this.isRepeatMac(deviceId, mac2), "MAC-2重复:" + mac2, ServiceCode.DEVICE_MAC_REPEAT.getCode());
    }

    @Override
    public void checkSn(Long deviceId, String deviceNo) {
        ServiceUtil.assertion(isRepeatSn(deviceId, deviceNo), "SN重复", ServiceCode.DEVICE_SN_REPEAT.getCode());
    }

    @Override
    public boolean isAgentAllowMchSwitch(DeviceVO device) {
        if (device != null && DeviceServiceMode.AGENT.getMode().equals(device.getServiceMode()) && device.getAgentId() != null) {
            SmUserVO agent = userService.selectSimpleById(device.getAgentId());
            return agent == null || agent.getAgentAllowMchSwitch();
        }
        return true;
    }

    @Override
    public void checkBonus(DeviceVO device) {
        if (device == null || CollectionUtils.isEmpty(device.getBonusList())) {
            return;
        }
        BigDecimal decimal100 = new BigDecimal(100);

        BigDecimal sumPoint = CollectionUtils.sumDecimal(device.getBonusList(), Bonus::getPoint);
        ServiceUtil.assertion(sumPoint.compareTo(decimal100) > 0, "设备%s的总分成比例不允许超过100", device.getDeviceNo());

        // 不允许分成小于0
        for (Bonus bonus : device.getBonusList()) {
            ServiceUtil.assertion(bonus.getPoint() == null, "设备%s的%s分成比例不允许为空", device.getDeviceNo(), bonus.getArrivalName());
            ServiceUtil.assertion(bonus.getPoint().compareTo(BigDecimal.ZERO) < 0, "设备%s的%s分成比例不允许小于0", device.getDeviceNo(), bonus.getArrivalName());
        }
    }

    @Override
    public void checkBonus(Long deviceId) {
        if (deviceId == null) {
            return;
        }
        DeviceVO device = deviceService.selectById(deviceId);
        deviceAssembler.assembleBonusList(device);
        this.checkBonus(device);
    }

    @Override
    public boolean canOpera(Long deviceId, Long userId) {
        if (deviceId == null || userId == null) {
            return false;
        }
        DeviceVO device = deviceService.selectById(deviceId);
        return canOpera(device, userId);
   }

    @Override
    public boolean canOpera(DeviceVO device, Long userId) {
        if (device == null) {
            return false;
        }
        return this.isMch(device, userId)
                || storeStaffValidator.hasStorePermission(device.getStoreId(), userId, StoreStaffPermissions.DEVICE_OPERA);
    }
}
