package com.trade.admin.enterprise.customer.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.trade.admin.enterprise.customer.constant.Constants;
import com.trade.admin.enterprise.customer.domain.CustomerReferralCode;
import com.trade.admin.enterprise.customer.domain.SearchCustomerReferralCode;
import com.trade.admin.enterprise.customer.mapper.CustomerReferralCodeMapper;
import com.trade.admin.enterprise.customer.service.CustomerAssignService;
import com.trade.admin.enterprise.customer.service.CustomerReferralCodeService;
import com.trade.admin.system.domain.entity.SysRole;
import com.trade.admin.system.domain.entity.SysUser;
import com.trade.admin.system.domain.model.LoginUser;
import com.trade.admin.system.security.utils.SecurityUtils;

import com.trade.admin.system.service.ISysRoleService;
import com.trade.admin.system.service.ISysUserService;
import com.trade.common.constant.HttpStatus;
import com.trade.common.core.page.GridPage;
import com.trade.common.exception.ServiceException;
import com.trade.common.utils.LoggerUtil;
import com.trade.common.utils.QRCodeUtil;
import com.trade.common.utils.StringUtils;
import com.trade.common.utils.uuid.SnowflakeIdGenerator;
import com.trade.common.validate.ValidatorGroup;
import com.trade.common.validate.ValidatorUtil;
import com.trade.service.filestorage.entity.TFileStorage;
import com.trade.service.filestorage.enums.FileModuleEnum;
import com.trade.service.filestorage.service.OSSFileService;
import com.trade.service.filestorage.util.FileUtil;
import com.trade.service.system.domain.SysDictData;
import com.trade.service.system.service.ISysDictTypeService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.trade.admin.system.utils.PageUtils;
import org.springframework.transaction.annotation.Transactional;

/**
 * @description: 客户推荐码实现类
 * @Author: wanglang
 * @Date: 2024/5/29 10:47
 * @Version: 1.0
 */
@Service
public class CustomerReferralCodeServiceImpl extends ServiceImpl<CustomerReferralCodeMapper, CustomerReferralCode> implements CustomerReferralCodeService {

    private static final Logger log = LoggerUtil.logger(LoggerUtil.LogFileNameEnum.SYS_LOG);;
    @Resource
    private CustomerReferralCodeMapper customerReferralCodeMapper;
    @Resource
    private ISysRoleService roleService;
    @Resource
    private ISysUserService sysUserService;
    @Resource
    private ISysDictTypeService dictTypeService;
    @Resource
    private OSSFileService ossFileService;
    @Resource
    private CustomerAssignService customerAssignService;

