package org.jeecg.modules.stm.audit.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;


import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.stm.audit.entity.*;
import org.jeecg.modules.stm.audit.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import org.jeecg.modules.stm.doc.entity.DocFiles;
import org.jeecg.modules.stm.doc.service.IDocFilesService;
import org.jeecg.modules.stm.utils.StmConstans;
import org.jeecg.modules.stm.utils.UserUtil;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 项目条目
 * @Author: jeecg-boot
 * @Date:   2025-01-07
 * @Version: V1.0
 */

@RestController
@RequestMapping("/audit/auditProjectItem")
@Slf4j
public class AuditProjectItemController extends JeecgController<AuditProjectItem, IAuditProjectItemService> {
	@Autowired
	private IAuditProjectItemService auditProjectItemService;
	@Autowired
	private IAuditCheckMethodService auditCheckMethodService;
	@Autowired
	private IAuditCheckMethodItemService auditCheckMethodItemService;
	@Autowired
	private IAuditActRelOthersService stActRelOthersService;
	@Autowired
	private IAuditTaskService auditTaskService;
	@Autowired
	private IAuditComplianeItemService auditComplianeItemService;
	@Autowired
	private IAuditItemRelCheckService auditItemRelCheckService;
	@Autowired
	private IDocFilesService docFilesService;
	
	/**
	 * 分页列表查询
	 *
	 * @param auditProjectItem
	 * @param pageNo
	 * @param pageSize
	 * @param req
	 * @return
	 */
	//@AutoLog(value = "项目条目-分页列表查询")

	@GetMapping(value = "/list")
	public Result<IPage<AuditProjectItem>> queryPageList(AuditProjectItem auditProjectItem,
								   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
								   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
								   HttpServletRequest req) {
		QueryWrapper<AuditProjectItem> queryWrapper = QueryGenerator.initQueryWrapper(auditProjectItem, req.getParameterMap());
		Page<AuditProjectItem> page = new Page<AuditProjectItem>(pageNo, pageSize);
		IPage<AuditProjectItem> pageList = auditProjectItemService.page(page, queryWrapper);
		return Result.OK(pageList);
	}

	 @GetMapping(value = "/listAll")
	 public Result<List<AuditProjectItem>> queryListAll(AuditProjectItem auditProjectItem, HttpServletRequest req) {
		 QueryWrapper<AuditProjectItem> queryWrapper = QueryGenerator.initQueryWrapper(auditProjectItem, req.getParameterMap());
		 List<AuditProjectItem> list = auditProjectItemService.list(queryWrapper);
		 return Result.OK(list);
	 }

	
	/**
	 *   添加
	 *
	 * @param auditProjectItem
	 * @return
	 */
	@AutoLog(value = "项目条目-添加")

	@RequiresPermissions("audit:audit_project_item:add")
	@PostMapping(value = "/add")
	public Result<String> add(@RequestBody AuditProjectItem auditProjectItem) {
		auditProjectItemService.save(auditProjectItem);
		return Result.OK("添加成功！");
	}

	@GetMapping(value = "/getAllProjectItems")
	public Result<List<Map<String,Object>>> getAllProjectItems(AuditProjectItem auditProjectItem, HttpServletRequest req) {
		List<Map<String,Object>> list = auditProjectItemService.getAllProjectItems(auditProjectItem);
		return Result.OK(list);
	}
	
	/**
	 *  编辑
	 *
	 * @param auditProjectItem
	 * @return
	 */
	@AutoLog(value = "项目条目-编辑")

	@RequiresPermissions("audit:audit_project_item:edit")
	@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
	public Result<String> edit(@RequestBody AuditProjectItem auditProjectItem) {
		auditProjectItemService.updateById(auditProjectItem);
		return Result.OK("编辑成功!");
	}
	
	/**
	 *   通过id删除
	 *
	 * @param id
	 * @return
	 */
	@AutoLog(value = "项目条目-通过id删除")

	@RequiresPermissions("audit:audit_project_item:delete")
	@DeleteMapping(value = "/delete")
	public Result<String> delete(@RequestParam(name="id",required=true) String id) {
		auditProjectItemService.removeById(id);
		return Result.OK("删除成功!");
	}
	
	/**
	 *  批量删除
	 *
	 * @param ids
	 * @return
	 */
	@AutoLog(value = "项目条目-批量删除")

