/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the yifu4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.yifu.cloud.plus.v1.yifu.salary.service.impl;

import com.alibaba.excel.EasyExcelFactory;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ResultConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.DateUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.OSSUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.FileVo;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.salary.entity.TSalaryAtta;
import com.yifu.cloud.plus.v1.yifu.salary.entity.TSalaryStandard;
import com.yifu.cloud.plus.v1.yifu.salary.mapper.TSalaryAttaMapper;
import com.yifu.cloud.plus.v1.yifu.salary.service.TSalaryAccountService;
import com.yifu.cloud.plus.v1.yifu.salary.service.TSalaryAttaService;
import com.yifu.cloud.plus.v1.yifu.salary.service.TSalaryStandardService;
import com.yifu.cloud.plus.v1.yifu.salary.vo.SalaryAttaVo;
import com.yifu.cloud.plus.v1.yifu.salary.vo.TSalaryAccountExportByEkpVo;
import com.yifu.cloud.plus.v1.yifu.salary.vo.TSalaryTypeFourExportEkpVo;
import com.yifu.cloud.plus.v1.yifu.salary.vo.TSalaryTypeThreeExportEkpVo;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 薪资结算附件表
 *
 * @author hgw
 * @date 2022-08-05 11:40:14
 */
@Log4j2
@Service
@AllArgsConstructor
public class TSalaryAttaServiceImpl extends ServiceImpl<TSalaryAttaMapper, TSalaryAtta> implements TSalaryAttaService {

	private final OSSUtil ossUtil;

	private final TSalaryStandardService tSalaryStandardService;
	private final TSalaryAccountService tSalaryAccountService;

	private final AtomicInteger atomicInteger = new AtomicInteger(0);

	/**
	 * 薪资结算附件表简单分页查询
	 *
	 * @param tAtta 薪资结算附件表
	 * @return
	 */
	@Override
	public IPage<TSalaryAtta> getTAttaPage(Page<TSalaryAtta> page, TSalaryAtta tAtta) {
		return baseMapper.getTAttaPage(page, tAtta);
	}

	/**
	 * @Description: 工程薪资暂停发附件上传
	 * @Author: hgw
	 * @Date: 2021/10/27 15:43
	 * @return: com.yifu.cloud.v1.common.core.util.R<java.lang.String>
	 **/
	@Override
	public R<String> uploadEngineerPauseSalaryAtta(MultipartFile[] file, String filePath, String linkId, Integer linkType
			, Integer[] engineerType, String recordId) throws IOException {
		if (Common.isEmpty(file) || Common.isEmpty(engineerType) || engineerType.length != file.length) {
			return R.failed(CommonConstants.PARAM_INFO_ERROR);
		}
		for (int i = 0; i < file.length; i++) {
			this.uploadAtta(file[i], filePath, linkId, linkType, engineerType[i], null, recordId);
		}
		return R.ok("上传成功！");
	}

	/**
	 * @Description: 自定义暂停发附件上传
	 * @Author: hgw
	 * @Date: 2021-11-22 17:37:39
	 * @return: com.yifu.cloud.v1.common.core.util.R<java.lang.String>
	 **/
	@Override
	public R<String> uploadPauseDiyAtta(MultipartFile[] file, String filePath, String linkId, Integer linkType
			, String recordId) throws IOException {
		if (Common.isEmpty(file)) {
			return R.failed(CommonConstants.PARAM_INFO_ERROR);
		}
		for (int i = 0; i < file.length; i++) {
			this.uploadAtta(file[i], filePath, linkId, linkType, null, null, recordId);
		}
		return R.ok("上传成功！");
	}

	/**
	 * @Description: 自定义暂停发附件上传
	 * @Author: hgw
	 * @Date: 2021-11-22 17:37:39
	 * @return: com.yifu.cloud.v1.common.core.util.R<java.lang.String>
	 **/
	@Override
	public R<String> uploadLostAndFoundAtta(MultipartFile[] file, String filePath, String linkId, Integer linkType) throws IOException {
		if (Common.isEmpty(file)) {
			return R.failed(CommonConstants.PARAM_INFO_ERROR);
		}
		for (int i = 0; i < file.length; i++) {
			this.uploadAtta(file[i], filePath, linkId, linkType, null, null, null);
		}
		return R.ok("上传成功！");
	}

