package com.hotent.portal.controller;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.gexin.fastjson.JSON;
import com.hotent.base.aop.AopCacheHelper;
import com.hotent.base.constants.JmsConstant;
import com.hotent.base.constants.TenantConstant;
import com.hotent.base.entity.URIEntity;
import com.hotent.base.jms.JmsProducer;
import com.hotent.base.util.*;
import com.hotent.base.util.time.DateUtil;
import com.hotent.portal.service.PortalBizSystemManager;
import io.swagger.models.auth.In;
import org.omg.CORBA.OBJ_ADAPTER;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.hotent.base.annotation.ApiGroup;
import com.hotent.base.constants.ApiGroupConsts;
import com.hotent.base.controller.BaseController;
import com.hotent.base.model.CommonResult;
import com.hotent.base.query.PageList;
import com.hotent.base.query.QueryFilter;
import com.hotent.sys.persistence.manager.SysLogsManager;
import com.hotent.sys.persistence.model.SysLogs;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 * <pre> 
 * 描述：系统操作日志 控制器类
 * 构建组：x7
 * 作者:liyg
 * 邮箱:liygui@jee-soft.cn
 * 日期:2018-08-31 10:59:25
 * 版权：广州宏天软件有限公司
 * </pre>
 */
@RestController
@RequestMapping(value="/sys/sysLogs/v1")
@Api(tags="系统日志")
@ApiGroup(group= {ApiGroupConsts.GROUP_PORTAL})
public class SysLogsController extends BaseController<SysLogsManager, SysLogs>{
	private Logger logger = LoggerFactory.getLogger(SysLogsController.class);
	@Resource
	SysLogsManager sysLogsManager;
	@Resource
	JmsProducer jmsProducer;
	@Resource
	AopCacheHelper aopCacheHelper;

	@Resource
	PortalBizSystemManager portalBizSystemManager;

	private static String moduleType = "base" ;

	/**
	 * 系统操作日志列表(分页条件查询)数据
	 * @param request
	 * @return
	 * @throws Exception
	 * PageJson
	 * @exception
	 */
	@PostMapping("/list")
	@ApiOperation(value="系统操作日志数据列表", httpMethod = "POST", notes = "获取系统操作日志列表")
	public PageList<SysLogs> list(@ApiParam(name="queryFilter",value="查询对象")@RequestBody QueryFilter<SysLogs> queryFilter) throws Exception{
		return sysLogsManager.query(queryFilter);
	}

	/**
	 * 系统操作日志明细页面
	 * @param id
	 * @return
	 * @throws Exception
	 * ModelAndView
	 */
	@GetMapping(value="/get/{id}")
	public SysLogs get(@ApiParam(name="id",value="业务对象主键", required = true)@PathVariable String id) throws Exception{
		return sysLogsManager.get(id);
	}

	/**
	 * 新增系统操作日志
	 * @param sysLogs
	 * @throws Exception
	 * @return
	 * @exception
	 */
	@PostMapping(value="save")
	public CommonResult<String> save(@ApiParam(name="sysLogs",value="系统操作日志业务对象", required = true)@RequestBody SysLogs sysLogs) throws Exception{
		String msg = "添加系统操作日志成功";
		if(StringUtil.isEmpty(sysLogs.getId())){
			sysLogsManager.create(sysLogs);
		}else{
			sysLogsManager.update(sysLogs);
			msg = "更新系统操作日志成功";
		}
		return new CommonResult<String>(msg);
	}

	/**
	 * 删除系统操作日志记录
	 * @param id
	 * @throws Exception
	 * @return
	 * @exception
	 */
	@DeleteMapping(value="remove/{id}")
	public  CommonResult<String>  remove(@ApiParam(name="id",value="业务主键", required = true)@PathVariable String id) throws Exception{
		sysLogsManager.remove(id);
		return new CommonResult<String>(true, "删除成功");
	}

	/**
	 * 批量删除系统操作日志记录
	 * @param ids
	 * @throws Exception
	 * @return
	 * @exception
	 */
	@DeleteMapping(value="/removes")
	public CommonResult<String> removes(@ApiParam(name="ids",value="业务主键数组,多个业务主键之间用逗号分隔", required = true)@RequestParam String...ids) throws Exception{
		sysLogsManager.removeByIds(ids);
		return new CommonResult<String>(true, "删除成功");
	}