	@RequiresPermissions("audit:audit_project_item:deleteBatch")
	@DeleteMapping(value = "/deleteBatch")
	public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
		this.auditProjectItemService.removeByIds(Arrays.asList(ids.split(",")));
		return Result.OK("批量删除成功!");
	}
	
	/**
	 * 通过id查询
	 *
	 * @param id
	 * @return
	 */
	//@AutoLog(value = "项目条目-通过id查询")

	@GetMapping(value = "/queryById")
	public Result<AuditProjectItem> queryById(@RequestParam(name="id",required=true) String id) {
		AuditProjectItem auditProjectItem = auditProjectItemService.getById(id);
		if(auditProjectItem==null) {
			return Result.error("未找到对应数据");
		}
		return Result.OK(auditProjectItem);
	}

    /**
    * 导出excel
    *
    * @param request
    * @param auditProjectItem
    */
    @RequiresPermissions("audit:audit_project_item:exportXls")
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, AuditProjectItem auditProjectItem) {
        return super.exportXls(request, auditProjectItem, AuditProjectItem.class, "项目条目");
    }

    /**
      * 通过excel导入数据
    *
    * @param request
    * @param response
    * @return
    */
    @RequiresPermissions("audit:audit_project_item:importExcel")
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        return super.importExcel(request, response, AuditProjectItem.class);
    }

	@PostMapping(value = "/addOrUpdateBatch")
	public Result<String> addOrUpdateBatch(@RequestBody AuditProjectItem auditProjectItem) {
		List<AuditProjectItem> list = auditProjectItem.getItems();
		if(list!=null&&list.size()>0) {
			for(AuditProjectItem item:list) {
				item.setCheckid(auditProjectItem.getCheckid());
				item.setPid(auditProjectItem.getPid());
				item.setComeFrom(StmConstans.Audit_TASK_COME_FROM_project);
			}
			auditProjectItemService.saveOrUpdateBatch(list);
		}
		return Result.OK("保存成功！");
	}

	@PostMapping(value = "/addCheckAndItems")
	public Result<String> addCheckAndItems(@RequestBody AuditComplianeItem auditComplianeItem, HttpServletRequest req) {
		List<AuditCheckMethod> listCheckMethod = auditComplianeItem.getCheckMethods();
		if (listCheckMethod.isEmpty()) {
			return Result.error("No check methods provided.");
		}

		Integer oldItemId = auditComplianeItem.getId();

		AuditCheckMethod checkMethod = listCheckMethod.get(0);
		Integer checkId = checkMethod.getId();
		checkMethod.setIsPublic(false);
		checkMethod.setCreateUser(UserUtil.getUserId());
		auditCheckMethodService.saveOrUpdate(checkMethod);
		handleAuditComplianceItem(auditComplianeItem);
		if(oldItemId==null) {
			handleAuditItemRelCheck(auditComplianeItem, checkMethod);
		}
		handleActRelations(checkMethod);
		handleCheckMethodItems(checkMethod, checkId);
		return Result.OK("保存成功！");
	}

	private void handleAuditComplianceItem(AuditComplianeItem auditComplianeItem) {
		Integer itemId = auditComplianeItem.getId();
		String itemContent = auditComplianeItem.getContent();

		if (itemContent != null && auditComplianeItem.getItem() != null) {
			auditComplianeItem.setInd(1);
			auditComplianeItem.setIsPublic(false);
			String filePath = auditComplianeItem.getFileUploadPath();

			if (filePath != null && !filePath.isEmpty()) {
				DocFiles docFiles= fileIsExist(filePath);
				if(docFiles==null) {
					docFiles = saveDocFile(filePath);
				}
				auditComplianeItem.setFileId(docFiles.getId());
			}

			auditComplianeItemService.saveOrUpdate(auditComplianeItem);
		}
	}

	private DocFiles saveDocFile(String filePath) {
		if (filePath == null || filePath.isEmpty()) {
			throw new IllegalArgumentException("File path cannot be null or empty");
		}

		DocFiles docFile = new DocFiles();
		String fileName = extractFileName(filePath);
		String fileType = extractFileType(filePath);

		docFile.setFileName(fileName);
		docFile.setFileTp(fileType);
		docFile.setFilePath(filePath);
		docFile.setInd(1);
		docFile.setCtp(-1);
		docFile.setCreateBy(UserUtil.getUserId());
		docFile.setCreateTime(new Date());
		docFile.setDes("合规库私有文件");

		docFilesService.saveOrUpdate(docFile);
		return docFile;
	}


	private void handleAuditItemRelCheck(AuditComplianeItem auditComplianeItem, AuditCheckMethod checkMethod) {
		AuditItemRelCheck auditItemRelCheck = new AuditItemRelCheck();
		auditItemRelCheck.setCitemid(auditComplianeItem.getId());
		auditItemRelCheck.setCheckid(checkMethod.getId());
		auditItemRelCheckService.save(auditItemRelCheck);
	}

	private void handleActRelations(AuditCheckMethod checkMethod) {
		String actIds = checkMethod.getActIds();
		if (actIds != null && !actIds.isEmpty()) {
			List<AuditActRelOthers> actRelOthers = new ArrayList<>();
			stActRelOthersService.setActRelations(actRelOthers, actIds, checkMethod.getId(), StmConstans.Audit_TP_CHECK_METHOD);

			if (checkMethod.getId() != null) {
				QueryWrapper<AuditActRelOthers> queryWrapper = new QueryWrapper<>();
				queryWrapper.eq("tid", checkMethod.getId()).eq("tp", StmConstans.Audit_TP_CHECK_METHOD);
				stActRelOthersService.remove(queryWrapper);
			}
			stActRelOthersService.saveOrUpdateBatch(actRelOthers);
		}
	}

	private void handleCheckMethodItems(AuditCheckMethod checkMethod, Integer checkId) {
		Integer projectId = checkMethod.getProjectid();
		List<AuditCheckMethodItem> list = checkMethod.getCheckMethodItems();

		if (checkId == null) {
			if (list != null && !list.isEmpty()) {
				list.forEach(item -> item.setCheckid(checkMethod.getId()));
				auditCheckMethodItemService.saveOrUpdateBatch(list);
			}

			List<Integer> checkIds = new ArrayList<>();
			checkIds.add(checkMethod.getId());
			auditTaskService.copyCheckItem2ProjectItem(checkIds, projectId,StmConstans.Audit_TASK_COME_FROM_RULE);

			AuditTask auditTask = new AuditTask();
			auditTask.setProjectid(projectId);
			auditTask.setCheckid(checkMethod.getId());
			auditTask.setComeFrom(StmConstans.Audit_TASK_COME_FROM_RULE);
			auditTaskService.save(auditTask);
		} else {
			if (list != null && !list.isEmpty()) {
				List<AuditProjectItem> newList = list.stream().map(item -> {
					AuditProjectItem auditProjectItem = new AuditProjectItem();
					auditProjectItem.setCheckid(checkMethod.getId());
					auditProjectItem.setPid(projectId);
					auditProjectItem.setComeFrom(StmConstans.Audit_TASK_COME_FROM_project);
					auditProjectItem.setDes(item.getDes());
					auditProjectItem.setName(item.getName());
					auditProjectItem.setId(item.getId());
					auditProjectItem.setTp(item.getTp());
					return auditProjectItem;
				}).collect(Collectors.toList());
				auditProjectItemService.saveOrUpdateBatch(newList);
			}
		}
	}

	@PostMapping(value = "/batchAddCheckAndItems")
	public Result<String> batchAddCheckAndItems(@RequestBody List<AuditComplianeItem> auditComplianeItems, HttpServletRequest req)
	{
		if(!auditComplianeItems.isEmpty()) {
			for(int i=0;i<auditComplianeItems.size();i++) {
				AuditComplianeItem auditComplianeItem = auditComplianeItems.get(i);
				auditComplianeItem.setIsPublic(false);
				auditComplianeItemService.saveOrUpdate(auditComplianeItem);
				List<AuditCheckMethod> listCheckMethod = auditComplianeItem.getCheckMethods();

				if (listCheckMethod.isEmpty()) {
					continue;
				}
				for (AuditCheckMethod acm : listCheckMethod) {
					AuditCheckMethod checkMethod = listCheckMethod.get(0);
					Integer checkId = checkMethod.getId();
					checkMethod.setIsPublic(false);
					checkMethod.setCreateUser(UserUtil.getUserId());
					auditCheckMethodService.saveOrUpdate(checkMethod);
					handleAuditComplianceItem(auditComplianeItem);
					handleAuditItemRelCheck(auditComplianeItem, checkMethod);
					handleActRelations(checkMethod);
					handleCheckMethodItems(checkMethod,checkId);
				}
			}
		}
		return Result.OK("保存成功！");
	}


	private DocFiles fileIsExist(String filePath) {
		QueryWrapper<DocFiles> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("file_path",filePath);
		List<DocFiles> list = docFilesService.list(queryWrapper);
		if(list!=null&&list.size()>0) {
			return list.get(0);
		}
		return null;
	}

	private String extractFileName(String filePath) {
		int pos = filePath.lastIndexOf("/");
		return (pos > -1) ? filePath.substring(pos + 1) : filePath;
	}

	private String extractFileType(String filePath) {
		int pos = filePath.lastIndexOf(".");
		return (pos > -1) ? filePath.substring(pos + 1) : "";
	}

}
