package com.yeejoin.precontrol.common.aop;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.JoinPoint.StaticPart;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yeejoin.precontrol.common.entity.Company;
import com.yeejoin.precontrol.common.entity.HazardousWork;
import com.yeejoin.precontrol.common.entity.OpsLog;
import com.yeejoin.precontrol.common.entity.Person;
import com.yeejoin.precontrol.common.entity.Project;
import com.yeejoin.precontrol.common.entity.RiskWork;
import com.yeejoin.precontrol.common.entity.TaskRiskControl;
import com.yeejoin.precontrol.common.enums.OpsLogEnum;
import com.yeejoin.precontrol.common.service.ICompanyService;
import com.yeejoin.precontrol.common.service.IHazardousWorkService;
import com.yeejoin.precontrol.common.service.IOpsLogService;
import com.yeejoin.precontrol.common.service.IPersonService;
import com.yeejoin.precontrol.common.service.IProjectService;
import com.yeejoin.precontrol.common.service.IRiskWorkService;
import com.yeejoin.precontrol.common.service.ITaskRiskControlService;
import com.yeejoin.precontrol.common.utils.IpUtils;
import com.yeejoin.precontrol.common.utils.PlatformUtils;

//import io.undertow.servlet.spec.HttpServletRequestImpl;

@Aspect
@Component
public class ControllerLogAop {

	@Autowired
	IOpsLogService iOpsLogService;
	@Autowired
	IPersonService iPersonService;
	@Autowired
	ICompanyService iCompanyService;
	@Autowired
	IProjectService iProjectService;
	@Autowired
	IHazardousWorkService iHazardousWorkService;
	@Autowired
	IRiskWorkService iRiskWorkService;
	@Autowired
	ITaskRiskControlService iTaskRiskControlService;

	@Autowired
	PlatformUtils platformUtils;

	@Pointcut("@annotation(com.yeejoin.precontrol.common.annotations.OpsLog)")
	public void point() throws Throwable {

	}

	static Long opsId;

	// 目标方法执行完后执行
	@Before("point()")
	public void doBefore(JoinPoint joinPoint) {
		opsId = null;
		// 保存日志
		OpsLog sysLog = new OpsLog();
		// 从切面织入点处通过反射机制获取织入点处的方法
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		joinPoint.getKind();
		StaticPart StaticPart = joinPoint.getStaticPart();
		// 获取切入点所在的方法
		Method method = signature.getMethod();
		// 获取操作
		com.yeejoin.precontrol.common.annotations.OpsLog myLog = method
				.getAnnotation(com.yeejoin.precontrol.common.annotations.OpsLog.class);
		OpsLogEnum value = myLog.value();
		sysLog.setOpsOperation(value.getValue());// 保存获取的操作

		// 获取请求的类名
		String className = joinPoint.getTarget().getClass().getName();
		sysLog.setClazzName(className);
		// 获取请求的方法名
		String methodName = method.getName();
		sysLog.setMethodName(methodName);

		// 请求的参数
		Object[] args = joinPoint.getArgs();
		List<Object> list = new ArrayList<Object>();
		for (Object object : args) {
			if (object instanceof HttpServletRequest) {
				continue;
			}
			list.add(object);
		}
		//String params = JSONObject.toJSONString(list);
		String params = "";
		List<String> names = new ArrayList<String>();
		if (OpsLogEnum.getDeleteGroup().contains(value)) {
			Object obj = list.get(0);
			if (value.getLabel().contains("person")) {
				List<Long> ids = (List<Long>) obj;
				List<Person> persons = iPersonService.list(new LambdaQueryWrapper<Person>().in(Person::getId, ids));
				names = persons.stream().map(i -> i.getName()).collect(Collectors.toList());
			} else if (value.getLabel().contains("company")) {
				String[] ids = obj.toString().split(",");
				List<Company> companys = iCompanyService
						.list(new LambdaQueryWrapper<Company>().in(Company::getId, Arrays.asList(ids)));
				names = companys.stream().map(i -> i.getName()).collect(Collectors.toList());
			} else if (value.getLabel().contains("project")) {
				List<Long> ids = (List<Long>) obj;
				List<Project> projects = iProjectService
						.list(new LambdaQueryWrapper<Project>().in(Project::getId, ids));
				names = projects.stream().map(i -> i.getName()).collect(Collectors.toList());
			} else if (value.getLabel().contains("hazardousWork")) {
				List<Long> ids = (List<Long>) obj;
				List<HazardousWork> hazardousWorks = iHazardousWorkService
						.list(new LambdaQueryWrapper<HazardousWork>().in(HazardousWork::getId, ids));
				names = hazardousWorks.stream().map(i -> i.getName()).collect(Collectors.toList());
			} else if (value.getLabel().contains("riskWork")) {
				String[] ids = obj.toString().split(",");
				List<RiskWork> riskworks = iRiskWorkService
						.list(new LambdaQueryWrapper<RiskWork>().in(RiskWork::getId, Arrays.asList(ids)));
				names = riskworks.stream().map(i -> i.getName()).collect(Collectors.toList());
			} else if (value.getLabel().contains("riskControl")) {
				String[] ids = obj.toString().split(",");
				List<TaskRiskControl> taskRiskControls = iTaskRiskControlService
						.list(new LambdaQueryWrapper<TaskRiskControl>().in(TaskRiskControl::getId, Arrays.asList(ids)));
				names = taskRiskControls.stream().map(i -> i.getName()).collect(Collectors.toList());
			}
			params = params + "," + JSONObject.toJSONString(names);
		}
		sysLog.setArgs(params);

		Person person = platformUtils.getPerson();
		sysLog.setPersonId(person.getId());
		sysLog.setRealName(person.getName());
		sysLog.setMobile(person.getPhone());
		// 获取用户ip地址
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		sysLog.setIpAddr(IpUtils.getRealIp(request));

		// 调用service保存SysLog实体类到数据库
		sysLog.setId((long) joinPoint.hashCode());
		iOpsLogService.save(sysLog);
//		opsId = sysLog.getId();
//		joinPoint.hashCode();
		System.out.println("将日志记录到数据库");
	}

	@AfterThrowing(value = "point()", throwing = "ex")
	public void doThrow(JoinPoint joinPoint, Exception ex) {
//		if (opsId != null) {
			iOpsLogService.removeById(joinPoint.hashCode());
			String methodName = joinPoint.getSignature().getName();
			System.out.println(methodName + "方法异常，异常信息为：" + ex.getMessage());
//		}
	}
}
