package org.sky.scientific.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.sky.core.excel.util.ExcelUtil;
import org.sky.core.log.exception.ServiceException;
import org.sky.core.mp.support.Condition;
import org.sky.core.mp.support.Query;
import org.sky.core.secure.utils.SecureUtil;
import org.sky.core.tool.node.ForestNodeMerger;
import org.sky.core.tool.utils.BeanUtil;
import org.sky.core.tool.utils.Charsets;
import org.sky.core.tool.utils.CollectionUtil;
import org.sky.core.tool.utils.Func;
import org.sky.scientific.excel.SubjectEnterpriseExcel;
import org.sky.scientific.mapper.SubjectEnterpriseMapper;
import org.sky.scientific.mapper.SubjectMapper;
import org.sky.scientific.pojo.entity.Subject;
import org.sky.scientific.pojo.entity.SubjectEnterprise;
import org.sky.scientific.pojo.vo.SubjectVO;
import org.sky.scientific.service.ISubjectService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 服务实现类
 */
@Service
@AllArgsConstructor
public class SubjectServiceImpl extends ServiceImpl<SubjectMapper, Subject> implements ISubjectService {

	private final static String PARENT_ID = "parentId";

	private final SubjectEnterpriseMapper subjectEnterpriseMapper;

	@Override
	public List<SubjectVO> lazyList(Long parentId, Map<String, Object> subject) {
		if (Func.isEmpty(Func.toStr(subject.get(PARENT_ID)))) {
			parentId = null;
		}
		List<SubjectVO> list = baseMapper.lazyList(parentId, subject);
		return ForestNodeMerger.merge(list);
	}

	@Override
	public IPage<SubjectEnterprise> selectSubjectEnterpriseList(IPage<SubjectEnterprise> page, SubjectEnterprise subjectEnterprise) {
		subjectEnterprise.setTenantId(SecureUtil.getTenantId());
		return page.setRecords(subjectEnterpriseMapper.selectSubjectEnterpriseList(page, subjectEnterprise));
	}

	@Override
	public boolean submitSubject(Subject subject) {
//		subject.setAccSubject();
		if (Func.isEmpty(subject.getId())) {
			//新增
			return save(subject);
		} else {
			//修改
			return updateById(subject);
		}
	}

	@Override
	public boolean deleteSubject(Long subjectId) {
		//查询是否有子项
		if (baseMapper.selectCount(Wrappers.<Subject>lambdaQuery().eq(Subject::getParentId, subjectId)) > 0) {
			throw new ServiceException("请先删除子项！");
		}
		return baseMapper.deleteSubject(subjectId);
	}

	@Override
	public boolean importSubjectEnterprise(MultipartFile file) {
		List<SubjectEnterpriseExcel> data = ExcelUtil.read(file, 0, 2, SubjectEnterpriseExcel.class);
		if (CollectionUtil.isEmpty(data)) {
			throw new ServiceException("未能从模板中读取数据，请检查模板格式是否正确");
		}
		List<SubjectEnterprise> insertList = new ArrayList<>();
		int batchCount = 20;
		for (SubjectEnterpriseExcel excel : data) {
			SubjectEnterprise entity = Objects.requireNonNull(BeanUtil.copyProperties(excel, SubjectEnterprise.class));
			entity.setTenantId(SecureUtil.getTenantId());
			Subject dbSubject = baseMapper.selectOne(Wrappers.<Subject>lambdaQuery().eq(Subject::getName, excel.getSubjectName()));
			if (dbSubject == null) {
				throw new ServiceException("对应会计科目：" + excel.getSubjectName() + "不存在");
			}
			entity.setSubjectId(dbSubject.getId());
			insertList.add(entity);
			if (insertList.size() % batchCount == 0) {
				if (subjectEnterpriseMapper.insertBatch(insertList) > 0) {
					insertList.clear();
				}
			}
		}

		if (Func.isEmpty(insertList)) {
			subjectEnterpriseMapper.insertBatch(insertList);
		}
		return true;
	}

	@Override
	public boolean deleteBatchSubjectEnterprise(List<Long> ids) {
		return subjectEnterpriseMapper.deleteBatch((ids)) > 0;
	}

	@SneakyThrows
	@Override
	public void exportSubjectEnterprise(HttpServletResponse response, SubjectEnterprise dto) {

		IPage<SubjectEnterprise> page = Condition.getPage(new Query().setCurrent(1).setSize(Integer.MAX_VALUE));
		List<SubjectEnterprise> list = this.selectSubjectEnterpriseList(page, dto).getRecords();

		InputStream templateFileName = this.getClass().getClassLoader().getResourceAsStream("export-template/企业会计科目.xls");
		response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding("utf-8");
		response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("企业会计科目.xls", Charsets.UTF_8));
		ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
			.withTemplate((templateFileName))
			.excelType(ExcelTypeEnum.XLS)
			.build();

		WriteSheet writeSheet = EasyExcel.writerSheet().build();
		//设置list集合数据
		excelWriter.fill(new FillWrapper("list", list), writeSheet);
		excelWriter.finish();
		if (templateFileName != null) {
			templateFileName.close();
		}
	}

	@Override
	public boolean submitSubjectEnterprise(SubjectEnterprise subjectEnterprise) {
		SubjectEnterprise dbEntityByName = subjectEnterpriseMapper.selectOne(Wrappers.<SubjectEnterprise>lambdaQuery()
			.eq(SubjectEnterprise::getName, subjectEnterprise.getName()));

		SubjectEnterprise dbEntityByCode = subjectEnterpriseMapper.selectOne(Wrappers.<SubjectEnterprise>lambdaQuery()
			.eq(SubjectEnterprise::getCode, subjectEnterprise.getCode()));

		if (Func.isNull(subjectEnterprise.getId())) {
			//新增
			if (dbEntityByName != null && Func.equals(dbEntityByName.getName(), subjectEnterprise.getName())) {
				throw new ServiceException("科目名称已存在");
			}
			if (dbEntityByCode != null && Func.equals(dbEntityByCode.getCode(), subjectEnterprise.getCode())) {
				throw new ServiceException("科目代码已存在");
			}
			subjectEnterprise.setTenantId(SecureUtil.getTenantId());
			return subjectEnterpriseMapper.insert(subjectEnterprise) == 1;
		} else {
			//修改
			if (dbEntityByName != null && Func.equals(dbEntityByName.getName(), subjectEnterprise.getName()) && !Func.equals(dbEntityByName.getId(), subjectEnterprise.getId())) {
				throw new ServiceException("科目名称已存在");
			}
			if (dbEntityByCode != null && Func.equals(dbEntityByCode.getCode(), subjectEnterprise.getCode()) && !Func.equals(dbEntityByCode.getId(), subjectEnterprise.getId())) {
				throw new ServiceException("科目代码已存在");
			}
			subjectEnterprise.setTenantId(SecureUtil.getTenantId());
			return subjectEnterpriseMapper.updateById(subjectEnterprise) == 1;
		}
	}

}