    @Override
    public GridPage<CustomerReferralCode> findBySearch(SearchCustomerReferralCode search) {
        PageUtils.startPage();
        // search.setCurrentUserId(getCurrentLongUserId(ConstantUtil.EC_CUSTOMERREFERRALCODE));
        Page<CustomerReferralCode> page = PageHelper.startPage(search.getPage(), search.getRows());
        List<CustomerReferralCode> rows = customerReferralCodeMapper.findBySearch(search);
        return new GridPage<>(search.getPage(), search.getRows(), page.getTotal(), rows);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean add(CustomerReferralCode code) {
        ValidatorUtil.validator(ValidatorGroup.ValidatorType.ADD, code);
        SysRole role = roleService.selectRoleById(code.getRoleId());
        if (null == role || role.getRoleName().equals(code.getRoleName())) {
            throw new ServiceException("该角色在系统管理模块-权限设置中不存在！", HttpStatus.BAD_REQUEST);
        }
        if (null == code.getUserId()) {
            throw new ServiceException("请选择用户！", HttpStatus.BAD_REQUEST);
        }
        SysUser user = sysUserService.selectUserById(code.getUserId());
        if (null == user || null == user.getId()) {
            throw new ServiceException("请选择用户！", HttpStatus.BAD_REQUEST);
        }
        CustomerReferralCode duplicateUser = customerReferralCodeMapper.getByUserIdAndRoleName(code.getUserId(),
                code.getRoleName());
        if (null != duplicateUser) {
            throw new ServiceException("该用户已经存在推荐码，请选择其他的用户！", HttpStatus.BAD_REQUEST);
        }
        CustomerReferralCode duplicateCode = customerReferralCodeMapper.getByReferralCode(code.getReferralCode());
        if (null != duplicateCode) {
            throw new ServiceException("该推荐码已存在，请输入其他的推荐码！", HttpStatus.BAD_REQUEST);
        }
        String suffix = new SnowflakeIdGenerator(2).nextUniqueId();
        CustomerReferralCode duplicateSuffix = customerReferralCodeMapper.getByReferralUrlSuffix(suffix);
        if (null != duplicateSuffix) {
            throw new ServiceException("该推荐链接已存在！", HttpStatus.BAD_REQUEST);
        }
        LoginUser loginUser = SecurityUtils.getLoginUser();
        code.setRoleId(role.getId());
        code.setRoleName(role.getRoleName());
        code.setLoginName(user.getUserName());
        code.setUserName(user.getNickName());
        code.setOperatorId(loginUser.getUserId());
        code.setOperatorName(loginUser.getUser().getNickName());
        code.setOperatorTime(LocalDateTime.now());
        code.setStatus(true);
        List<SysDictData> sysDictDatas = dictTypeService.selectDictDataByType(Constants.CUSTOMER_REGISTER_PREFIX);
        if (CollectionUtils.isEmpty(sysDictDatas)) {
            throw new ServiceException("系统字典未配置注册地址前缀", HttpStatus.BAD_REQUEST);
        }
        SysDictData sysDictData = sysDictDatas.get(0);
        code.setReferralUrlPrefix(sysDictData.getDictValue());
        code.setReferralUrlSuffix(suffix);
        try {
            // 生成二维码
            String logo = generateLogoPath();
            // 文件存放地址
            String location = "files";
            String fileName = code.getReferralUrlSuffix() + ".jpg";
            File sourceFile = QRCodeUtil.createCode(code.getReferralUrlPrefix() + code.getReferralUrlSuffix(), logo,
                    location, fileName);
            // 保存二维码
            TFileStorage tFileStorage = ossFileService.uploadAndSaveDBRecord(sourceFile,
                    FileModuleEnum.CUSTOMER_REFERRALCODE);
            code.setFileId(tFileStorage.getId());
            customerReferralCodeMapper.add(code);
            if (sourceFile.exists()) {
                sourceFile.delete();
            }
        } catch (Exception e) {
            log.error("生成二维码失败", e);
            throw new ServiceException("新增推荐码出错！", HttpStatus.BAD_REQUEST);
        }
        return true;
    }

    @Override
    public Map<String, Object> getDetailForAdd() {
        return getRoleUserMap();
    }

    @Override
    public Map<String, Object> getDetailForUpdate(Long customerReferralCodeId) {
        Map<String, Object> map = getRoleUserMap();
        CustomerReferralCode code = null;
        if (null != customerReferralCodeId) {
            code = customerReferralCodeMapper.get(customerReferralCodeId);
        }
        map.put("customerReferralCode", code);
        return map;
    }

    @Override
    public boolean update(CustomerReferralCode code) {
        ValidatorUtil.validator(ValidatorGroup.ValidatorType.ADD, code);
        String newCode = code.getReferralCode();
        Long newUserId = code.getUserId();
        if (StringUtils.isBlank(newCode)) {
            throw new ServiceException("推荐码不能为空！", HttpStatus.BAD_REQUEST);
        }
        if (null == newUserId) {
            throw new ServiceException("用户ID不能为空！", HttpStatus.BAD_REQUEST);
        }
        SysUser user = sysUserService.selectUserById(newUserId);
        if (null == user || null == user.getId()) {
            throw new ServiceException("请选择用户！", HttpStatus.BAD_REQUEST);
        }
        CustomerReferralCode exits = customerReferralCodeMapper.get(code.getId());
        if (null == exits) {
            throw new ServiceException("需要修改的推荐码信息不存在！", HttpStatus.BAD_REQUEST);
        }
        if (!exits.isStatus()) {
            throw new ServiceException("禁用状态下不支持修改！", HttpStatus.BAD_REQUEST);
        }
        // 页面上选的用户 与当前的 用户ID不一致：说明有变动，则验证是否与其他的重复
        if (exits.getUserId() != newUserId) {
            CustomerReferralCode duplicateUser = customerReferralCodeMapper.getByUserIdAndRoleName(code.getUserId(),
                    exits.getRoleName());
            if (null != duplicateUser) {
                throw new ServiceException("该用户已经存在推荐码，请选择其他的用户！", HttpStatus.BAD_REQUEST);
            }
        }
        if (!exits.getReferralCode().equals(newCode)) {
            CustomerReferralCode duplicateCode = customerReferralCodeMapper.getByReferralCode(newCode);
            if (null != duplicateCode) {
                throw new ServiceException("该推荐码已存在，请输入其他的推荐码！", HttpStatus.BAD_REQUEST);
            }
        }
        LoginUser currentUser = SecurityUtils.getLoginUser();
        code.setLoginName(user.getUserName());
        code.setUserName(user.getNickName());
        code.setOperatorId(currentUser.getUserId());
        code.setOperatorName(currentUser.getUser().getNickName());
        code.setOperatorTime(LocalDateTime.now());
        customerReferralCodeMapper.update(code);
        return true;
    }

    @Override
    public boolean disable(Long customerReferralCodeId) {
        if (null == customerReferralCodeId) {
            throw new ServiceException("需要禁用的推荐码ID不能为空！", HttpStatus.BAD_REQUEST);
        }
        CustomerReferralCode exits = customerReferralCodeMapper.get(customerReferralCodeId);
        if (null != exits && !exits.isStatus()) {
            throw new ServiceException("该配置信息已经是禁用状态了，无法再次禁用！", HttpStatus.BAD_REQUEST);
        }
        updateStatus(customerReferralCodeId, false);
        return true;
    }

    @Override
    public boolean enable(Long customerReferralCodeId) {
        if (null == customerReferralCodeId) {
            throw new ServiceException("需要启用的推荐码ID不能为空！", HttpStatus.BAD_REQUEST);
        }
        CustomerReferralCode exits = customerReferralCodeMapper.get(customerReferralCodeId);
        if (null != exits && exits.isStatus()) {
            throw new ServiceException("该配置信息已经是启用状态了，无法再次启用！", HttpStatus.BAD_REQUEST);
        }
        updateStatus(customerReferralCodeId, true);
        return true;
    }

    @Override
    public boolean isCustomerReferralCode(Long userId, String roleName) {
        CustomerReferralCode code = customerReferralCodeMapper.getByUserIdAndRoleName(userId, roleName);
        if (null != code) {
            return true;
        }
        return false;
    }

    @Override
    public CustomerReferralCode getByReferralCode(String referralCode) {
        return customerReferralCodeMapper.getByReferralCode(referralCode);
    }

    @Override
    public CustomerReferralCode getByReferralUrlSuffix(String urlSuffix) {
        return customerReferralCodeMapper.getByReferralUrlSuffix(urlSuffix);
    }

    @Override
    public boolean checkCode(String referralCode) {
        if (StringUtils.isNotEmpty(referralCode)) {
            // 查询推荐码属于那个用户
            CustomerReferralCode exits = this.getByReferralCode(referralCode);
            if (null == exits) {
                throw new ServiceException("推荐码不存在！", HttpStatus.BAD_REQUEST);
            }
            if (!exits.isStatus()) {
                throw new ServiceException("推荐码被禁用！", HttpStatus.BAD_REQUEST);
            }
        }
        return true;
    }

    @Override
    public CustomerReferralCode getDetailForView(Long customerReferralCodeId) {
        if (null == customerReferralCodeId) {
            throw new ServiceException("推荐码ID不能为空！", HttpStatus.BAD_REQUEST);
        }
        CustomerReferralCode code = customerReferralCodeMapper.get(customerReferralCodeId);
        if (null == code) {
            throw new ServiceException("该条记录不存在！", HttpStatus.BAD_REQUEST);
        }
        code.setReferralUrl(code.getReferralUrlPrefix() + code.getReferralUrlSuffix());
        if (null != code.getFileId() && code.getFileId() != 0) {
            // FileStorage fileStore = fileStorageService.get(code.getFileId());
            // code.setFileStore(fileStore);
        }
        return code;
    }

    @Override
    public Boolean delete(Long customerReferralCodeId) {
        if (null == customerReferralCodeId) {
            throw new ServiceException("推荐码ID不能为空！", HttpStatus.BAD_REQUEST);
        }
        CustomerReferralCode referralCode = customerReferralCodeMapper.get(customerReferralCodeId);
        if (StringUtils.isNotBlank(referralCode.getRoleName())) {
            // 推荐码不能被占用：BD RC
            boolean occupied = customerAssignService.isOccupiedByUserId(referralCode.getUserId());
            if (occupied) {
                throw new ServiceException("推荐码被占用，请前往客户分配模块，调整客户的分配后后再进行删除操作！", HttpStatus.BAD_REQUEST);
            }
        }
        customerReferralCodeMapper.delete(customerReferralCodeId);
        return true;
    }

    @Override
    public Boolean occupied(Long customerReferralCodeId) {
        if (null == customerReferralCodeId) {
            throw new ServiceException("推荐码ID不能为空！", HttpStatus.BAD_REQUEST);
        }
        CustomerReferralCode referralCode = customerReferralCodeMapper.get(customerReferralCodeId);
        if (null == referralCode) {
            return false;
        }
        return customerAssignService.isOccupiedByUserId(referralCode.getUserId());
    }

    @Override
    public CustomerReferralCode getByUserId(Long userId) {
        return customerReferralCodeMapper.getByUserId(userId);
    }

    public String generateLogoPath() {
        String path = FileUtil.getAbsolutePath("qrcode-logo", ".png", FileModuleEnum.CUSTOMER_REFERRALCODE);
        File file = new File(path);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        OutputStream os;
        try {
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            org.springframework.core.io.Resource[] resources = resolver
                    .getResources("static/qrcode-logo.png/qrcode-logo.png");
            org.springframework.core.io.Resource resource = resources[0];
            InputStream ins = resource.getInputStream();
            os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (IOException e) {
            log.error("保存注册二维码logo失败", e);
        }
        return file.getPath();
    }

    private Map<String, Object> getRoleUserMap() {
        Map<String, Object> map = new HashMap<String, Object>();
        SysRole sysRole = roleService.selectByRoleKey(Constants.BD);
        if (sysRole != null) {
            List<SysUser> userList = new ArrayList<>();
            List<Long> userIds = sysUserService.selectUserIdByRoleId(sysRole.getRoleId());
            for (Long userId : userIds) {
                SysUser user = sysUserService.selectUserById(userId);
                if (null != user) {
                    userList.add(user);
                }
            }
            map.put(Constants.BD, userList);
        }
        return map;
    }

    private void updateStatus(Long customerReferralCodeId, boolean status) {
        LoginUser currentUser = SecurityUtils.getLoginUser();
        CustomerReferralCode code = new CustomerReferralCode();
        code.setId(customerReferralCodeId);
        code.setStatus(status);
        code.setOperatorId(currentUser.getUserId());
        code.setOperatorName(currentUser.getUser().getNickName());
        code.setOperatorTime(LocalDateTime.now());
        customerReferralCodeMapper.updateStatus(code);
    }
}