	/**
	 * 首页门户 获取门户访问量 统计
	 * @param type 类型 0:近一个月 1:近半年 2：近一年
	 */
	@GetMapping(value="/portal/visits")
	@ApiOperation(value = "首页门户获取门户访问量统计", httpMethod = "GET", notes = "首页门户获取门户访问量统计")
	public JSONArray getPortalVisits(@ApiParam(name="type",value="类型")@RequestParam String type) throws Exception{
		DateTimeFormatter dayFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		DateTimeFormatter monthFormat = DateTimeFormatter.ofPattern("yyyy-MM");

		JSONArray result = new JSONArray();
		Map<String, Integer> dateMap = new LinkedHashMap<String, Integer>();
		LocalDate today = LocalDate.now(); //获取当前日期
		if("0".equals(type)) {
			LocalDate oneMonthAgo = today.minus(Period.ofDays(30)); // 计算近一个月的日期范围
			for (LocalDate date = oneMonthAgo; date.isBefore(today); date = date.plusDays(1)) {
				dateMap.put(dayFormat.format(date), 0);
			}
			QueryWrapper wrapper = new QueryWrapper();
			wrapper.select("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m-%d') as day", "count(ID_) as count");
			wrapper.eq("OPE_NAME_", "通过别名获取布局信息");
			wrapper.eq("OPE_CONTENT_", "[\"default_front\"]");
			wrapper.ge("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m-%d')", dayFormat.format(oneMonthAgo));
			wrapper.le("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m-%d')", dayFormat.format(today));
			wrapper.groupBy("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m-%d') ");
			wrapper.orderByDesc("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m-%d') ");
			List<Map<String, Object>> list = sysLogsManager.getBaseMapper().selectMaps(wrapper);
			for (int i = 0; i <list.size() ; i++) {
				Map<String, Object> map = list.get(i);
				String day = (String)map.get("day");
				Long num = (Long)map.get("count");
				dateMap.put(day, num.intValue());
			}
			for (Map.Entry<String, Integer> entry : dateMap.entrySet()) {
				JSONObject obj = new JSONObject();
				obj.set("time", entry.getKey());
				obj.set("value", entry.getValue());
				result.add(obj);
			}
		} else if("1".equals(type)) {
			LocalDate sixMonthsAgo = today.minus(Period.ofMonths(6)); // 计算近半年的日期范围
			for (LocalDate date = sixMonthsAgo; date.isBefore(today); date = date.plusMonths(1)) {
				dateMap.put(monthFormat.format(date), 0);
			}
			QueryWrapper wrapper = new QueryWrapper();
			wrapper.select("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m') as month", "count(ID_) as count");
			wrapper.eq("OPE_NAME_", "通过别名获取布局信息");
			wrapper.eq("OPE_CONTENT_", "[\"default_front\"]");
			wrapper.ge("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m')", monthFormat.format(sixMonthsAgo));
			wrapper.le("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m')", monthFormat.format(today));
			wrapper.groupBy("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m') ");
			wrapper.orderByDesc("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m') ");
			List<Map<String, Object>> list = sysLogsManager.getBaseMapper().selectMaps(wrapper);
			for (int i = 0; i <list.size() ; i++) {
				Map<String, Object> map = list.get(i);
				String month = (String)map.get("month");
				Long num = (Long)map.get("count");
				dateMap.put(month, num.intValue());
			}
			for (Map.Entry<String, Integer> entry : dateMap.entrySet()) {
				JSONObject obj = new JSONObject();
				obj.set("time", entry.getKey());
				obj.set("value", entry.getValue());
				result.add(obj);
			}
		} else {
			LocalDate monthsAgo = today.minus(Period.ofMonths(12)); // 计算近一年的日期范围
			for (LocalDate date = monthsAgo; date.isBefore(today); date = date.plusMonths(1)) {
				dateMap.put(monthFormat.format(date), 0);
			}
			QueryWrapper wrapper = new QueryWrapper();
			wrapper.select("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m') as month", "count(ID_) as count");
			wrapper.eq("OPE_NAME_", "通过别名获取布局信息");
			wrapper.eq("OPE_CONTENT_", "[\"default_front\"]");
			wrapper.ge("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m')", monthFormat.format(monthsAgo));
			wrapper.le("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m')", monthFormat.format(today));
			wrapper.groupBy("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m') ");
			wrapper.orderByDesc("DATE_FORMAT(EXECUTION_TIME_, '%Y-%m') ");
			List<Map<String, Object>> list = sysLogsManager.getBaseMapper().selectMaps(wrapper);
			for (int i = 0; i <list.size() ; i++) {
				Map<String, Object> map = list.get(i);
				String month = (String)map.get("month");
				Long num = (Long)map.get("count");
				dateMap.put(month, num.intValue());
			}
			for (Map.Entry<String, Integer> entry : dateMap.entrySet()) {
				JSONObject obj = new JSONObject();
				obj.set("time", entry.getKey());
				obj.set("value", entry.getValue());
				result.add(obj);
			}
		}

		return result;
	}

