package cn.superdesk.uniorder.controller.invoice.customer.invoiced;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.lang.UUID;
import cn.superdesk.uniorder.common.exception.constants.ExceptionMsg;
import cn.superdesk.uniorder.common.excel.utils.ExcelImportExport;
import cn.superdesk.uniorder.common.excel.utils.ExcelImportReaderUtils;
import cn.superdesk.uniorder.common.exception.UnifiedOrderRuntimeException;
import cn.superdesk.uniorder.common.json.AnJsonUtils;
import cn.superdesk.uniorder.common.rest.response.R;
import cn.superdesk.uniorder.common.rest.response.ResponseResultOuterUtils;
import cn.superdesk.uniorder.common.rest.response.AnResponseStreamUtils;
import cn.superdesk.uniorder.common.excel.converters.szhtxx.CustomStringBigDecimalConverter;
import cn.superdesk.uniorder.common.security.JwtUtil;
import cn.superdesk.uniorder.common.security.dto.LoginSysUser;
import cn.superdesk.uniorder.controller.base.BaseController;
import cn.superdesk.uniorder.dto._constant.ResourceConstant;
import cn.superdesk.uniorder.dto.param.invoice.excel.InvoiceInvoicedOpBackCollectionForm;
import cn.superdesk.uniorder.dto.param.invoice.excel.InvoiceInvoicedHistoryExcelRow;
import cn.superdesk.uniorder.dto.param.invoice.excel.InvoiceInvoicedNormalExcelRow;
import cn.superdesk.uniorder.dubbo.consumer._common.ProviderEnvConstantDubboCustomerService;
import cn.superdesk.uniorder.dubbo.consumer.invoice.customer.invoiced.InvoiceInvoicedDubboConsumerService;
import cn.superdesk.uniorder.dubbo.consumer.invoice.customer.invoiced.InvoiceInvoicedFieldIsBackCollectionDubboConsumerService;
import cn.superdesk.uniorder.common.numerical.AnDateHelper;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;


@Api(value = "客户结算-应收账款-导入Excel", tags = {"客户结算-应收账款-导入Excel"})
@Slf4j
@RestController
@RequestMapping("/invoiceInvoiced/importExcel")
public class InvoiceInvoicedImportExcelController extends BaseController {

	@Autowired
	private InvoiceInvoicedDubboConsumerService                      invoiceInvoicedDubboConsumerService;
	@Autowired
	private InvoiceInvoicedFieldIsBackCollectionDubboConsumerService invoiceInvoicedFieldIsBackCollectionDubboConsumerService;

	@Resource
	private ProviderEnvConstantDubboCustomerService providerEnvConstantDubboCustomerService;
	@Resource
	private Snowflake                               snowflake;

