package com.fzm.mall.server.admin.config;

import com.fzm.mall.server.admin.annotation.AdminLog;
import com.fzm.mall.server.admin.auth_center.entity.dto.*;
import com.fzm.mall.server.admin.enums.log.OperateModuleEnum;
import com.fzm.mall.server.admin.enums.log.OperateTypeEnum;
import com.fzm.mall.server.admin.enums.response.MallResponseEnum;
import com.fzm.mall.server.admin.goods_center.entity.dto.*;
import com.fzm.mall.server.admin.goods_center.enums.status.SpuStatusEnum;
import com.fzm.mall.server.admin.home_page.entity.dto.*;
import com.fzm.mall.server.admin.home_page.enums.status.MerchantRegisterEnum;
import com.fzm.mall.server.admin.home_page.enums.type.RepairPwdTypeEnum;
import com.fzm.mall.server.admin.home_page.service.IAdminService;
import com.fzm.mall.server.admin.repo.ResponseVO;
import com.fzm.mall.server.admin.system.service.IAdminLogService;
import com.fzm.mall.server.admin.user_center.entity.dto.UserLockDTO;
import com.fzm.mall.server.admin.user_center.enums.status.UserLockStatusEnum;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author wangp
 * @date 2021/2/26 18:13
 * @description 日志切面
 * @since JDK 1.8
 */