	/**
	 * 提交日志记录
	 * @param opeName 操作名称
	 * @param opeContent 操作内容
	 * @param reqUrl 请求url地址
	 */
	@PostMapping(value="/submitSysLog")
	@ApiOperation(value = "提交日志记录", httpMethod = "POST", notes = "提交日志记录")
	public CommonResult<String> submitSysLog(HttpServletRequest request, @RequestBody String json) throws Exception {
		com.gexin.fastjson.JSONObject obj = JSON.parseObject(json);
		String opeName = obj.getString("opeName");
		String opeContent = obj.getString("opeContent");
		String reqUrl = obj.getString("reqUrl");
		CommonResult<String> rtn = null;
		if(StringUtil.isEmpty(opeName)) {
			rtn = new CommonResult<String>(false, "缺少【opeName】操作名称！");
			return rtn;
		}
		if(StringUtil.isEmpty(opeContent)) {
			rtn = new CommonResult<String>(false, "缺少【opeContent】操作内容！");
			return rtn;
		}

		try {
			Map<String, String> cacheSettings = aopCacheHelper.getSysLogsSettingStatusMap();
			if (BeanUtils.isEmpty(cacheSettings) || !cacheSettings.containsKey(moduleType)) {
				logger.error("未获取到日志配置中关于模块：{}的日志配置，跳过该模块的日志记录。", moduleType);
				rtn = new CommonResult<String>(true, "添加成功！", "");
				return rtn;
			}

			String executor = "系统[无用户登录系统]";
			if (StringUtil.isNotEmpty(AuthenticationUtil.getCurrentUserFullname())) {
				executor = String.format("%s[%s]", AuthenticationUtil.getCurrentUserFullname(), AuthenticationUtil.getCurrentUsername());
			}
			if(StringUtil.isNotEmpty(opeContent) && opeContent.length() > 3999) {
				opeContent = opeContent.substring(0, 3999);
			}
			SysLogs sysLogs = new SysLogs();
			sysLogs.setId(UniqueIdUtil.getSuid());
			sysLogs.setOpeName(opeName);
			sysLogs.setOpeContent(opeContent);
			sysLogs.setModuleType(moduleType);
			sysLogs.setReqUrl(reqUrl);
			sysLogs.setExecutionTime(DateUtil.getCurrentDate());
			String tenantId = HttpUtil.getTenantId();
			if (BeanUtils.isEmpty(tenantId)) {
				tenantId = TenantConstant.PLATFORM_TENANT_ID;
			}
			sysLogs.setLogType("操作日志");
			sysLogs.setExecutor(executor);
			sysLogs.setIp(WebUtil.getIpAddr(request));
			sysLogsManager.create(sysLogs);
		} catch (Throwable e) {
			throw e;
		}
		rtn = new CommonResult<String>(true, "添加成功！", "");
		return rtn;
	}


