package com.usky.vpp.util;

import com.usky.common.security.utils.SecurityUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * VPP 审计与编号工具
 */
public final class VppAuditHelper {

    public static final int NOT_DELETED = 0;
    public static final int DELETED = 1;

    private VppAuditHelper() {
    }

    public static void fillCreate(Object entity) {
        LocalDateTime now = LocalDateTime.now();
        invokeSetter(entity, "setCreateTime", now);
        invokeSetter(entity, "setUpdateTime", now);
        invokeSetter(entity, "setDeleteFlag", NOT_DELETED);
        String auditUser = currentUsername();
        if (StringUtils.hasText(auditUser)) {
            invokeSetter(entity, "setCreatedBy", auditUser);
            invokeSetter(entity, "setUpdatedBy", auditUser);
        }
        fillTenantIdIfAbsent(entity);
    }

    public static void fillUpdate(Object entity) {
        invokeSetter(entity, "setUpdateTime", LocalDateTime.now());
        String auditUser = currentUsername();
        if (StringUtils.hasText(auditUser)) {
            invokeSetter(entity, "setUpdatedBy", auditUser);
        }
    }

    public static void fillSoftDelete(Object entity) {
        invokeSetter(entity, "setDeleteFlag", DELETED);
        invokeSetter(entity, "setDeletedAt", LocalDateTime.now());
        fillUpdate(entity);
    }

    public static boolean isDeletedAt(LocalDateTime deletedAt) {
        return deletedAt != null;
    }

    public static void fillSoftDeleteAt(Object entity) {
        fillSoftDelete(entity);
    }

    public static boolean isActive(Integer deleteFlag, LocalDateTime deletedAt) {
        return !isDeleted(deleteFlag) && !isDeletedAt(deletedAt);
    }

    public static boolean isDeleted(Integer deleteFlag) {
        return deleteFlag != null && deleteFlag == DELETED;
    }

    public static String nextApplyNo() {
        return "ACC" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 4).toUpperCase();
    }

    public static String nextEventId() {
        return "EVE_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now())
                + UUID.randomUUID().toString().substring(0, 4).toUpperCase();
    }

    public static String nextInvitationNo() {
        return "INV_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now())
                + UUID.randomUUID().toString().substring(0, 4).toUpperCase();
    }

    public static String nextBillNo() {
        return "BILL_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now())
                + UUID.randomUUID().toString().substring(0, 4).toUpperCase();
    }

    private static String currentUsername() {
        try {
            return SecurityUtils.getUsername();
        } catch (Exception ex) {
            return null;
        }
    }

    private static void fillTenantIdIfAbsent(Object entity) {
        if (StringUtils.hasText(invokeGetter(entity, "getTenantId"))) {
            return;
        }
        Integer tenantId = currentTenantId();
        if (tenantId != null) {
            invokeSetter(entity, "setTenantId", tenantId);
        }
    }

    public static Integer resolveTenantId(String dnId) {
        if (StringUtils.hasText(dnId)) {
            Integer tenantId = VppSiteResourceHelper.resolveTenantIdByUnResourceId(dnId);
            if (tenantId != null) {
                return tenantId;
            }
        }
        return currentTenantId();
    }

    private static String invokeGetter(Object entity, String method) {
        try {
            Method m = entity.getClass().getMethod(method);
            Object value = m.invoke(entity);
            return value != null ? value.toString() : null;
        } catch (Exception ignored) {
            return null;
        }
    }

    private static Integer currentTenantId() {
        try {
            return SecurityUtils.getTenantId();
        } catch (Exception ex) {
            return null;
        }
    }

    private static void invokeSetter(Object entity, String method, Object value) {
        try {
            Method m = entity.getClass().getMethod(method, value.getClass());
            m.invoke(entity, value);
        } catch (Exception ignored) {
            // 部分实体无审计字段时忽略
        }
    }
}
