package com.yeejoin.amos.avic.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.stream.Collectors;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.enumeration.UserType;
import org.typroject.tyboot.core.restful.doc.TycloudOperation;
import org.typroject.tyboot.core.restful.doc.TycloudResource;
import org.typroject.tyboot.core.restful.utils.ResponseHelper;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import com.alibaba.fastjson.JSONArray;
import com.yeejoin.amos.avic.config.AmosAuth;
import com.yeejoin.amos.avic.face.model.AvicCustomPathModel;
import com.yeejoin.amos.avic.face.model.TransferModel;
import com.yeejoin.amos.avic.face.orm.entity.AvicCustomPath;
import com.yeejoin.amos.avic.face.service.AvicCustomPathService;
import com.yeejoin.indicators.feign.IndicatorsManager;
import com.yeejoin.indicators.feign.request.DataFetchRequest;
import com.yeejoin.indicators.feign.request.DataRecordRequest;
import com.yeejoin.indicators.feign.request.DataReportAuditRequest;
import com.yeejoin.indicators.feign.workflow.WorkflowManager;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@RestController
@TycloudResource(module = "avic", value = "FileFransfer")
@RequestMapping(value = "/v1/avic/WebServicesFileFransfer")
@Api(tags = "avic-")
public class WebServicesFileFransferResource {
	private final Logger logger = LogManager.getLogger(WebServicesFileFransferResource.class);
	@Value("${avic.webservice.path}")
	String webserviceUrl;

	@Autowired
	IndicatorsManager indicatorsManager;
	@Autowired
	WorkflowManager workflowManager;

	@Autowired
	private AvicCustomPathService simpleService;
	@Autowired
	AmosAuth amosAuth;

	@Value(value = "${upload.temp.dir}")
	String tempDir;
	@Value(value = "${avic.time.connection.timeout}")
	long connectionTimeout;
	@Value(value = "${avic.time.receive.timeout}")
	long receiveTimeout;

	SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSSS");

