package com.gxwebsoft.app.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.app.mapper.AppCredentialMapper;
import com.gxwebsoft.app.service.AppCredentialService;
import com.gxwebsoft.app.entity.AppCredential;
import com.gxwebsoft.app.param.AppCredentialParam;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 应用密钥凭证Service实现
 *
 * @author 科技小王子
 * @since 2026-03-28 21:29:43
 */
@Slf4j
@Service
public class AppCredentialServiceImpl extends ServiceImpl<AppCredentialMapper, AppCredential> implements AppCredentialService {

    @Override
    public PageResult<AppCredential> pageRel(AppCredentialParam param) {
        PageParam<AppCredential, AppCredentialParam> page = new PageParam<>(param);
        page.setDefaultOrder("sort_number asc, create_time desc");
        List<AppCredential> list = baseMapper.selectPageRel(page, param);
        // 脱敏处理：appSecret 不对外展示（仅创建/重置时返回明文）
        list.forEach(this::maskSecret);
        return new PageResult<>(list, page.getTotal());
    }

    @Override
    public List<AppCredential> listRel(AppCredentialParam param) {
        List<AppCredential> list = baseMapper.selectListRel(param);
        PageParam<AppCredential, AppCredentialParam> page = new PageParam<>();
        page.setDefaultOrder("sort_number asc, create_time desc");
        list = page.sortRecords(list);
        list.forEach(this::maskSecret);
        return list;
    }

    @Override
    public AppCredential getByIdRel(Integer id) {
        AppCredentialParam param = new AppCredentialParam();
        param.setId(id.longValue());
        AppCredential credential = param.getOne(baseMapper.selectListRel(param));
        if (credential != null) {
            maskSecret(credential);
        }
        return credential;
    }

    @Override
    public AppCredential createCredential(AppCredential credential) {
        // 生成 AppID：app_ + 16位随机字符串
        String appId = "app_" + CommonUtil.randomUUID16();
        // 生成 AppSecret：32位随机字符串（大小写字母+数字）
        String appSecret = generateSecretValue();

        credential.setAppId(appId);
        credential.setAppSecret(appSecret);
        // 默认状态正常
        if (credential.getStatus() == null) {
            credential.setStatus(0);
        }
        if (StrUtil.isBlank(credential.getType())) {
            credential.setType("server");
        }

        save(credential);
        log.info("创建凭证成功，websiteId={}, appId={}", credential.getWebsiteId(), appId);
        // 返回含明文 secret 的对象（仅此一次）
        return credential;
    }

    @Override
    public AppCredential resetSecret(Long id) {
        AppCredential credential = getById(id);
        if (credential == null) {
            throw new RuntimeException("凭证不存在");
        }
        String newSecret = generateSecretValue();
        credential.setAppSecret(newSecret);
        updateById(credential);
        log.info("重置凭证密钥成功，id={}", id);
        return credential;
    }

    @Override
    public boolean updateStatus(Long id, Integer status) {
        return update(new LambdaUpdateWrapper<AppCredential>()
                .eq(AppCredential::getId, id)
                .set(AppCredential::getStatus, status));
    }

    /**
     * 生成32位随机 AppSecret
     */
    private String generateSecretValue() {
        // 格式：8位-8位-8位-8位（类似 UUID 格式，便于复制）
        return RandomUtil.randomString(8) + "-"
                + RandomUtil.randomString(8) + "-"
                + RandomUtil.randomString(8) + "-"
                + RandomUtil.randomString(8);
    }

    /**
     * 脱敏处理：将 appSecret 替换为掩码
     */
    private void maskSecret(AppCredential credential) {
        if (StrUtil.isNotBlank(credential.getAppSecret())) {
            // 只保留前4位，其余用 * 替代
            String secret = credential.getAppSecret();
            credential.setAppSecret(secret.substring(0, Math.min(4, secret.length())) + "**********************");
        }
    }

}
