package com.sckw.system.aspect;

import com.sckw.core.exception.SystemException;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.system.service.KwsDataPermissionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Arrays;
import java.util.List;

/**
 * 角色删除后级联逻辑删除角色数据权限。
 *
 * <p>不侵入 {@code KwsRoleService#deleteByKey(String)} 原有代码逻辑，通过切面在同一事务中补充删除
 * {@code kws_data_permission} 表中对应角色的数据权限记录。</p>
 *
 * @author codex
 */
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
@Order(Ordered.HIGHEST_PRECEDENCE)
public class KwsRoleDeleteDataPermissionAspect {

    private final KwsDataPermissionService kwsDataPermissionService;

    private final PlatformTransactionManager transactionManager;

    /**
     * 环绕角色删除方法，保证角色删除与数据权限逻辑删除处于同一事务。
     *
     * @param joinPoint 原始角色删除方法切点
     * @param ids       角色ID字符串，多个ID使用英文逗号分隔
     * @return 原始方法返回值
     * @throws Throwable 原始方法或数据权限删除失败时抛出异常，触发事务回滚
     */
    @Around(value = "execution(public void com.sckw.system.service.KwsRoleService.deleteByKey(String)) && args(ids)")
    public Object deleteDataPermissionAfterRoleDelete(ProceedingJoinPoint joinPoint, String ids) throws Throwable {
        List<Long> roleIds = parseRoleIds(ids);
        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
        try {
            return transactionTemplate.execute(status -> {
                try {
                    Object result = joinPoint.proceed();
                    kwsDataPermissionService.deleteByRoleIds(roleIds);
                    log.info("角色删除后已逻辑删除数据权限, roleIds={}", roleIds);
                    return result;
                } catch (Throwable throwable) {
                    status.setRollbackOnly();
                    log.error("角色删除或数据权限逻辑删除失败, roleIds={}", roleIds, throwable);
                    throw new RoleDeleteDataPermissionException(throwable);
                }
            });
        } catch (RoleDeleteDataPermissionException e) {
            throw e.getCause();
        }
    }

    /**
     * 解析角色ID字符串。
     *
     * @param ids 角色ID字符串
     * @return 角色ID列表
     */
    static List<Long> parseRoleIds(String ids) {
        if (StringUtils.isBlank(ids) || StringUtils.isBlank(ids.trim())) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, "角色ID不能为空");
        }
        try {
            return Arrays.stream(ids.split(","))
                    .map(String::trim)
                    .filter(StringUtils::isNotBlank)
                    .map(Long::parseLong)
                    .toList();
        } catch (NumberFormatException e) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, "角色ID格式错误");
        }
    }

    /**
     * 事务模板中转运行时异常，保留原始异常继续向上抛出。
     */
    private static class RoleDeleteDataPermissionException extends RuntimeException {

        RoleDeleteDataPermissionException(Throwable cause) {
            super(cause);
        }
    }
}
