package com.zc.business.interfaces;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.service.ISysDeptService;
import com.zc.business.domain.DcDevice;
import com.zc.business.domain.DcOperLog;
import com.zc.business.service.IDcDeviceService;
import com.zc.business.service.IDcOperLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Aspect
@Component
public class OperationLogAspect {

    @AfterReturning(pointcut = "@annotation(operationLog)", returning = "jsonResult")
    public void AfterReturning(JoinPoint joinPoint, OperationLog operationLog, Object jsonResult) throws Throwable {
        System.out.println("运行成功");
        around((ProceedingJoinPoint) joinPoint, operationLog, "0", jsonResult, null);
    }

    @AfterThrowing(value = "@annotation(operationLog)", throwing = "e")
    public void AfterThrowing(JoinPoint joinPoint, OperationLog operationLog, Exception e) throws Throwable {
        System.out.println("运行失败");
        around((ProceedingJoinPoint) joinPoint, operationLog, "1", null, e);
    }

    public void around(ProceedingJoinPoint joinPoint, OperationLog operationLog, String state, Object jsonResult, Exception exception) throws Throwable {

        ISysDeptService deptService = SpringUtils.getBean(ISysDeptService.class);
        IDcOperLogService dcOperLogService = SpringUtils.getBean(IDcOperLogService.class);
        IDcDeviceService dcDeviceService = SpringUtils.getBean(IDcDeviceService.class);

        try {
            DcOperLog dcOperLog = new DcOperLog();
            String operUrl = operationLog.operUrl();
            LoginUser loginUser;
            try {

                loginUser = SecurityUtils.getLoginUser();
            }catch (Exception e){
                loginUser = null;
            }
            Object[] pointArgs = joinPoint.getArgs();

            HttpServletRequest request;
            try {

                request = ServletUtils.getRequest();
            }catch (Exception e){
                request = null;
            }
            if (operUrl.contains("batchFunctions")) {
                if (loginUser != null) {
                    SysDept sysDept = deptService.selectDeptById(loginUser.getDeptId());

                    dcOperLog.setOperName(loginUser.getUsername());
                    dcOperLog.setDeptName(sysDept.getDeptName());
                    dcOperLog.setOperLocation(loginUser.getLoginLocation());
                }
                dcOperLog.setOperType("2");
                dcOperLog.setOperIp(IpUtils.getIpAddr(request));
                dcOperLog.setJsonResult(String.valueOf(joinPoint.proceed(pointArgs)));
                dcOperLog.setOperTime(new Date());


                HashMap<String, ArrayList<JSONObject>> pointArg = (HashMap<String, ArrayList<JSONObject>>) pointArgs[0];
                ArrayList<JSONObject> devices = pointArg.get("devices");
                ArrayList<JSONObject> functions = pointArg.get("functions");
                for (Object dev : devices) {
                    JSONObject device = (JSONObject) JSON.toJSON(dev);
                    LambdaQueryWrapper<DcDevice> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                    lambdaQueryWrapper.eq(DcDevice::getId, device.get("id"));
                    List<DcDevice> list = dcDeviceService.list(lambdaQueryWrapper);
                    if (list.size() > 0) {
                        DcDevice dcDevice = list.get(0);
                        dcOperLog.setDcDeviceId(String.valueOf(dcDevice.getId()));
                        dcOperLog.setDcDeviceName(dcDevice.getDeviceName());
                        dcOperLog.setDcDeviceType(dcDevice.getDeviceType());
                    }
                    for (Object fun : functions) {
                        JSONObject function = (JSONObject) JSON.toJSON(fun);
                        dcOperLog.setOperParam(function.getString("params"));
                        dcOperLogService.addDcOperLog(dcOperLog);
                    }
                }
            } else if (operUrl.contains("functions")) {
                LambdaQueryWrapper<DcDevice> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(DcDevice::getIotDeviceId, pointArgs[0]);
                List<DcDevice> list = dcDeviceService.list(lambdaQueryWrapper);
                if (list.size() > 0) {
                    DcDevice dcDevice = list.get(0);
                    dcOperLog.setDcDeviceId(String.valueOf(dcDevice.getId()));
                    dcOperLog.setDcDeviceName(dcDevice.getDeviceName());
                    dcOperLog.setDcDeviceType(dcDevice.getDeviceType());
                }
                if (loginUser != null) {
                    SysDept sysDept = deptService.selectDeptById(loginUser.getDeptId());

                    dcOperLog.setOperName(loginUser.getUsername());
                    dcOperLog.setDeptName(sysDept.getDeptName());
                    dcOperLog.setOperLocation(loginUser.getLoginLocation());
                    dcOperLog.setOperType("0");
                } else {
                    dcOperLog.setOperType("1");
                }
                dcOperLog.setOperIp(IpUtils.getIpAddr(request));
                dcOperLog.setOperParam(Arrays.toString(joinPoint.getArgs()));
                dcOperLog.setJsonResult(String.valueOf(joinPoint.proceed(pointArgs)));
                if (Objects.equals(state, "0")) {
                    dcOperLog.setStatus(0);
                } else {
                    dcOperLog.setStatus(1);
                }
                dcOperLog.setOperTime(new Date());
                dcOperLogService.addDcOperLog(dcOperLog);
            }

        } catch (Exception e) {
            throw e;
        }
    }
}