	@Override
	public R<FileVo> uploadAtta(@RequestBody MultipartFile file, String filePath, String linkId
			, Integer linkType, Integer engineerType, String printRemark, String recordId) throws IOException {
		//初始化附件上传队列上限值
		int maxLimit = 5;
		if (atomicInteger.incrementAndGet() <= maxLimit){
			try {
				String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename();
				//filePath不传默认存储空间的根目录
				//jpg,jpeg,png,bmp
				String key = "";
				if (!Common.isNotNull(filePath)) {
					key = fileName;
				} else {
					key = filePath + "/" + fileName;
				}
				boolean flag = ossUtil.uploadFileByStream(file.getInputStream(), key, null);
				FileVo fileVo;
				TSalaryAtta salaryAtta;
				URL url = null;
				if (flag) {
					salaryAtta = this.saveTSalaryAtta(fileName, key, file.getSize(), linkId, linkType, engineerType, printRemark, recordId);
					try {
						this.save(salaryAtta);
					} catch (Exception e) {
						log.error("OSS文件上传接口异常：" + e.getMessage());
						ossUtil.deleteObject(null, key);
						return R.failed("failed:" + e.getMessage());
					}
					url = ossUtil.getObjectUrl(null, salaryAtta.getAttaSrc());
					fileVo = new FileVo(salaryAtta.getId(), salaryAtta.getAttaName(), url.toString());
					return R.ok(fileVo);
				} else {
					return R.failed("failed:上传至存储空间失败");
				}
			}catch (Exception e){
				log.error("附件上传异常：",e);
			}finally {
				atomicInteger.decrementAndGet();
			}
		}else {
			atomicInteger.decrementAndGet();
			log.error("超出阈值："+ ResultConstants.FILE_UPLOADING_DATA);
			return  R.failed(ResultConstants.FILE_UPLOADING_DATA);
		}
		return null;
	}

	/**
	 * @param fileName 文件名
	 * @param key      路径
	 * @param fileSize 大小
	 * @Description: 保存附件信息
	 * @Author: hgw
	 * @Date: 2019/10/25 15:49
	 * @return: com.yifu.cloud.v1.hrms.api.entity.TSalaryAtta
	 **/
	private TSalaryAtta saveTSalaryAtta(String fileName, String key, Long fileSize, String linkId
			, Integer linkType, Integer engineerType, String printRemark, String recordId) {
		TSalaryAtta salaryAtta = new TSalaryAtta();
		char slash = '/';
		char point = '.';
		if (fileName.lastIndexOf(slash) >= 0) {
			salaryAtta.setAttaName(key.substring(fileName.lastIndexOf(slash), fileName.length()));
		} else {
			salaryAtta.setAttaName(fileName);
		}
		salaryAtta.setAttaSize(fileSize);
		salaryAtta.setAttaSrc(key);
		if (key.lastIndexOf(point) >= 0) {
			salaryAtta.setAttaType(key.substring(fileName.lastIndexOf(point), fileName.length()));
		}
		salaryAtta.setAttaUrl("");
		salaryAtta.setCreateTime(LocalDateTime.now());
		salaryAtta.setUpdateTime(LocalDateTime.now());
		YifuUser user = SecurityUtils.getUser();
		salaryAtta.setCreateBy(null == user ? "" : user.getId());
		salaryAtta.setUpdateBy(null == user ? "" : user.getId());
		salaryAtta.setLinkId(linkId);
		salaryAtta.setLinkType(linkType);
		salaryAtta.setEngineerType(engineerType);
		salaryAtta.setPrintRemark(printRemark);
		salaryAtta.setRecordId(recordId);
		salaryAtta.setRecordStatus(CommonConstants.ZERO_INT);
		return salaryAtta;
	}

	/**
	 * @param linkId
	 * @param linkType
	 * @Description: 获取list，并且从oss服务器根据AttaSrc获取路径，塞入AttaUrl
	 * @Author: hgw
	 * @Date: 2021/11/19 16:03
	 * @return: java.util.List<com.yifu.cloud.v1.hrms.api.entity.TSalaryAtta>
	 **/
	@Override
	public List<TSalaryAtta> getAttaListHaveSrc(String linkId, Integer linkType) {
		// 附件
		TSalaryAtta sa = new TSalaryAtta();
		sa.setLinkId(linkId);
		// 附件类型：0工资；1工程工资；2暂停发；3自定义项暂停发 8 自有员工校验附件
		sa.setLinkType(linkType);
		sa.setRecordStatus(0);
		List<TSalaryAtta> attaList = baseMapper.getTAttaList(sa);
		this.setSrc(attaList);
		return attaList;
	}

	/**
	 * @param recordId
	 * @Description: 获取list，并且从oss服务器根据AttaSrc获取路径，塞入AttaUrl
	 * @Author: hgw
	 * @Date: 2021/11/19 16:03
	 * @return: java.util.List<com.yifu.cloud.v1.hrms.api.entity.TSalaryAtta>
	 **/
	@Override
	public List<TSalaryAtta> getAttaListByRecordId(String recordId) {
		// 附件
		TSalaryAtta sa = new TSalaryAtta();
		sa.setRecordId(recordId);
		List<TSalaryAtta> attaList = baseMapper.getTAttaList(sa);
		this.setSrc(attaList);
		return attaList;
	}

