package org.springblade.api;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.redisson.Redisson;
import org.redisson.RedissonLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.redis.lock.RedisLock;
import org.springblade.core.tenant.annotation.TenantIgnore;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.FileUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.pl.equipment.entity.EquipmentEntity;
import org.springblade.modules.pl.equipment.service.IEquipmentService;
import org.springblade.modules.pl.factory.entity.FactoryEntity;
import org.springblade.modules.pl.factory.service.IFactoryService;
import org.springblade.modules.pl.inspectionRecords.entity.InspectionRecordsEntity;
import org.springblade.modules.pl.inspectionRecords.service.IInspectionRecordsService;
import org.springblade.modules.pl.product.entity.ProductEntity;
import org.springblade.modules.pl.product.entity.ProductImageRecordEntity;
import org.springblade.modules.pl.product.service.IProductImageRecordService;
import org.springblade.modules.pl.product.service.IProductService;
import org.springblade.modules.pl.product.vo.ProductImageRecordVO;
import org.springblade.modules.pl.productModel.entity.ProductModelEntity;
import org.springblade.modules.pl.productModel.service.IProductModelService;
import org.springblade.modules.resource.builder.OssBuilder;
import org.springblade.webSocket.server.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.socket.WebSocketSession;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@RestController
@AllArgsConstructor
@RequestMapping("pl/camera/api")
@Api(value = "设备", tags = "设备相关外放接口")
@Slf4j
public class CameraApiController {

	/**
	 * 对象存储构建类
	 */
	private final OssBuilder ossBuilder;

	private final IEquipmentService equipmentService;

	private final IProductService productService;

	private final IProductImageRecordService productImageRecordService;

	private final IProductModelService productModelService;

	@Resource
	private final RedissonClient redissonLock;

	private final WebSocketServer webSocketServer;

	private final IFactoryService factoryService;

	private final IInspectionRecordsService inspectionRecordsService;

	/**
	 * 上传文件
	 *
	 * @param file 文件
	 * @return ObjectStat
	 */
	@TenantIgnore
	@PostMapping("/put-file")
	public R putFile(@RequestParam MultipartFile file,@RequestParam String productCode,@RequestParam String macAddress) throws InterruptedException {
		// 获取可重入锁, 指定锁的名称
		RLock lock = redissonLock.getLock("lock:cameraUploadImg:"+productCode);
		// 尝试获取锁
		// 参数1：获取锁的最大等待时间（期间会多次重试获取锁）
		// 参数2：锁自动释放时间
		// 参数3：时间单位
		boolean isGetLock = lock.tryLock(50, 60, TimeUnit.SECONDS);
		String fileUrl = "";
		if (isGetLock) {
			try {
				EquipmentEntity equipmentEntity = equipmentService.getOne(Wrappers.<EquipmentEntity>lambdaQuery().eq(EquipmentEntity::getMacAddress,macAddress),false);
				FactoryEntity factory = null;
				if(equipmentEntity!=null){
					factory = factoryService.getById(equipmentEntity.getFactoryId());
				}
				int randomNumber = new Random().nextInt(90000);
//				String randomString = String.format("%05d", randomNumber);
//				String fileName = DateUtil.format(new Date(),"yyyyMMddHHmmssSSS")+randomString;
				String fileName= "upload/"+(factory==null?"000000":factory.getCode())+"/" + DateUtil.today() + "/"+productCode+"/" + StringUtil.randomUUID() + "." + FileUtil.getFileExtension(file.getOriginalFilename());
				BladeFile bladeFile = ossBuilder.template(equipmentEntity==null?"000000":equipmentEntity.getTenantId(),"minio").putFile(fileName, file.getInputStream());
				fileUrl = bladeFile.getLink();
				if(equipmentEntity!=null){
					if("2".equals(factory.getType())){
						InspectionRecordsEntity inspectionRecords = inspectionRecordsService.submit(productCode,bladeFile.getLink(),equipmentEntity);
						webSocketServer.sendToAll(JSONObject.toJSONString(inspectionRecords));
						if(inspectionRecords.getStatus()==2){
							return R.fail(inspectionRecords.getOcrResult());
						}
					}else{
						ProductImageRecordEntity productImageRecord = new ProductImageRecordEntity();
						productImageRecord.setStatus(1);
						productImageRecord.setQrCode(productCode);
						productImageRecord.setProductImage(bladeFile.getLink());
						ProductImageRecordVO productImageRecordVO = productImageRecordService.submit(productCode,equipmentEntity,productImageRecord,bladeFile,factory);
						webSocketServer.sendToAll(JSONObject.toJSONString(productImageRecordVO));
						if(productImageRecord.getStatus()==2){
							return R.fail(productImageRecord.getMessage());
						}
					}
				}

			} catch (IOException e) {
				log.error("拍照异常",e);
			} finally {
				lock.unlock();
			}
		}
		Map<String,Object> result = new HashMap<>();
		result.put("macAddress",macAddress);
		result.put("productCode",productCode);
		result.put("imgUrl",fileUrl);
		return R.data(result);

	}


	@TenantIgnore
	@PostMapping("/ws_init")
	public Map<String,Object> ws_init(@RequestParam String action,@RequestParam String type,@RequestParam String path ) throws InterruptedException {
		Map<String,Object> param = new HashMap<>();
		param.put("action",action);
		param.put("type",type);
		param.put("path","C:\\Users\\86180\\Desktop\\logo\\logo_jj.png");
		param.put("status","200");
		param.put("result","NG");
		return param;
	}
}
