package org.dromara.system.service.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.system.zwy.client.HmacClient;
import org.springframework.stereotype.Service;

import cn.hutool.core.util.ReflectUtil;

import org.dromara.common.core.domain.R;
import org.dromara.system.service.ISysLogininforService;
import org.dromara.system.service.ISysOperLogService;
import org.dromara.system.service.ISysRoleService;
import org.dromara.system.service.ISysUserService;

import org.dromara.system.zwy.domain.HmacCheckRequest;
import org.dromara.system.zwy.utils.ObjectHashGenerator;


import java.nio.charset.StandardCharsets;
import java.util.*;

@RequiredArgsConstructor
@Service
@Slf4j
public class SysHmacService {

    private final HmacClient hmacClient;

    private final ISysOperLogService operLogService;

    private final ISysLogininforService loginInfoService;

    private final ISysUserService userService;

    private final ISysRoleService roleService;




    public R<Map<String, Object>> verify(HmacCheckRequest request) {
        Object bizObj;

        switch (request.getBizType()) {
            case "operLog":
                bizObj = operLogService.selectOperLogById(request.getId());
                break;
            case "loginInfo":
                bizObj = loginInfoService.selectLogininById(request.getId());
                break;
            case "sysUser":
                bizObj = userService.selectSysUserById(request.getId());
                break;
            case "sysRole":
                bizObj = roleService.selectSysRoleById(request.getId());
                break;
            default:
                return R.fail("不支持的业务类型: " + request.getBizType());
        }

        if (bizObj == null) {
            return R.fail("数据不存在");
        }

        // 2. 计算拼接字符串
        String concatenatedValues;
        if (request.getFields() == null || request.getFields().isEmpty()) {
            concatenatedValues = ObjectHashGenerator.generateHash(bizObj);
        } else {
            List<String> fieldValues = new ArrayList<>();
            for (String field : request.getFields()) {
                Object val = ReflectUtil.getFieldValue(bizObj, field);
                fieldValues.add(val == null ? "null" : val.toString());
            }
            Collections.sort(fieldValues);
            concatenatedValues = String.join("", fieldValues);
        }

        String base64 = Base64.getEncoder().encodeToString(concatenatedValues.getBytes(StandardCharsets.UTF_8));

        String newHmac;
        try {
            newHmac = hmacClient.calculateHmac(base64);
//            newHmac = base64;
        } catch (Exception e) {
            log.error("调用 HMAC 服务失败", e);
            return R.fail("调用 HMAC 服务失败");
        }

        String originHmac = null;
        try {
            if (bizObj instanceof Map) {
                // 从 Map 中尝试拿“主业务对象”的 hmac
                Object mainObj = ((Map<?, ?>) bizObj).get("user");
                if (mainObj == null) {
                    mainObj = ((Map<?, ?>) bizObj).get("role");
                }
                if (mainObj != null) {
                    originHmac = (String) mainObj.getClass().getMethod("getHmac").invoke(mainObj);
                }
            } else {
                // bizObj 是单个实体，直接反射取getHmac()
                originHmac = (String) bizObj.getClass().getMethod("getHmac").invoke(bizObj);
            }
        } catch (Exception e) {
            log.warn("获取对象中hmac字段失败", e);
        }


        if (originHmac == null || originHmac.isEmpty()) {
            return R.fail("原始HMAC为空，无法校验完整性");
        }

        boolean match = Objects.equals(originHmac, newHmac);

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("match", match);
        resultMap.put("expected", originHmac);
        resultMap.put("actual", newHmac);

        return R.ok(resultMap);
    }
}

