/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the yifu4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.yifu.cloud.plus.v1.yifu.archives.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fadada.api.bean.req.seal.CancelSealAuthReq;
import com.fadada.api.bean.req.seal.CompanySealListReq;
import com.fadada.api.bean.req.seal.OwnerInfo;
import com.fadada.api.bean.req.seal.SealAuthReq;
import com.fadada.api.bean.rsp.BaseRsp;
import com.fadada.api.bean.rsp.seal.CompanySealListRsp;
import com.fadada.api.bean.rsp.seal.SealRes;
import com.fadada.api.client.SealClient;
import com.fadada.api.exception.ApiException;
import com.yifu.cloud.plus.v1.yifu.archives.entity.FddCompanyInfo;
import com.yifu.cloud.plus.v1.yifu.archives.entity.FddPersonAccount;
import com.yifu.cloud.plus.v1.yifu.archives.entity.FddSealInfo;
import com.yifu.cloud.plus.v1.yifu.archives.entity.FddSealPersonAuth;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.FddSealInfoMapper;
import com.yifu.cloud.plus.v1.yifu.archives.service.*;
import com.yifu.cloud.plus.v1.yifu.archives.utils.FddUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.exception.CheckedException;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.List;

/**
 * 法大大印章
 *
 * @author huyc
 * @date 2022-06-28 16:24:12
 */
@Service
@RequiredArgsConstructor
public class FddSealInfoServiceImpl extends ServiceImpl<FddSealInfoMapper, FddSealInfo> implements FddSealInfoService {

	private final FddUtil fddUtil;

	private final FddSealPersonAuthService fddSealPersonAuthService;

	private final FddCompanyInfoService fddCompanyInfoService;

	private final FddPersonAccountService fddPersonAccountService;

	private final FddReqLogService reqLogService;

