package com.sunyard.chsm.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sunyard.chsm.auth.AppUser;
import com.sunyard.chsm.auth.UserContext;
import com.sunyard.chsm.enums.KeyCategory;
import com.sunyard.chsm.enums.KeyStatus;
import com.sunyard.chsm.mapper.KeyInfoMapper;
import com.sunyard.chsm.model.dto.KeyInfoDTO;
import com.sunyard.chsm.model.entity.KeyInfo;
import com.sunyard.chsm.param.KeyCreateReq;
import com.sunyard.chsm.param.KeyInfoQuery;
import com.sunyard.chsm.param.KeyInfoResp;
import com.sunyard.chsm.param.KeyUpdateReq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author liulu
 * @since 2024/12/16
 */
@Slf4j
@Service
@Transactional
public class KeyManageService {

    @Resource
    private KeyInfoMapper keyInfoMapper;
    @Resource
    private KeyInfoService keyInfoService;

    public Page<KeyInfoResp> queryPageList(KeyInfoQuery query) {
        KeyInfoDTO.Query nq = new KeyInfoDTO.Query();
        nq.setKeyType(Optional.ofNullable(query.getKeyType()).map(KeyCategory::getCode).orElse(null));
        nq.setStatus(Optional.ofNullable(query.getStatus()).map(KeyStatus::getCode).orElse(null));
        nq.setAppId(UserContext.getCurrentAppId());
        Page<KeyInfoDTO.KeyView> page = keyInfoService.selectPageList(nq);
        List<KeyInfoDTO.KeyView> records = page.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        }
        List<KeyInfoResp> viewList = records.stream()
                .map(it -> {
                    KeyInfoResp resp = new KeyInfoResp();
                    BeanUtils.copyProperties(it, resp);
                    resp.setKeyId(it.getId());
                    return resp;
                })
                .collect(Collectors.toList());

        return new Page<KeyInfoResp>(page.getCurrent(), page.getSize(), page.getTotal()).setRecords(viewList);
    }

    public KeyInfoResp queryInfo(Long id) {
        checkIds(Collections.singletonList(id));
        KeyInfoDTO.KeyView view = keyInfoService.selectById(id);
        KeyInfoResp resp = new KeyInfoResp();
        BeanUtils.copyProperties(view, resp);
        resp.setKeyId(view.getId());
        return resp;
    }

    public Long create(KeyCreateReq req) {
        KeyInfoDTO.KeySave save = new KeyInfoDTO.KeySave();
        save.setApplicationId(UserContext.getCurrentAppId());
        save.setKeyTemplateCode(req.getKeyTemplateCode());
        save.setGenNumber(req.getGenNumber());
        return keyInfoService.save(save);
    }


    public void update(KeyUpdateReq req) {
        Assert.notNull(req.getEffectiveTime(), "新密钥生效时间不能为空");
        checkIds(req.getIds());
        KeyInfoDTO.KeyUpdate update = new KeyInfoDTO.KeyUpdate();
        update.setIds(req.getIds());
        update.setEffectiveTime(req.getEffectiveTime());
        keyInfoService.update(update);
    }

    public void enableKey(List<Long> ids) {
        checkIds(ids);
        keyInfoService.enableKey(ids);
    }

    public void disableKey(List<Long> ids) {
        checkIds(ids);
        keyInfoService.disableKey(ids);
    }

    public void archiveKey(List<Long> ids) {
        checkIds(ids);
        keyInfoService.archiveKey(ids);
    }

    public void destroyKey(List<Long> ids) {
        checkIds(ids);
        keyInfoService.destroyKey(ids);
    }


    private void checkIds(List<Long> ids) {
        AppUser appUser = UserContext.getCurrentUser();
        List<KeyInfo> keyInfos = keyInfoMapper.selectBatchIds(ids);
        Assert.notEmpty(keyInfos, "密钥ID不正确");
        String msg = keyInfos.stream()
                .filter(it -> !Objects.equals(it.getApplicationId(), appUser.getAppId()))
                .map(KeyInfo::getCode)
                .collect(Collectors.joining(", "));
        Assert.isTrue(ObjectUtils.isEmpty(msg), "密钥ID:" + msg + "不属于当前应用, 无权操作");
    }

}
