package cn.com.qmth.examcloud.core.questions.service.impl;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.criteria.Predicate;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import cn.com.qmth.examcloud.api.commons.security.bean.User;
import cn.com.qmth.examcloud.commons.exception.StatusException;
import cn.com.qmth.examcloud.core.questions.base.FileDisposeUtil;
import cn.com.qmth.examcloud.core.questions.base.IdUtils;
import cn.com.qmth.examcloud.core.questions.base.dto.ExportTemplateDto;
import cn.com.qmth.examcloud.core.questions.base.enums.ExportTemplateType;
import cn.com.qmth.examcloud.core.questions.dao.ExportTemplateRepo;
import cn.com.qmth.examcloud.core.questions.dao.entity.ExportTemplateEntity;
import cn.com.qmth.examcloud.core.questions.service.ExportTemplateService;
import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
import cn.com.qmth.examcloud.web.config.SystemProperties;
import cn.com.qmth.examcloud.web.filestorage.FileStoragePathEnvInfo;

@Service("exportTemplateService")
public class ExportTemplateServiceImpl implements ExportTemplateService {

	private static final Logger LOG = LoggerFactory.getLogger(ExportTemplateServiceImpl.class);

	private static final String ZIP_SUFFIX = "zip";

	@Autowired
	private ExportTemplateRepo exportTemplateRepo;

	public static final String TEMP_FILE_EXP = "temp/exportTemplat/";
//    @Autowired
//    private UpyunService upyunService;
	@Autowired
	private SystemProperties systemProperties;

	@Override
	public Page<ExportTemplateDto> getPage(Long rootOrgId, String fileName, String type, int curPage, int pageSize) {
		Specification<ExportTemplateEntity> specification = (root, query, cb) -> {
			List<Predicate> predicates = new ArrayList<>();

			predicates.add(cb.equal(root.get("rootOrgId"), rootOrgId));

			if (StringUtils.isNotBlank(fileName)) {
				predicates.add(cb.like(root.get("fileName"), toSqlSearchPattern(fileName)));
			}
			if (StringUtils.isNotBlank(type)) {
				predicates.add(cb.equal(root.get("type"), type));
			}

			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
		};
		PageRequest pageRequest = PageRequest.of(curPage - 1, pageSize, Sort.by(Direction.DESC, "creationTime"));

		Page<ExportTemplateEntity> page = exportTemplateRepo.findAll(specification, pageRequest);
		List<ExportTemplateEntity> list = page.getContent();
		List<ExportTemplateDto> retList = new ArrayList<ExportTemplateDto>();
		if (list != null && list.size() > 0) {
//            String upyunFileUrl = PropertyHolder.getString("$upyun.site.1.domain");
			for (ExportTemplateEntity e : list) {
				ExportTemplateDto dto = new ExportTemplateDto();
				BeanUtils.copyProperties(e, dto);
//                dto.setFullFilePath(upyunFileUrl + dto.getFilePath());
				// 通用存储
				dto.setFullFilePath(FileStorageUtil.realPath(dto.getFilePath()));
				dto.setTypeName(ExportTemplateType.getName(dto.getType()));
				retList.add(dto);
			}
		}
		return new PageImpl<ExportTemplateDto>(retList, PageRequest.of(curPage - 1, pageSize), page.getTotalElements());
	}