@Aspect
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LogAspect {

    private final IAdminLogService adminLogService;
    private final IAdminService adminService;

    @Pointcut("@annotation(com.fzm.mall.server.admin.annotation.AdminLog)")
    public void adminLogAnnotationPointcut() {
    }

    /**
     * 后置返回通知
     * 如果参数中的第一个参数为JoinPoint，则第二个参数为返回值的信息
     * 如果参数中的第一个参数不为JoinPoint，则第一个参数为returning中对应的参数
     * returning 只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知，否则不执行
     *
     * @param joinPoint
     * @param resObj
     */
    @AfterReturning(value = "adminLogAnnotationPointcut()", returning = "resObj")
    public void afterReturningAdviceADD(JoinPoint joinPoint, ResponseVO resObj) throws Exception {
        if (!resObj.getCode().equals(MallResponseEnum.SUCCESS.code())) {
            return;
        }

        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();

        // 获取管理员id
        String adminId = request.getHeader("adminId");
        Object obj = joinPoint.getArgs()[0];

        Map<String, Object> annotationValue = getAdminLogAnnotationValue(joinPoint);
        String description = annotationValue.get("description").toString();
        Integer module = Integer.parseInt(annotationValue.get("module").toString());
        Integer opType = Integer.parseInt(annotationValue.get("opType").toString());
        String note = "";

        switch (OperateModuleEnum.getByModule(module)) {
            case HOME_PAGE:
                note = homePageSwitch(opType, obj);
                break;
            case GOODS_CENTER:
                note = goodsCenterSwitch(opType, obj);
                break;
            case ORDER_CENTER:
                break;
            case SHOP_CENTER:
                break;
            case OPERATE_CENTER:
                break;
            case DISTRIBUTION_CENTER:
                break;
            case MESSAGE_CENTER:
                break;
            case CUSTOMER_SERVICE_CENTER:
                break;
            case USER_CENTER:
                note = userCenterSwitch(opType, obj);
                break;
            case FINANCE_CENTER:
                note = financeCenterSwitch(opType, obj);
                break;
            case AUTH_CENTER:
                note = authCenterSwitch(opType, obj);
                break;
            case DATA_CENTER:
                break;
            case SYSTEM_CENTER:
                break;
        }

        adminLogService.add(adminId, module, description, note);
    }

    //首页日志备注
    public String homePageSwitch(Integer opType, Object obj) {
        String note = "";
        switch (OperateTypeEnum.getByBehavior(opType)) {
            case LOGIN:
                note = "登陆账号:" + ((LoginDTO) obj).getAccount();
                break;
            case REPAIR_PWD:
                Integer type = ((RepairPwdDTO) obj).getType();
                if (type.equals(RepairPwdTypeEnum.PWD.getType())) {
                    note = "原密码修改密码";
                }
                if (type.equals(RepairPwdTypeEnum.SMS.getType())) {
                    note = "手机验证码修改原密码";
                }
                if (type.equals(RepairPwdTypeEnum.RESET.getType())) {
                    note = "重置密码";
                }
                break;
            case REGISTER:
                note = "注册账号:" + ((RegisterDTO) obj).getPhone();
                break;
            case MERCHANT:
                note = "商户账号:" + ((MerchantDTO) obj).getRegisterPhone();
                break;
            case FORGET_RESET_PWD:
                note = "账号:" + ((ResetPwdDTO) obj).getPhone();
                break;
        }

        return note;
    }

    //商品中心日志备注
    public String goodsCenterSwitch(Integer opType, Object obj) {
        String note = "";

        switch (OperateTypeEnum.getByBehavior(opType)) {
            case ADD_GOODS:
                note = ((GoodsSpuDTO) obj).getName();
                break;
            case EDIT_GOODS:
                note = ((GoodsEditDTO) obj).getGoodsId();
                break;
            case ON_OFF:
                OnOffDTO dto1 = (OnOffDTO) obj;
                Integer type1 = dto1.getType();
                String goodsId1 = dto1.getGoodsId();
                if (type1.equals(SpuStatusEnum.ON.getStatus())) {
                    note = goodsId1 + "-上架";
                }
                if (type1.equals(SpuStatusEnum.OFF.getStatus())) {
                    note = goodsId1 + "-下架";
                }
                break;
            case DEFAULT_FIRST:
                note = obj.toString();
                break;
            case GOODS_CHECK:
                GoodsCheckDTO dto2 = (GoodsCheckDTO) obj;
                Integer status = dto2.getStatus();
                String goodsId2 = dto2.getGoodsId();
                if (status.equals(SpuStatusEnum.CHECK_FAIL.getStatus())) {
                    note = goodsId2 + "-审核失败";
                }
                if (status.equals(SpuStatusEnum.CHECK_PASS.getStatus())) {
                    note = goodsId2 + "-审核成功";
                }
                break;
            case ADD_INTEGRAL:
                note = ((IntegralExchangeDTO) obj).getName();
                break;
            case REPAIR_INTEGRAL_STOCK:
                StockDTO dto3 = (StockDTO) obj;
                String goodsId3 = dto3.getGoodsId();
                Integer stock = dto3.getStock();
                note = goodsId3 + "-" + stock;
                break;
            case REPAIR_INTEGRAL_VALUE:
                IntegralDTO dto4 = (IntegralDTO) obj;
                String goodsId4 = dto4.getGoodsId();
                Integer integral = dto4.getIntegral();
                note = goodsId4 + "-" + integral;
                break;
        }

        return note;
    }

    //用户中心日志备注
    public String userCenterSwitch(Integer opType, Object obj) {
        String note = "";

        switch (OperateTypeEnum.getByBehavior(opType)) {
            case USER_LOCK:
                UserLockDTO dto1 = (UserLockDTO) obj;
                Integer lock1 = dto1.getLock();
                String uid1 = dto1.getUid();
                if (lock1.equals(UserLockStatusEnum.NORMAL.getStatus())) {
                    note = uid1 + "-解锁";
                }
                if (lock1.equals(UserLockStatusEnum.LOCKING.getStatus())) {
                    note = uid1 + "-锁定";
                }
                break;
            case MERCHANT_LOCK:
                MerchantLockDTO dto2 = (MerchantLockDTO) obj;
                Integer lock2 = dto2.getLock();
                String merchantId2 = dto2.getMerchantId();
                if (lock2.equals(MerchantRegisterEnum.NORMAL.getStatus())) {
                    note = merchantId2 + "-解锁";
                }
                if (lock2.equals(MerchantRegisterEnum.LOCKING.getStatus())) {
                    note = merchantId2 + "-锁定";
                }
                break;
            case RESET_PWD:
                note = obj.toString();
                break;
            case MERCHANT_CHECK:
                MerchantCheckDTO dto4 = (MerchantCheckDTO) obj;
                String merchantId4 = dto4.getMerchantId();
                Integer check4 = dto4.getCheck();
                if (check4.equals(MerchantRegisterEnum.EXAMINE_FAIL.getStatus())) {
                    note = merchantId4 + "-审核失败";
                }
                if (check4.equals(MerchantRegisterEnum.WAIT_PAY.getStatus())) {
                    note = merchantId4 + "-审核通过";
                }
                break;
        }

        return note;
    }

    //财务中心日志备注
    public String financeCenterSwitch(Integer opType, Object obj) {
        String note = "";

        switch (OperateTypeEnum.getByBehavior(opType)) {
        }

        return note;
    }

    //首页日志备注
    public String authCenterSwitch(Integer opType, Object obj) {
        String note = "";
        switch (OperateTypeEnum.getByBehavior(opType)) {
            case ADD_ROLE:
                note = "角色名称：" + ((RoleDTO) obj).getRoleName();
                break;
            case DEL_ROLE:
            case DISABLE_ROLE:
                note = "角色id：" + obj;
                break;
            case EDIT_ROLE:
                note = "角色id：" + ((RoleEditDTO) obj).getRoleId();
                break;
            case ADD_ADMIN:
                note = "管理员账号：" + ((AddAdminDTO) obj).getAccount();
                break;
            case DEL_ADMIN:
            case DISABLE_ADMIN:
                note = "管理员id：" + obj;
                break;
            case RESET_ADMIN_PWD:
                note = "管理员id：" + ((ResetAdminPwdDTO) obj).getAdminId();
                break;
            case REPAIR_ADMIN_ROLE:
                note = "管理员id：" + ((RepairAdminRoleDTO) obj).getAdminId() +
                        "--角色id：" + ((RepairAdminRoleDTO) obj).getRoleId();
                break;
        }

        return note;
    }

    /**
     * 获取@AdminLog 注解上信息
     *
     * @param joinPoint
     * @return map
     * @throws Exception
     */
    public Map<String, Object> getAdminLogAnnotationValue(JoinPoint joinPoint) throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        Map<String, Object> map = new HashMap<>();

        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] classes = method.getParameterTypes();
                if (classes.length == arguments.length) {
                    //取入参数据
                    String description = method.getAnnotation(AdminLog.class).description();
                    Integer module = method.getAnnotation(AdminLog.class).module().getModule();
                    Integer opType = method.getAnnotation(AdminLog.class).opType().getBehavior();
                    map.put("description", description);
                    map.put("module", module);
                    map.put("opType", opType);
                    break;
                }
            }
        }

        return map;
    }

}