	/**
	 * 用户登陆次数排行查询
	 * @param orgId 0全部组织
	 * @param type 0:月度 1:季度 2:年度
	 * @param year 年
	 * @param data type=0 月度不需要传入 type=1 ,传入1、2、3、4 季度数字  type=2 年度不需要传入此值
	 * */
	@GetMapping(value="/getUserLogin")
	@ApiOperation(value = "用户登陆排行查询", httpMethod = "GET", notes = "用户登陆排行查询")
	public CommonResult<?> getUserLogin(@ApiParam(name="orgId",value="组织id")@RequestParam String orgId,
										@ApiParam(name="type",value="类型")@RequestParam String type,
										@ApiParam(name="year",value="年")@RequestParam String year,
										@ApiParam(name="data",value="数据类型")@RequestParam String data) throws Exception{

		return new CommonResult<>(true,"获取成功",sysLogsManager.getLoginRank(orgId,type,year,data));
	}



	/**
	 * 用户登陆趋势图
	 * @param orgId 0全部组织
	 * @param type 0:月度 1:季度 2:年度
	 * @param year 年
	 * @param data type=0 月度不需要传入 type=1 ,传入1、2、3、4 季度数字  type=2 年度不需要传入此值
	 * */
	@GetMapping(value="/getLoginLogTrend")
	@ApiOperation(value = "用户登陆趋势图", httpMethod = "GET", notes = "用户登陆趋势图")
	public CommonResult<?> getLoginLogTrend(@ApiParam(name="orgId",value="组织id")@RequestParam String orgId,
											@ApiParam(name="type",value="类型")@RequestParam String type,
											@ApiParam(name="year",value="年")@RequestParam String year,
											@ApiParam(name="data",value="数据类型")@RequestParam String data) throws Exception{

		return new CommonResult<>(true,"获取成功",sysLogsManager.getLoginLogTrend(orgId,type,year,data));
	}


	/**
	 * 流程统计总数
	 * @param orgId 0全部组织
	 * @param type 0:月度 1:季度 2:年度
	 * @param year 年
	 * @param data type=0 月度不需要传入 type=1 ,传入1、2、3、4 季度数字  type=2 年度不需要传入此值
	 * @param isAll 0=不按日期 1=按日期
	 * */
	@GetMapping(value="/getBpmProInstStatic")
	@ApiOperation(value = "流程统计总数", httpMethod = "GET", notes = "流程统计总数")
	public CommonResult<?> getBpmProInstStatic(@ApiParam(name="orgId",value="组织id")@RequestParam String orgId,
											   @ApiParam(name="type",value="类型")@RequestParam String type,
											   @ApiParam(name="year",value="年")@RequestParam String year,
											   @ApiParam(name="data",value="数据类型")@RequestParam String data,
											   @ApiParam(name="isAll",value="是否全查")@RequestParam String isAll) throws Exception{

		return new CommonResult<>(true,"获取成功",sysLogsManager.getBpmProInstStatic(orgId,type,year,data,isAll));
	}

	/**
	 * 流程统计总数
	 * @param orgId 0全部组织
	 * @param type 0:月度 1:季度 2:年度
	 * @param year 年
	 * @param data type=0 月度不需要传入 type=1 ,传入1、2、3、4 季度数字  type=2 年度不需要传入此值
	 * @param isAll 0=不按日期 1=按日期
	 * */
	@GetMapping(value="/getBpmProInstCountStatic")
	@ApiOperation(value = "流程统计总数", httpMethod = "GET", notes = "流程统计总数")
	public CommonResult<?> getBpmProInstCountStatic(@ApiParam(name="orgId",value="组织id")@RequestParam String orgId,
											   @ApiParam(name="type",value="类型")@RequestParam String type,
											   @ApiParam(name="year",value="年")@RequestParam String year,
											   @ApiParam(name="data",value="数据类型")@RequestParam String data) throws Exception{

		return new CommonResult<>(true,"获取成功",sysLogsManager.getBpmProInstCountStatic(orgId,type,year,data));
	}