	@Transactional
	@Override
	public void addFile(User user, Long rootOrgId, String templateName, String type, MultipartFile dataFile) {
		if (StringUtils.isBlank(templateName)) {
			throw new StatusException("10001", "模板名称不能为空");
		}
		if (!ExportTemplateType.checkCode(type)) {
			throw new StatusException("10002", "模板类型错误");
		}
		ExportTemplateEntity e = new ExportTemplateEntity();
		String fName = dataFile.getOriginalFilename();
		e.setFileName(templateName);
		e.setType(type);
		e.setEnable(false);
		e.setCreationTime(new Date());
		e.setCreateUser(user.getDisplayName());
		e.setFileKey(IdUtils.uuid());
		e.setRootOrgId(rootOrgId);
		String suffix = fName.substring(fName.lastIndexOf(".") + 1, fName.length());
		e.setSuffix(suffix);

		String relativePath = e.getFileKey() + "." + e.getSuffix();
//        UpyunPathEnvironmentInfo env = new UpyunPathEnvironmentInfo();
//        env.setRootOrgId(rootOrgId.toString());
//        env.setRelativePath(relativePath);
//        String fpath = null;
//        InputStream is = null;
//        try {
//            is = dataFile.getInputStream();
//            fpath = upyunService.writeFile("export_template", env, is, null).getRelativePath();
//        } catch (IOException e1) {
//            throw new StatusException("10003", "模板上传出错");
//        } finally {
//            if (is != null) {
//                try {
//                    is.close();
//                } catch (IOException e1) {
//                    log.warn("InputStream close faild!");
//                }
//            }
//        }
		// 通用存储
		FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
		env.setRootOrgId(rootOrgId.toString());
		env.setRelativePath(relativePath);
		InputStream is = null;
		try {
			is = dataFile.getInputStream();
			String fpath = FileStorageUtil.saveFile("export_template", env, is, null).getRelativePath();
			e.setFilePath(fpath);
		} catch (IOException e1) {
			throw new StatusException("10003", "模板上传出错");
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e1) {
					LOG.warn("InputStream close faild!");
				}
			}
		}

		exportTemplateRepo.save(e);
	}

	@Transactional
	@Override
	public void delete(Long rootOrgId, Long id) {
		exportTemplateRepo.deleteByRootOrgIdAndId(rootOrgId, id);
	}

	@Transactional
	@Override
	public void enable(Long rootOrgId, Long id) {
		ExportTemplateEntity et = exportTemplateRepo.findByIdAndRootOrgId(id, rootOrgId);
		if (et != null) {
			exportTemplateRepo.updateEnableByType(rootOrgId, et.getType(), false);
			exportTemplateRepo.updateEnableById(rootOrgId, id, true);
		} else {
			throw new StatusException("30001", "模板不存在");
		}

	}

	@Transactional
	@Override
	public void disenable(Long rootOrgId, Long id) {
		exportTemplateRepo.updateEnableById(rootOrgId, id, false);
	}

	private String toSqlSearchPattern(String column) {
		if (StringUtils.isBlank(column)) {
			return "%";
		} else {
			column = column.trim().replaceAll("\\s", "%");
			column = "%" + column + "%";
			return column;
		}
	}

	@Override
	public String getExportTemplateName(ExportTemplateType type, Long rootOrgId) {
		String temPath = systemProperties.getTempDataDir();
		List<ExportTemplateEntity> list = exportTemplateRepo.findByRootOrgIdAndTypeAndEnable(rootOrgId, type.getCode(),
				true);
		if (list == null || list.size() == 0) {
			throw new StatusException("50001", "模板未设置或未启用");
		}
		if (list != null && list.size() > 1) {
			throw new StatusException("50002", "存在多个启用的模板");
		}
		ExportTemplateEntity et = list.get(0);
		String fileName = et.getFileKey() + "." + et.getSuffix();
		String filePath = temPath + "/" + rootOrgId + "/" + fileName;
		File f = new File(filePath);
		if (!f.exists()) {
//			String upyunFileUrl = PropertyHolder.getString("$upyun.site.1.domain");
			//通用存储
			createExportTemplateFile(FileStorageUtil.realPath(et.getFilePath()), filePath);
		}
		return fileName;
	}

	private synchronized void createExportTemplateFile(String fileUrl, String localFilePath) {
		File f = new File(localFilePath);
		File dir = f.getParentFile();
		try {
			if (!dir.exists()) {
				dir.mkdirs();
			}
			f.createNewFile();
		} catch (IOException e) {
			throw new StatusException("60001", "创建模板文件失败");
		}
		if (!FileDisposeUtil.saveUrlAs(fileUrl, localFilePath)) {
			f.delete();
			throw new StatusException("60002", "获取模板到本地失败");
		}
	}

	@Override
	public File getExportTemplateDirectory(ExportTemplateType type, Long rootOrgId) {
		String temPath = systemProperties.getTempDataDir();
		if (temPath == null) {
			throw new StatusException("70000", "tempDataDir未设置");
		}
		List<ExportTemplateEntity> list = exportTemplateRepo.findByRootOrgIdAndTypeAndEnable(rootOrgId, type.getCode(),
				true);
		if (list == null || list.size() == 0) {
			throw new StatusException("70001", "模板未设置或未启用");
		}
		if (list != null && list.size() > 1) {
			throw new StatusException("70002", "存在多个启用的模板");
		}
		ExportTemplateEntity et = list.get(0);
		if (!ZIP_SUFFIX.equals(et.getSuffix())) {
			throw new StatusException("70003", "模板文件不是zip格式");
		}
		File dir = new File(temPath + "/" + rootOrgId + "/" + et.getFileKey() + "/");
		if (dir.exists()) {
			return dir;
		} else {
			String fileName = et.getFileKey() + "." + et.getSuffix();
			String filePath = temPath + "/" + rootOrgId + "/" + fileName;
			File f = new File(filePath);
			if (!f.exists()) {
//				String upyunFileUrl = PropertyHolder.getString("$upyun.site.1.domain");
				//通用存储
				createExportTemplateDir(FileStorageUtil.realPath(et.getFilePath()), filePath, dir);
			}
			return dir;
		}
	}

	private synchronized void createExportTemplateDir(String fileUrl, String localFilePath, File directory) {
		File f = new File(localFilePath);
		File dir = f.getParentFile();
		try {
			if (!dir.exists()) {
				dir.mkdirs();
			}
			if (!directory.exists()) {
				dir.mkdir();
			}
			f.createNewFile();
		} catch (IOException e) {
			throw new StatusException("80001", "创建模板文件失败");
		}
		if (!FileDisposeUtil.saveUrlAs(fileUrl, localFilePath)) {
			f.delete();
			throw new StatusException("80002", "获取模板到本地失败");
		} else {
			try {
				FileDisposeUtil.unZipFiles(localFilePath, directory.getAbsolutePath());
				f.delete();
			} catch (IOException e) {
				throw new StatusException("80003", "解压模板到本地失败");
			}
		}
	}
}