/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights reserved.
 * <a>http://www.crunii.com</a>
 */
package com.crunii.micro.service.sysmgr.service.impl;

import cn.hutool.json.JSONUtil;
import com.crunii.micro.common.constants.CommonConstants;
import com.crunii.micro.common.dto.PageReq;
import com.crunii.micro.common.utils.DateUtil;
import com.crunii.micro.domain.dto.Worker;
import com.crunii.micro.domain.entity.main.TsmMenu;
import com.crunii.micro.domain.entity.main.TsmPageVisitLog;
import com.crunii.micro.domain.entity.main.YcqAppConfigUrl;
import com.crunii.micro.domain.entitysql.main.TCallLogS;
import com.crunii.micro.domain.repo.main.TsmPageVisitLogRepo;
import com.crunii.micro.service.sysmgr.dto.sysmgr.MenuVisitReqDTO;
import com.crunii.micro.service.sysmgr.dto.sysmgr.VisitLogReq;
import com.crunii.micro.service.sysmgr.jdbc.LogJdbcDao;
import com.crunii.micro.service.sysmgr.service.FrequentVisitMenuService;
import com.crunii.micro.service.sysmgr.service.VisitLogService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * @author shenhs create 2023/7/15 15:32
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class VisitLogServiceImpl implements VisitLogService {

	@Autowired
	private TsmPageVisitLogRepo visitLogRepo;
	@Autowired
	private TsmMenuCache menuCache;
	@Resource
	private FrequentVisitMenuService frequentVisitMenuService;

	private final LogJdbcDao logJdbcDao;

	@Value("${backCallLogPath:C:\\logs\\back}")
	private String backCallLogPath;

	private CopyOnWriteArrayList<TsmPageVisitLog> logList = new CopyOnWriteArrayList<>();

	@Override public void saveVisitLog(Worker worker, VisitLogReq req, HttpServletRequest request) {
		/* 2023-11-21 前端放开日志调用接口,后端屏蔽访问日志
		String scope = worker.getScope();
		String mobile = worker.getMobile();
		String UA = request.getHeader(HttpHeaders.USER_AGENT);

		TsmPageVisitLog tsmPageVisitLog = new TsmPageVisitLog();
		tsmPageVisitLog.setScope(scope);
		tsmPageVisitLog.setUserAgent(UA);
		tsmPageVisitLog.setMobile(mobile);
		tsmPageVisitLog.setPageUrl(req.getUrl());
		tsmPageVisitLog.setCreateTime(new Date());
		tsmPageVisitLog.setVisitType(req.getVisitType());
		logList.add(tsmPageVisitLog);
		 */
		//记录菜单访问记录
		MenuVisitReqDTO menuVisitReqDTO=new MenuVisitReqDTO();
		menuVisitReqDTO.setMenuCode(req.getMenuCode());
		menuVisitReqDTO.setUrl(req.getUrl());
		//app端无菜单编码，存路由地址
		if (StringUtils.isBlank(menuVisitReqDTO.getMenuCode())&&StringUtils.isNotBlank(req.getUrl())){
			menuVisitReqDTO.setMenuCode(req.getUrl());
		}
		menuVisitReqDTO.setScope(req.getScope());
		menuVisitReqDTO.setMenuModule(req.getMenuModule());
		frequentVisitMenuService.createTsmWorkerMenuVisit(menuVisitReqDTO,worker);
	}

	public void saveTsmPageVisitLog(){
		logList.forEach(item->{
			findPageId(item);
		});
		visitLogRepo.saveAllAndFlush(logList);
		logList.clear();
	}


	private void findPageId(TsmPageVisitLog visitLog){
		String scope = visitLog.getScope();
		boolean run = true;
		if(CommonConstants.SCOPE_WEB.equals(scope)){
			Iterator<String> iterator = menuCache.urlSet().iterator();
			while (iterator.hasNext() && run){
				String next = iterator.next();
				if((visitLog.getVisitType()==VISIT_TYPE_INNER && next.equals(visitLog.getPageUrl())) || (visitLog.getVisitType()==VISIT_TYPE_OUTER && next.startsWith(visitLog.getPageUrl()))){
					TsmMenu tsmMenu = menuCache.get(next);
					visitLog.setPageId(tsmMenu.getMenuCode());
					run = false;
				}
			}
		}else if(CommonConstants.SCOPE_PHONE.equals(scope)){
			Iterator<String> iterator = menuCache.appUrlSet().iterator();
			while (iterator.hasNext() && run){
				String next = iterator.next();
				if((visitLog.getVisitType()==VISIT_TYPE_INNER && next.equals(visitLog.getPageUrl())) ||(visitLog.getVisitType()==VISIT_TYPE_OUTER && next.startsWith(visitLog.getPageUrl()))) {
					YcqAppConfigUrl ycqAppConfigUrl = menuCache.getAppConf(next);
					visitLog.setPageId(ycqAppConfigUrl.getAppCode());
					run = false;
				}
			}
		}

	}

	@Override
	public void cleanLog(){
		int count = logJdbcDao.cleanLog();
		log.info("清理七天前的日志记录表, 共删除数据量：{}条", count);
		int pageSize = 1000;
		int logCount = logJdbcDao.getLogCount();
		int totalPage = logCount % pageSize == 0 ? logCount % pageSize : (logCount % pageSize) + 1;
		String date = DateUtil.format(new Date(), DateUtil.defaultD1Pattern);
		String basePath = backCallLogPath + File.separator + date + File.separator;
		String suffix = ".txt";
		try {
			Paths.get(basePath).toFile().mkdirs();
			for (int page = 1; page <= totalPage; page++) {
				Integer fileIndex = page;
				Path filePath = Paths.get(  basePath + date + "_" + fileIndex + suffix);
				File file = filePath.toFile();
				if(file.exists()){
					file.delete();
				}
				file.createNewFile();

				PageReq pageReq = new PageReq();
				pageReq.setPageNo(page);
				pageReq.setPageSize(pageSize);
				List<TCallLogS> pageLogs = logJdbcDao.pageListLogs(pageReq).getResult();
				List<String> logs = pageLogs.stream().map(JSONUtil::toJsonStr).collect(Collectors.toList());

				for (String log : logs) {
					Files.write(filePath, log.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
				}
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}


}