	@TycloudOperation(ApiLevel = UserType.AGENCY, needAuth = false)
	@ApiOperation(value = "文件下载")
	@GetMapping("/download")
	public void downlaodFile(HttpServletRequest request, HttpServletResponse response,
			@RequestParam("url") String path) {
		// 根路径加上传参数的路径构成文件路径地址
		String realPath = tempDir + path;
		File file = new File(realPath);
		response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
		InputStream is = null;
		OutputStream os = null;
		try {
			is = new FileInputStream(file);
			os = response.getOutputStream();

			for (int b = -1; (b = is.read()) != -1;) {
				os.write(b);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (os != null) {
				try {
					os.flush();
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}
		return;

	}

	@TycloudOperation(ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "文件上传")
	@PostMapping(value = "/fileUpload")
	public ResponseModel fileUpload(@RequestParam(value = "file") MultipartFile file, HttpServletRequest request)
			throws Exception {
		if (file.isEmpty()) {
			throw new Exception("上传文件为空");
		}
		String fileName = file.getOriginalFilename();
		String suffixName = fileName.substring(fileName.lastIndexOf("."));
		String name = fileName.substring(0, fileName.lastIndexOf("."));
		String filePath = tempDir;
		fileName = name + "-" + sdf.format(new Date()) + suffixName;
		File dest = new File(filePath + fileName);
		if (!dest.getParentFile().exists()) {
			dest.getParentFile().mkdirs();
		}
		try {
			file.transferTo(dest);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return ResponseHelper.buildResponse(fileName);
	}

	@TycloudOperation(ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "发起文件传输流程")
	@RequestMapping(value = "/detail/{taskId}", method = RequestMethod.GET)
	public ResponseModel startPostfile(@PathVariable("taskId") String taskId) throws Exception {
		DataFetchRequest request = new DataFetchRequest();
		Map<String, Object> task = indicatorsManager.indicatorClient.getTaskByTaskId(taskId).getResult();
		Map<String, Object> bizTable = indicatorsManager.indicatorClient
				.getBizTableBySubjectId(task.get("bizTableId").toString()).getResult();
		request.setTaskId(taskId);
		request.setPage(1);
		request.setSize(20);
		request.setTableId(bizTable.get("id").toString());
		return ResponseHelper.buildResponse(indicatorsManager.indicatorClient.queryPage(request).getResult());
	}

	@TycloudOperation(ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "发起文件传输流程")
	@RequestMapping(value = "/transfer", method = RequestMethod.POST)
	public ResponseModel startPostfile(@RequestBody TransferModel transferModel) {
		Map<String, Object> task = indicatorsManager.indicatorClient.getTaskByTaskId(transferModel.getTaskId())
				.getResult();
		Map<String, Object> tmpl = indicatorsManager.indicatorClient
				.getTaskTemplateById(task.get("templateId").toString()).getResult();
		try {
			List<DataRecordRequest> list = new ArrayList<>();
			DataRecordRequest dataRecordRequest = new DataRecordRequest();
			dataRecordRequest.put("avicCode", transferModel.getAvicCode());
			dataRecordRequest.put("targetPath", transferModel.getPath());
			System.out.println(JSONArray.toJSON(transferModel.getFiles()).toString());
			dataRecordRequest.put("files", JSONArray.toJSON(transferModel.getFiles()).toString());
			list.add(dataRecordRequest);
			Map<String, Object> bizTable = indicatorsManager.indicatorClient
					.getBizTableBySubjectId(task.get("bizTableId").toString()).getResult();

			indicatorsManager.indicatorClient.saveBizRecord(transferModel.getTaskId(), bizTable.get("id").toString(),
					list);
//			workflowManager.workflowClient.startFormByProcess(null, tmpl.get("processDefinition").toString());
			indicatorsManager.indicatorClient.adopt(transferModel.getTaskId());
		} catch (java.lang.Exception e) {
			e.printStackTrace();
		}
		if (transferModel.getAutoConfirm()) {
			Timer timer = new Timer();
			timer.schedule(new MyTimerTask(transferModel), 1000);
		}

		return ResponseHelper.buildResponse(null);
	}

	class MyTimerTask extends TimerTask {

		TransferModel transferModel;

		MyTimerTask(TransferModel transferModel) {
			this.transferModel = transferModel;
		}

		@Override
		public void run() {
			RequestContext.setToken(amosAuth.getToken());
			RequestContext.setProduct(amosAuth.getProduct());
			RequestContext.setAppKey(amosAuth.getAppKey());
			postfile(transferModel);
		}

	}

	@TycloudOperation(ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "传输")
	@RequestMapping(value = "/confirm", method = RequestMethod.POST)
	public ResponseModel postfile(@RequestBody TransferModel transferModel) {
		auth(transferModel);
		return ResponseHelper.buildResponse(null);
	}

	private void auth(TransferModel transferModel) {
		Map<String, Object> task = indicatorsManager.indicatorClient.getTaskByTaskId(transferModel.getTaskId())
				.getResult();
		syncSendFile(task, transferModel);
		DataReportAuditRequest dataReportAuditRequest = new DataReportAuditRequest();
		dataReportAuditRequest.setTaskId(transferModel.getTaskId());
		dataReportAuditRequest.setInstanceId(task.get("processInstanceId").toString());
		dataReportAuditRequest.setRemark(transferModel.getComment());
		dataReportAuditRequest.setCondition("0");
		indicatorsManager.indicatorClient.auditWorkFlow(dataReportAuditRequest);
	}

	private void syncSendFile(Map<String, Object> task1, TransferModel transferModel1) {

		Thread thread = new Thread(new Runnable() {
			Map<String, Object> task = task1;
			TransferModel transferModel = transferModel1;
			@Override
			public void run() {
				AvicCustomPath avicCustomPath = simpleService.getById(transferModel.getPath());
				try {
					JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
					Client client = dcf.createClient(webserviceUrl);
					HTTPConduit conduit = (HTTPConduit) client.getConduit();
					HTTPClientPolicy policy = new HTTPClientPolicy();
					policy.setConnectionTimeout(connectionTimeout); // 连接超时时间
					policy.setReceiveTimeout(receiveTimeout);// 请求超时时间.
					conduit.setClient(policy);
					if (ObjectUtils.isEmpty(transferModel.getAvicCode())) {
						for (String file : transferModel.getFiles().stream().map(m -> m.getUrl())
								.collect(Collectors.toList())) {
							String filePath = tempDir;
							File dest = new File(filePath + file);
							DataHandler handler = new DataHandler(new FileDataSource(dest));
							client.invoke("transferFile", handler, dest.getName(), avicCustomPath.getPath());
						}
					} else {
						for (String file : transferModel.getFiles().stream().map(m -> m.getUrl())
								.collect(Collectors.toList())) {
							String filePath = tempDir;
							File dest = new File(filePath + file);
							DataHandler handler = new DataHandler(new FileDataSource(dest));
							client.invoke("useCodetransferFile", handler, dest.getName(), avicCustomPath.getPath(),
									transferModel.getAvicCode());
						}
					}
				} catch (java.lang.Exception e) {
					e.printStackTrace();
				}
			}
		});
		thread.start();

	}

	@TycloudOperation(ApiLevel = UserType.AGENCY)
	@ApiOperation(value = "传输目录配置")
	@RequestMapping(value = "/config", method = RequestMethod.POST)
	public ResponseModel postConfig(@RequestBody AvicCustomPathModel model) {
		JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
		Client client = dcf.createClient(webserviceUrl);
		try {
			client.invoke("transferPathConfig", model);
		} catch (java.lang.Exception e) {
			e.printStackTrace();
		}
		return ResponseHelper.buildResponse(null);
	}
}
