package com.malk.pro.service.dingtalk;

import com.malk.pro.tenant.TenantContext;
import com.malk.pro.tenant.TenantProfile;
import com.malk.pro.tenant.VendorCredential;
import com.malk.server.common.McException;
import com.malk.service.dingtalk.DDClient;
import com.malk.utils.UtilToken;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 多租户钉钉服务（mjava-pro 容器）
 *
 * <p>capability: multi-tenant-runtime。从 {@link TenantContext} 取当前租户的钉钉凭据，
 * 自动走 {@code {tenantId}:dingtalk:{appKey}} 命名空间缓存 access_token，
 * 避免不同租户互相覆盖。</p>
 *
 * <p>调用方范式：业务先 {@code @Autowired DynamicDDService}，
 * 再用 {@link #getAccessToken()} 拿到当前租户 token，传给具体 {@code DDClient_*} 方法。</p>
 */
@Slf4j
@Service
public class DynamicDDService {

    private static final String VENDOR = com.malk.server.dingtalk.DDConf.NS;
    // 钉钉 access_token 官方 TTL 7200s；UtilToken.put 内部会再扣 5s 容错
    private static final long DEFAULT_TOKEN_TTL_MS = 7200_000L;

    @Autowired
    private DDClient ddClient;

    /**
     * 当前租户的钉钉凭据。租户/凭据缺失抛 {@link McException}。
     */
    public VendorCredential currentCredential() {
        TenantProfile profile = TenantContext.current();
        if (profile == null) {
            throw new McException("TENANT_REQUIRED", "TenantContext 未注入，无法获取钉钉凭据");
        }
        VendorCredential credential = profile.credential(VENDOR);
        if (credential == null) {
            throw new McException("VENDOR_NOT_CONFIGURED",
                    "tenant=" + profile.getTenantId() + " 未配置 dingtalk 凭据");
        }
        return credential;
    }

    /**
     * 当前租户 access_token，按 {tenantId}:dingtalk:{appKey} 命名空间缓存。
     */
    public String getAccessToken() {
        VendorCredential credential = currentCredential();
        String tenantId = TenantContext.currentTenantId();
        String key = VENDOR + ":" + credential.getAppKey();
        String token = UtilToken.get(tenantId, key);
        if (StringUtils.isNotBlank(token)) {
            return token;
        }
        token = ddClient.getAccessToken(credential.getAppKey(), credential.getAppSecret());
        if (StringUtils.isBlank(token)) {
            throw new McException("DD_TOKEN_FAILED",
                    "tenant=" + tenantId + " 钉钉 token 获取失败");
        }
        UtilToken.put(tenantId, key, token, DEFAULT_TOKEN_TTL_MS);
        return token;
    }

    public String currentAppKey() {
        return currentCredential().getAppKey();
    }

    public String currentAppSecret() {
        return currentCredential().getAppSecret();
    }

    public String currentCorpId() {
        return currentCredential().getCorpId();
    }
}