	@Override
	public List<FddSealInfo> getFddSealInfoPage(FddSealInfo fddSealInfo) {
		long count = this.count(Wrappers.<FddSealInfo>query().lambda().eq(FddSealInfo::getStatus,CommonConstants.TWO_STRING));
		if (count == CommonConstants.ZERO_INT) {
			//初始化印章
			//发送请求
			CompanySealListReq req = new CompanySealListReq();
			try {
				//获取法大大印章列表
				BaseRsp<CompanySealListRsp> rsp = getCompanySealListRspBaseRsp(req);
				if (StringUtils.equals(rsp.getCode(), FddUtil.SUCCESS)) {
					List<SealRes> seals = rsp.getData().getSeals();
					for (SealRes seal : seals) {
						FddSealInfo sealInfo = new FddSealInfo();
						sealInfo.setSealName(seal.getSealName());
						sealInfo.setDeleteFlag(CommonConstants.ZERO_INT);
						sealInfo.setSealId(String.valueOf(seal.getSealId()));
						sealInfo.setStatus(String.valueOf(seal.getStatus()));
						sealInfo.setSysFlag(String.valueOf(seal.getSysFlag()));
						this.save(sealInfo);
					}
				}
			} catch (ApiException e) {
				e.printStackTrace();
			}
		} else {
			List<FddSealInfo> records = this.list(Wrappers.<FddSealInfo>query().lambda().eq(FddSealInfo::getStatus,CommonConstants.TWO_STRING));
			for (FddSealInfo record : records) {
				//判断列表中法大大的sealId是否都存在。如果不存在,则获取记录,并更新印章值
				if (StringUtils.isEmpty(record.getSealId()) && StringUtils.isEmpty(record.getStatus())) {
					//发送请求
					CompanySealListReq req = new CompanySealListReq();
					try {
						//获取法大大印章列表
						BaseRsp<CompanySealListRsp> rsp = getCompanySealListRspBaseRsp(req);
						if (StringUtils.equals(rsp.getCode(), FddUtil.SUCCESS)) {
							List<SealRes> seals = rsp.getData().getSeals();
							for (SealRes seal : seals) {
								if (StringUtils.equals(seal.getSealName(), record.getSealName())) {
									record.setSealId(String.valueOf(seal.getSealId()));
									record.setStatus(String.valueOf(seal.getStatus()));
									record.setSysFlag(String.valueOf(seal.getSysFlag()));
									this.updateById(record);
								}
							}

						}
					} catch (ApiException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return baseMapper.getFddSealInfoPage(fddSealInfo);
	}

	@Override
	public R<String> sealAuth(List<String> id, String fddPersonAccountId) throws ApiException {
		for (String sId : id) {
			FddSealInfo entity = this.getById(sId);
			if (entity == null) {
				return R.failed("未获取到印章信息");
			}
			//获取员工信息
			FddPersonAccount fddPersonAccount = fddPersonAccountService.getById(fddPersonAccountId);
			if (fddPersonAccount == null) {
				return R.failed("未获取到员工信息");
			}
			FddSealPersonAuth fddSealPersonAuth = fddSealPersonAuthService.getOne(Wrappers.<FddSealPersonAuth>query().lambda().eq(FddSealPersonAuth::getFddPersonAccountId, fddPersonAccountId)
					.eq(FddSealPersonAuth::getSealId, entity.getSealId()));
			if (fddSealPersonAuth != null) {
				return R.failed("当前印章已经授权该员工");
			}
			SealAuthReq req = new SealAuthReq();
			req.setToken(fddUtil.getToken());
			SealAuthReq.EmployeeInfo employeeInfo = new SealAuthReq.EmployeeInfo();
			employeeInfo.setUnionId(fddPersonAccount.getUnionid());
			req.setEmployeeInfo(employeeInfo);
			OwnerInfo owner = new OwnerInfo();
			FddCompanyInfo fddCompanyInfo1 = fddCompanyInfoService.getOne(Wrappers.<FddCompanyInfo>query().lambda().eq(FddCompanyInfo::getId, entity.getSealCompanyId()));
			owner.setUnionId(fddCompanyInfo1.getCompanyUnionId());
			req.setOwner(owner);
			SealAuthReq.SealInfo seal = new SealAuthReq.SealInfo();
			seal.setSealId(entity.getSealId());
			req.setSealInfo(seal);
			//发送请求
			SealClient sealClient = new SealClient(fddUtil.getFadadaApiClient());
			BaseRsp rsp = sealClient.sealAuth(req);
			reqLogService.saveLog(this.getClass().getName(), Thread.currentThread().getStackTrace()[1].getMethodName(), req, rsp);
			if (StringUtils.equals(rsp.getCode(), FddUtil.SUCCESS)) {
				//生成授权数据
				FddSealPersonAuth auth = new FddSealPersonAuth();
				auth.setFddPersonAccountId(fddPersonAccount.getId());
				auth.setSealId(entity.getSealId());
				auth.setStatus(CommonConstants.ONE_STRING);
				fddSealPersonAuthService.save(auth);
			}else {
				throw new CheckedException(rsp.getMsg());
			}
		}
		return R.ok();
	}

	@Override
	public R<String> cancelSealAuth(List<String> id, String fddPersonAccountId) throws ApiException {
		for (String sId : id) {
			FddSealInfo entity = this.getById(sId);
			if (entity == null) {
				return R.failed("未获取到印章信息");
			}
			FddSealPersonAuth fddSealPersonAuth = fddSealPersonAuthService.getOne(Wrappers.<FddSealPersonAuth>query().lambda().eq(FddSealPersonAuth::getFddPersonAccountId, fddPersonAccountId)
					.eq(FddSealPersonAuth::getSealId, entity.getSealId()));
			if (fddSealPersonAuth == null) {
				return R.failed("未获取到印章对应的授权员工信息");
			}
			//获取员工信息
			FddPersonAccount fddPersonAccount = fddPersonAccountService.getById(fddPersonAccountId);
			if (fddPersonAccount == null) {
				return R.failed("未获取到员工信息");
			}
			CancelSealAuthReq req = new CancelSealAuthReq();
			req.setToken(fddUtil.getToken());
			CancelSealAuthReq.EmployeeInfo employeeInfo = new CancelSealAuthReq.EmployeeInfo();
			employeeInfo.setUnionId(fddPersonAccount.getUnionid());
			req.setEmployeeInfo(employeeInfo);
			CancelSealAuthReq.SealInfo seal = new CancelSealAuthReq.SealInfo();
			seal.setSealId(entity.getSealId());
			req.setSealInfo(seal);
			//发送请求
			SealClient sealClient = new SealClient(fddUtil.getFadadaApiClient());
			BaseRsp rsp = sealClient.cancelSealAuth(req);
			reqLogService.saveLog(this.getClass().getName(), Thread.currentThread().getStackTrace()[1].getMethodName(), req, rsp);
			if (StringUtils.equals(rsp.getCode(), FddUtil.SUCCESS)) {
				//生成授权数据
				fddSealPersonAuthService.removeById(fddSealPersonAuth);
			} else {
				return R.failed("取消印章授权失败");
			}
		}
		return R.ok();
	}

	/**
	 * @param req
	 * @Author: huyc
	 * @Date: 2022/6/29
	 * @Description: 获取法大大印章列表
	 * @return: com.fadada.api.bean.rsp.BaseRsp<com.fadada.api.bean.rsp.seal.CompanySealListRsp>
	 **/
	private BaseRsp<CompanySealListRsp> getCompanySealListRspBaseRsp(CompanySealListReq req) throws ApiException {
		req.setToken(fddUtil.getToken());
		req.setSealInfo(CommonConstants.ONE_INT);
		SealClient sealClient = new SealClient(fddUtil.getFadadaApiClient());
		BaseRsp<CompanySealListRsp> rsp = sealClient.companySealList(req);
		reqLogService.saveLog(this.getClass().getName(), Thread.currentThread().getStackTrace()[1].getMethodName(), req, rsp);
		return rsp;
	}

	/**
	 * @param file
	 * @Author: huyc
	 * @Date: 2022/6/30
	 * @Description: MultipartFile转file
	 * @return: java.io.File
	 **/
	public static File multipartFileToFile(MultipartFile file) throws IOException {
		File toFile;
		InputStream ins;
		ins = file.getInputStream();
		toFile = new File(file.getOriginalFilename());
		inputStreamToFile(ins, toFile);
		ins.close();
		return toFile;
	}
	/**
	 * @param ins
	 * @param file
	 * @Author: huyc
	 * @Date: 2022/6/30
	 * @Description: 获取流文件
	 * @return: void
	 **/
	private static void inputStreamToFile(InputStream ins, File file) throws IOException {
		try {
			OutputStream os = new FileOutputStream(file);
			int bytesRead;
			int byteLength = 8192;
			byte[] buffer = new byte[byteLength];
			while ((bytesRead = ins.read(buffer, 0, byteLength)) != -1) {
				os.write(buffer, 0, bytesRead);
			}
			os.close();
			ins.close();
		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		}
	}

}