	/**
	 * @param salaryAttaIds
	 * @param linkId
	 * @author fxj
	 * @date 2021-12-03
	 * @description 更新附件关联id
	 */
	@Transactional
	@Override
	public void updateAttaByLinkId(List<String> salaryAttaIds, String linkId) {
		if (Common.isNotNull(salaryAttaIds) && Common.isNotNull(linkId)) {
			List<TSalaryAtta> attaList = baseMapper.selectList(Wrappers
					.<TSalaryAtta>query().lambda().in(TSalaryAtta::getId, salaryAttaIds));
			if (Common.isNotNull(attaList)) {
				for (TSalaryAtta atta : attaList) {
					atta.setLinkId(linkId);
					baseMapper.updateById(atta);
				}
			}
		}
	}

	/**
	 * @param attaList
	 * @Description: 塞路径
	 * @Author: hgw
	 * @Date: 2021/11/23 17:37
	 * @return: void
	 **/
	@Override
	public void setSrc(List<TSalaryAtta> attaList) {
		if (attaList != null && !attaList.isEmpty()) {
			URL url;
			for (TSalaryAtta tsa : attaList) {
				if (Common.isNotNull(tsa.getAttaSrc())) {
					url = ossUtil.getObjectUrl(null, tsa.getAttaSrc());
					tsa.setAttaUrl(String.valueOf(url));
				}
			}
		}
	}

	/**
	 * @param applyNo
	 * @Description: 获取薪资报账，转化为excel，上传到系统，然后将附件名称与地址返回
	 * @Author: hgw
	 * @Date: 2024/4/18 17:05
	 * @return: com.yifu.cloud.plus.v1.yifu.salary.vo.SalaryAttaVo
	 **/
	@Async
	@Override
	public synchronized SalaryAttaVo getSalaryAccountToExcel(String applyNo) {
		SalaryAttaVo returnVo = new SalaryAttaVo();
		TSalaryStandard standard = tSalaryStandardService.getOne(Wrappers.<TSalaryStandard>query().lambda()
				.eq(TSalaryStandard::getApplyNo,applyNo).last(CommonConstants.LAST_ONE_SQL));
		// 默认薪资
		String formType = CommonConstants.ZERO_STRING;
		String preFileName = "薪资";
		if (Common.isNotNull(standard)){
			formType = standard.getFormType();
		}
		//薪资
		if (CommonConstants.ZERO_STRING.equals(formType)){
			List<TSalaryAccountExportByEkpVo> accountList = tSalaryAccountService.getAccountListByApplyNo(applyNo);
			if (accountList != null) {
				returnVo = getSalaryAttaVo(applyNo, returnVo, preFileName, accountList,TSalaryAccountExportByEkpVo.class);
			}
		}
		//劳务费
		if (CommonConstants.THREE_STRING.equals(formType)){
			List<TSalaryTypeThreeExportEkpVo> accountList = tSalaryAccountService.getAccountThreeListByApplyNo(applyNo);
			if (accountList != null) {
				returnVo = getSalaryAttaVo(applyNo, returnVo, preFileName, accountList,TSalaryTypeThreeExportEkpVo.class);
			}
		}
		//稿酬
		if (CommonConstants.FOUR_STRING.equals(formType)){
			List<TSalaryTypeFourExportEkpVo> accountList = tSalaryAccountService.getAccountFourListByApplyNo(applyNo);
			if (accountList != null) {
				returnVo = getSalaryAttaVo(applyNo, returnVo, preFileName, accountList,TSalaryTypeFourExportEkpVo.class);
			}
		}

		return returnVo;
	}

	private <T> SalaryAttaVo getSalaryAttaVo(String applyNo, SalaryAttaVo returnVo, String preFileName, List<T> accountList,Class<T> tClass) {
		String filePath = "salaryAccountFile";
		String fileName = preFileName + "报表"+ applyNo + DateUtil.getThisTime() + CommonConstants.XLSX;
		String key = filePath + "/" + fileName;
		;
		EasyExcelFactory.write(filePath, tClass).sheet(preFileName + "报表生成").doWrite(accountList);
		try {
			File file = new File(filePath);
			InputStream inputStream = new FileInputStream(file);
			// 调用上传服务
			boolean flag = ossUtil.uploadFileByStream(inputStream, key,null);
			if (flag) {
				log.info("文件：" + fileName + "上传至存储空间" + ossUtil.getBucketName() + "成功！");
				TSalaryAtta salaryAtta = this.saveTSalaryAtta(fileName, key, file.length(), applyNo, 14, null, null, null);
				try {
					this.save(salaryAtta);
				} catch (Exception e) {
					log.error("OSS文件上传接口异常：" + e.getMessage());
					ossUtil.deleteObject(null, key);
				}
				URL url = ossUtil.getObjectUrl(null, salaryAtta.getAttaSrc());
				returnVo.setAttaUrl(url.toString());
				returnVo.setAttaName(salaryAtta.getAttaName());
				return returnVo;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//删除临时文件
			try {
				org.apache.commons.io.FileUtils.forceDelete(new File(filePath));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

}