	/**
	 * 流程统计总数
	 * */
	@GetMapping(value="/getApiStatic")
	@ApiOperation(value = "api总数统计", httpMethod = "GET", notes = "api总数统计")
	public CommonResult<?> getApiStatic() throws Exception{
		Set<URIEntity> openApiList= portalBizSystemManager.getOpenApiListFromCacheOut();
		List<String> moduelNameList =openApiList.stream().map(item->item.getModuleName()).distinct().collect(Collectors.toList());
		List<Map<String,Object>> listMap=new ArrayList<>();
		moduelNameList.stream().forEach(item->{
			Map<String,Object> result=new HashMap<>();
			result.put("name",item);
			int count=0;
			for (URIEntity itemMo : openApiList) {
				if(itemMo.getModuleName().equals(item)){
					count++;
				}
			}
			result.put("count",count);
			listMap.add(result);
		});
//		listMap.sort(Comparator.comparingInt(o -> Integer.parseInt(o.get("count").toString())));

		Collections.sort(listMap, (o1, o2) -> Integer.parseInt(o2.get("count").toString()) - Integer.parseInt(o1.get("count").toString()));
		Map<String,Object> result=new HashMap<>();
		result.put("total",openApiList.size());
		result.put("list",listMap);
		return new CommonResult<>(true,"获取成功",result);
	}



	/**
	 * api分类调用记录
	 * */
	@GetMapping(value="/getApiTypeStatic")
	@ApiOperation(value = "api分类调用记录", httpMethod = "GET", notes = "api分类调用记录")
	public CommonResult<?> getApiTypeStatic(@ApiParam(name="orgId",value="组织id")@RequestParam String orgId,
											@ApiParam(name="type",value="类型")@RequestParam String type,
											@ApiParam(name="year",value="年")@RequestParam String year,
											@ApiParam(name="data",value="数据类型")@RequestParam String data) throws Exception{
		Set<URIEntity> openApiList= portalBizSystemManager.getOpenApiListFromCacheOut();
		return new CommonResult<>(true,"获取成功",sysLogsManager.getApiTypeStatic(orgId,type,year,data,openApiList));
	}

	/**
	 * api时间维度调用记录
	 * */
	@GetMapping(value="/getApiTimeStatic")
	@ApiOperation(value = "api时间维度调用记录", httpMethod = "GET", notes = "api时间维度调用记录")
	public CommonResult<?> getApiTimeStatic(@ApiParam(name="orgId",value="组织id")@RequestParam String orgId,
											@ApiParam(name="type",value="类型")@RequestParam String type,
											@ApiParam(name="year",value="年")@RequestParam String year,
											@ApiParam(name="data",value="数据类型")@RequestParam String data) throws Exception{
		Set<URIEntity> openApiList= portalBizSystemManager.getOpenApiListFromCacheOut();
		return new CommonResult<>(true,"获取成功",sysLogsManager.getApiTimeStatic(orgId,type,year,data,openApiList));
	}


	/**
	 * 获取api分组名称列表
	 * */
	@GetMapping(value="/getApiModuleNameList")
	@ApiOperation(value = "获取api分组名称列表", httpMethod = "GET", notes = "获取api分组名称列表")
	public CommonResult<?> getApiModuleNameList() throws Exception{
		Set<URIEntity> openApiList= portalBizSystemManager.getOpenApiListFromCacheOut();
		List<String> moduelNameList =openApiList.stream().map(item->item.getModuleName()).distinct().collect(Collectors.toList());
		List<Map<String,Object>> listMap=new ArrayList<>();
		Map<String,Object> resultMap=new HashMap<>();
		listMap.add(resultMap);
		resultMap.put("name","身份验证");
		moduelNameList.stream().forEach(item->{
			Map<String,Object> result=new HashMap<>();
			result.put("name",item);
			int count=0;
			for (URIEntity itemMo : openApiList) {
				if(itemMo.getModuleName().equals(item)){
					count++;
				}
			}
			result.put("count",count);
			listMap.add(result);
		});

		Map<String,Object> result=new HashMap<>();
		result.put("total",openApiList.size());
		result.put("list",listMap);
		return new CommonResult<>(true,"获取成功",result);
	}

	/**
	 * 获取开放平台api数据
	 * @return
	 * @throws Exception
	 */
	@GetMapping(value="getOpenApiData")
	@ApiOperation(value = "获取开放平台api数据", httpMethod = "GET", notes = "获取开放平台api数据")
	public CommonResult<?> getOpenApiData() {
		Set<URIEntity> openApiList= portalBizSystemManager.getOpenApiListFromCacheOut();
		return new CommonResult<>(true,"获取成功",sysLogsManager.getOpenApiData(openApiList));
	}
}
