package com.jy.log.service.impl;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jy.framework.exception.ServiceException;
import com.jy.framework.model.base.BaseIdPo;
import com.jy.framework.utils.AssertUtil;
import com.jy.log.dao.LogUserOperationDao;
import com.jy.log.model.dto.LogUserOperationDto;
import com.jy.log.model.dto.LogUserOperationSelectDto;
import com.jy.log.model.entity.LogUserOperation;
import com.jy.log.model.vo.LogUserOperationVo;
import com.jy.log.record.RecordAuditAspect;
import com.jy.log.service.LogUserOperationService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 用户操作日志 服务实现类
 * </p>
 *
 * @author
 * @since 2025-08-12
 */
@Slf4j
@Service
public class LogUserOperationServiceImpl implements LogUserOperationService {

    @Resource
    private LogUserOperationDao logUserOperationDao;

    @Override
    public Page<LogUserOperationVo> getPage(LogUserOperationSelectDto dto) {
        return logUserOperationDao.getPage(dto);
    }

    @Override
    public LogUserOperationVo getDetail(Long id) {
        LogUserOperationVo vo = logUserOperationDao.getDetail(id);
        AssertUtil.notNull(vo, "未知数据");
        return vo;
    }

    @Override
    public void add(LogUserOperation dto) {
        logUserOperationDao.save(dto);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(LogUserOperationDto dto) {
        boolean update = logUserOperationDao.update(q -> q
                .eq(BaseIdPo::getId, dto.getId())
                .eq(LogUserOperation::getAuditStatus, 0)
                .set(LogUserOperation::getAuditStatus, dto.getAuditStatus())
                .set(LogUserOperation::getRemark, dto.getRemark())
                .set(LogUserOperation::getAuditTime, new Date())
        );

        if (!update) {
            throw new ServiceException("已被审核");
        }

        if (dto.getAuditStatus() == 2) {
            return;
        }

        try {
            RecordAuditAspect.EXIST_FUN.set(true);

            // 获取springBean
            Object bean = SpringUtil.getBean(Class.forName(dto.getServiceBeanName()));

            // 获取入参class
            Class<?>[] array = JSONArray.parseArray(dto.getReqClasses()).toJavaList(String.class).stream()
                    .map(item -> {
                        try {
                            return Class.forName(item);
                        } catch (ClassNotFoundException e) {
                            throw new RuntimeException(e);
                        }
                    }).toArray(Class[]::new);

            // 获取执行方法
            Method method = bean.getClass().getMethod(dto.getMethodName(), array);

            // 获取方法参数
            Object[] params = new Object[array.length];
            List<JSONObject> paramList = JSONArray.parseArray(dto.getOperationData()).toJavaList(JSONObject.class);
            for (int i = 0; i < paramList.size(); i++) {
                params[i] = paramList.get(i).toJavaObject(array[i]);
            }

            // 执行方法
            method.invoke(bean, params);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException("业务执行失败");
        } finally {
            RecordAuditAspect.EXIST_FUN.remove();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<Long> idList) {
        logUserOperationDao.removeBatchByIds(idList);
    }

    @Override
    public boolean hasPendingAuditByBusinessId(Long businessId) {
        return logUserOperationDao.exists(q -> q.eq(LogUserOperation::getBusinessId, businessId)
                .eq(LogUserOperation::getAuditStatus, 0));
    }

}