	/**
	 * http://192.168.6.223:8089/web/invoiceInvoiced/importExcel/template/download/001
	 *
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	@ApiOperation(value = "Excel模板下载-导入回款模板")
	@RequestMapping(value = "template/download/001", method = RequestMethod.GET)
	public void downLoad001(HttpServletRequest request, HttpServletResponse response) throws IOException {

		ResourceConstant excelExportConstant = providerEnvConstantDubboCustomerService.getResourceConstant();

		String excelExportPathRoot             = excelExportConstant.getPathRoot();
		String excelExportRelativePathTemplate = excelExportConstant.getPathTemplate();
		String excelExportRelativePathStorage  = excelExportConstant.getPathStorage();

		String storagePath                 = excelExportPathRoot + excelExportRelativePathTemplate;
		String fileRelativePathStoragePath = "/excel/invoice/invoiced/templateImportBackCollection.xlsx";
		String fileName                    = "导入回款模板.xlsx";

		AnResponseStreamUtils.download(storagePath + fileRelativePathStoragePath, fileName, response);

	}

	@ApiOperation(value = "Excel模板下载-导入应收账款模板")
	@RequestMapping(value = "template/download/002", method = RequestMethod.GET)
	public void downLoad002(HttpServletRequest request, HttpServletResponse response) throws IOException {

		ResourceConstant excelExportConstant = providerEnvConstantDubboCustomerService.getResourceConstant();

		String excelExportPathRoot             = excelExportConstant.getPathRoot();
		String excelExportRelativePathTemplate = excelExportConstant.getPathTemplate();
		String excelExportRelativePathStorage  = excelExportConstant.getPathStorage();

		String storagePath                 = excelExportPathRoot + excelExportRelativePathTemplate;
		String fileRelativePathStoragePath = "/excel/invoice/invoiced/templateImportInvoiced.xlsx";
		String fileName                    = "导入应收账款模板.xlsx";

		AnResponseStreamUtils.download(storagePath + fileRelativePathStoragePath, fileName, response);

	}


	/**
	 * mark excelImport
	 * http://192.168.6.223:8089/web/invoiceInvoiced/importExcel/importExcelAndStoreOpBackCollection
	 *
	 * @param multipartFile
	 * @return
	 * @throws Exception
	 */
	@Deprecated
	@ApiOperation(value = "导入回款-一步登天-难!")
	@RequestMapping(value = "/excelimportAndStoreOpBackCollection", method = RequestMethod.POST)
	@ResponseBody
	public R<String> excelImportAndStoreOpBackCollection(@RequestParam("excelFile") MultipartFile multipartFile) throws Exception {

		String batchId = snowflake.nextIdStr();

		// 有个很重要的点 InvoiceInvoicedImportDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去

		// 写法1:
//		String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
//		// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
//		EasyExcel.read(fileName, InvoiceInvoicedParam.class, new InvoiceInvoicedImportDataListener()).sheet().doRead();

		// 写法2:
//		String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";

		ResourceConstant excelExportConstant = providerEnvConstantDubboCustomerService.getResourceConstant();

		String excelExportPathRoot             = excelExportConstant.getPathRoot();
		String excelExportRelativePathTemplate = excelExportConstant.getPathTemplate();
		String excelExportRelativePathStorage  = excelExportConstant.getPathStorage();

		String relativePath = File.separator + "upload" + File.separator + "invoice" + File.separator + "invoiced" + File.separator + "import" + File.separator + "backCollection" + File.separator;

		String currentDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));

		String targetFullPath = excelExportPathRoot + relativePath + currentDate + File.separator;

		if (!FileUtil.exist(targetFullPath)) {
			FileUtil.mkdir(targetFullPath);
		}

		String fileName = UUID.randomUUID().toString() + "@" + multipartFile.getOriginalFilename();
		String suffix   = Objects.requireNonNull(multipartFile.getOriginalFilename()).substring(multipartFile.getOriginalFilename().lastIndexOf(".") + 1);
		File   file1    = FileUtil.writeBytes(multipartFile.getBytes(), targetFullPath + fileName);

		if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
			throw new UnifiedOrderRuntimeException(ExceptionMsg.SYS_ERROR.getCode(), "上传文件格式不正确");
		}
		boolean isExcel2003 = true;
		if (fileName.matches("^.+\\.(?i)(xlsx)$")) {
			isExcel2003 = false;
		}


		ExcelReader excelReader = null;

		try {
			excelReader = EasyExcel.read(
					multipartFile.getInputStream(),
					InvoiceInvoicedOpBackCollectionForm.class,
					new InvoiceInvoicedImportExcelOpBackCollectionDataListener(
							invoiceInvoicedDubboConsumerService,
							invoiceInvoicedFieldIsBackCollectionDubboConsumerService,
							snowflake,
							batchId,
							getToken()
					))
					.registerConverter(new CustomStringBigDecimalConverter())
					.build();
			ReadSheet readSheet = EasyExcel.readSheet(0).build();
			excelReader.read(readSheet);

		} finally {

			if (excelReader != null) {
				// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
				excelReader.finish();
			}
		}

		return ResponseResultOuterUtils.createSuccesResult("200", batchId);
	}

	/**
	 * TODO 测试中 还是有点问题
	 * mark excelImport
	 * http://192.168.6.223:8089/web/invoiceInvoiced/importExcel/importExcelAndStoreOpBackCollection
	 *
	 * @param multipartFile
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "导入回款-三段式 基础校验-关联校验-反馈-如果没有问题-记录日志-入库")
	@RequestMapping(value = "/excelimportAndStoreOpBackCollection2", method = RequestMethod.POST)
	@ResponseBody
	public R<List<InvoiceInvoicedOpBackCollectionForm>> excelImportAndStoreOpBackCollection2(@RequestParam("excelFile") MultipartFile multipartFile) throws Exception {

		String batchId = snowflake.nextIdStr();

		ResourceConstant excelExportConstant = providerEnvConstantDubboCustomerService.getResourceConstant();

		String excelExportPathRoot             = excelExportConstant.getPathRoot();
		String excelExportRelativePathTemplate = excelExportConstant.getPathTemplate();
		String excelExportRelativePathStorage  = excelExportConstant.getPathStorage();

		String relativePath = File.separator + "upload" + File.separator + "invoice" + File.separator + "invoiced" + File.separator + "import" + File.separator + "backCollection" + File.separator;

		String currentDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));

		String targetFullPath = excelExportPathRoot + relativePath + currentDate + File.separator;

		if (!FileUtil.exist(targetFullPath)) {
			FileUtil.mkdir(targetFullPath);
		}

		String fileName = DateUtil.format(DateUtil.date(), AnDateHelper.CURRENT_DATE) + "@" + UUID.randomUUID().toString() + "@" + multipartFile.getOriginalFilename();
		String suffix   = Objects.requireNonNull(multipartFile.getOriginalFilename()).substring(multipartFile.getOriginalFilename().lastIndexOf(".") + 1);
		File   file1    = FileUtil.writeBytes(multipartFile.getBytes(), targetFullPath + fileName);

		if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
			throw new UnifiedOrderRuntimeException(ExceptionMsg.SYS_ERROR.getCode(), "上传文件格式不正确");
		}
		boolean isExcel2003 = true;
		if (fileName.matches("^.+\\.(?i)(xlsx)$")) {
			isExcel2003 = false;
		}


		List<InvoiceInvoicedOpBackCollectionForm> excelData = ExcelImportReaderUtils
				.builder()
				.inputStream(multipartFile.getInputStream())
				.readSheetNumber(0)
				.headRowNumber(1)
				.build()
				.read(InvoiceInvoicedOpBackCollectionForm.class);

		log.info("{}", AnJsonUtils.toJson(excelData));

		ExcelImportExport.builder()
				.fileFullPath(targetFullPath + fileName)
				.build()
				.write(excelData, InvoiceInvoicedOpBackCollectionForm.class);

		return ResponseResultOuterUtils.createSuccesResult("200", excelData);
	}


	/****************************************** 导入历史 start ******************************************/

	/**
	 * mark excelImport
	 * http://192.168.6.223:8089/web/invoiceInvoiced/importExcel/excelImportAndStoreOpHisotry
	 *
	 * @param multipartFile
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "导入历史-三段式 基础校验-关联校验-反馈-如果没有问题-记录日志-入库")
	@RequestMapping(value = "/excelImportAndStoreOpHisotry", method = RequestMethod.POST)
	@ResponseBody
	public R<List<InvoiceInvoicedHistoryExcelRow>> excelImportAndStoreOpHisotry(@RequestParam("excelFile") MultipartFile multipartFile) throws Exception {

		String batchId = snowflake.nextIdStr();

		ResourceConstant excelExportConstant = providerEnvConstantDubboCustomerService.getResourceConstant();

		String excelExportPathRoot             = excelExportConstant.getPathRoot();
		String excelExportRelativePathTemplate = excelExportConstant.getPathTemplate();
		String excelExportRelativePathStorage  = excelExportConstant.getPathStorage();

		String relativePath = File.separator + "upload" + File.separator + "invoice" + File.separator + "invoiced" + File.separator + "import" + File.separator + "history" + File.separator;

		String currentDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));

		String targetFullPath = excelExportPathRoot + relativePath + currentDate + File.separator;

		if (!FileUtil.exist(targetFullPath)) {
			FileUtil.mkdir(targetFullPath);
		}

		String fileName = DateUtil.format(DateUtil.date(), AnDateHelper.CURRENT_DATE) + "@" + UUID.randomUUID().toString() + "@" + multipartFile.getOriginalFilename();
		String suffix   = Objects.requireNonNull(multipartFile.getOriginalFilename()).substring(multipartFile.getOriginalFilename().lastIndexOf(".") + 1);
		File   file1    = FileUtil.writeBytes(multipartFile.getBytes(), targetFullPath + fileName);

		if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
			throw new UnifiedOrderRuntimeException(ExceptionMsg.SYS_ERROR.getCode(), "上传文件格式不正确");
		}
		boolean isExcel2003 = true;
		if (fileName.matches("^.+\\.(?i)(xlsx)$")) {
			isExcel2003 = false;
		}

		LoginSysUser loginSysUser = JwtUtil.getLoginSysUser(getToken());


		List<InvoiceInvoicedHistoryExcelRow> excelData = ExcelImportReaderUtils
				.builder()
				.loginSysUser(loginSysUser)
				.batchId(batchId)
				.inputStream(multipartFile.getInputStream())
				.readSheetNumber(0)
				.headRowNumber(1)
				.build()
				.read(InvoiceInvoicedHistoryExcelRow.class);

		log.info("Ecxel 读出来 \n{}", AnJsonUtils.toJson(excelData));

		ExcelImportExport
				.builder()
				.loginSysUser(loginSysUser)
				.batchId(batchId)
				.fileFullPath(targetFullPath + fileName)
				.build()
				.write(excelData, InvoiceInvoicedHistoryExcelRow.class);

		return ResponseResultOuterUtils.createSuccesResult("200", excelData);
	}

	/****************************************** 导入应收 start ******************************************/

	/**
	 * mark excelImport
	 * http://192.168.6.223:8089/web/invoiceInvoiced/importExcel/excelImportAndStoreOpNormal
	 *
	 * @param multipartFile
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "导入应收-三段式 基础校验-关联校验-反馈-如果没有问题-记录日志-入库")
	@RequestMapping(value = "/excelImportAndStoreOpNormal", method = RequestMethod.POST)
	@ResponseBody
	public R<List<InvoiceInvoicedNormalExcelRow>> excelImportAndStoreOpNormal(@RequestParam("excelFile") MultipartFile multipartFile) throws Exception {

		String batchId = snowflake.nextIdStr();

		ResourceConstant excelExportConstant = providerEnvConstantDubboCustomerService.getResourceConstant();

		String excelExportPathRoot             = excelExportConstant.getPathRoot();
		String excelExportRelativePathTemplate = excelExportConstant.getPathTemplate();
		String excelExportRelativePathStorage  = excelExportConstant.getPathStorage();

		String relativePath = File.separator + "upload" + File.separator + "invoice" + File.separator + "invoiced" + File.separator + "import" + File.separator + "normal" + File.separator;

		String currentDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));

		String targetFullPath = excelExportPathRoot + relativePath + currentDate + File.separator;

		if (!FileUtil.exist(targetFullPath)) {
			FileUtil.mkdir(targetFullPath);
		}

		String fileName = DateUtil.format(DateUtil.date(), AnDateHelper.CURRENT_DATE) + "@" + UUID.randomUUID().toString() + "@" + multipartFile.getOriginalFilename();
		String suffix   = Objects.requireNonNull(multipartFile.getOriginalFilename()).substring(multipartFile.getOriginalFilename().lastIndexOf(".") + 1);
		File   file1    = FileUtil.writeBytes(multipartFile.getBytes(), targetFullPath + fileName);

		if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
			throw new UnifiedOrderRuntimeException(ExceptionMsg.SYS_ERROR.getCode(), "上传文件格式不正确");
		}
		boolean isExcel2003 = true;
		if (fileName.matches("^.+\\.(?i)(xlsx)$")) {
			isExcel2003 = false;
		}

		LoginSysUser loginSysUser = JwtUtil.getLoginSysUser(getToken());

		List<InvoiceInvoicedNormalExcelRow> excelData = ExcelImportReaderUtils
				.builder()
				.loginSysUser(loginSysUser)
				.batchId(batchId)
				.inputStream(multipartFile.getInputStream())
				.readSheetNumber(0)
				.headRowNumber(1)
				.build()
				.read(InvoiceInvoicedNormalExcelRow.class);

		log.info("{}", AnJsonUtils.toJson(excelData));

		ExcelImportExport
				.builder()
				.loginSysUser(loginSysUser)
				.batchId(batchId)
				.fileFullPath(targetFullPath + fileName)
				.build()
				.write(excelData, InvoiceInvoicedNormalExcelRow.class);

		return ResponseResultOuterUtils.createSuccesResult("200", excelData);
	}


}
