/*
 *      Copyright (c) 2018-2028, Chill Zhuang 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 dreamlu.net 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: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.guosen.bussiness.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.constant.SystemConstant;
import org.springblade.common.utils.MoneyDesUtil;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DigestUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.guosen.bussiness.entity.Bussiness;
import org.springblade.modules.guosen.bussiness.vo.BussinessVO;
import org.springblade.modules.guosen.bussiness.mapper.BussinessMapper;
import org.springblade.modules.guosen.bussiness.service.IBussinessService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.modules.obs.service.ObsService;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springblade.yeePay.service.YeePayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.io.*;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.List;
import java.util.UUID;

import static org.springblade.core.cache.constant.CacheConstant.USER_CACHE;

/**
 *  服务实现类
 *
 * @author BladeX
 * @since 2021-07-08
 */
@Service
@Slf4j
public class BussinessServiceImpl extends BaseServiceImpl<BussinessMapper, Bussiness> implements IBussinessService {

	@Autowired
	private IUserService userService;
	@Autowired
	private ObsService obsService;
	@Autowired
	private YeePayService yeePayService;

	@Override
	public IPage<Bussiness> selectBussinessPage(IPage<Bussiness> page, BussinessVO bussiness) {
		return page.setRecords(baseMapper.selectBussinessPage(page, bussiness));
	}

	@Override
	@Transactional
	public boolean saveOrUpdate(Bussiness bussiness){
		if(bussiness.getId() == null){//新增
			//先创建平台账号，首先要效验下是否已存在相同的账号
			List<Object> users = userService.listObjs(Wrappers.<User>query().lambda().eq(User::getAccount, bussiness.getUserName()));
			if (users != null && users.size() > 0) {
				throw new ServiceException(StringUtil.format("当前用户 [{}] 已存在!", bussiness.getUserName()));
			}
			User user = new User();
			user.setPassword(DigestUtil.hex(bussiness.getUserPassword()));//密码为前端md5加密后
			user.setRoleId(SystemConstant.BUSSINESS_ROLE_ID);
			user.setDeptId(SystemConstant.BUSSINESS_DEPT_ID);
			user.setAccount(bussiness.getUserName());
			if(userService.save(user)){
				bussiness.setAccountId(user.getId());
				bussiness.setUserPassword(DigestUtil.hex(bussiness.getUserPassword()));
				boolean flag = true;
				String secret = null;
				while (flag){
					secret = generateSecret();
					Bussiness isUsed = this.getBaseMapper().selectOne(new QueryWrapper<>(new Bussiness()).lambda()
						.eq(Bussiness::getSecret, secret));
					if(isUsed != null){
						flag = true;
					}else{
						flag = false;
					}
				}
				bussiness.setSecret(secret);
				//余额设置为0
				bussiness.setRemain(MoneyDesUtil.encrypt("0", MoneyDesUtil.KEY_FOR_UC));

				boolean result = this.save(bussiness);
				if(result){
					String remoteUrl = this.generateApiFile(bussiness.getId(), secret);
					bussiness.setApiFilePath(remoteUrl);
					this.updateById(bussiness);
				}

				return result;
			}else {
				System.out.println(0/1);
			}

		}else{//修改
			User user = userService.getById(bussiness.getAccountId());
			user.setAccount(bussiness.getUserName());
			if(StringUtil.isNotBlank(bussiness.getUserPassword())){
				user.setPassword(DigestUtil.hex(bussiness.getUserPassword()));
			}
			userService.updateById(user);
			Bussiness oldEntity = this.getById(bussiness.getId());
			if(StringUtil.isNotBlank(bussiness.getUserPassword())){
				oldEntity.setUserPassword(DigestUtil.hex(bussiness.getUserPassword()));
			}
			oldEntity.setBusinessLicense(bussiness.getBusinessLicense());
			oldEntity.setIcon(bussiness.getIcon());
			oldEntity.setName(bussiness.getName());
			oldEntity.setOrganizationCodeLicense(bussiness.getOrganizationCodeLicense());
			oldEntity.setRecallUrl(bussiness.getRecallUrl());
			oldEntity.setTaxAffairsLicense(bussiness.getTaxAffairsLicense());
			oldEntity.setServiceRate(bussiness.getServiceRate());
			oldEntity.setMaxLimit(bussiness.getMaxLimit());
			oldEntity.setLeastPrice(bussiness.getLeastPrice());
			oldEntity.setBussinessType(bussiness.getBussinessType());
			oldEntity.setParentBussinessId(bussiness.getParentBussinessId());
			oldEntity.setRateStrategyId(bussiness.getRateStrategyId());
			oldEntity.setSubRateStrategyId(bussiness.getSubRateStrategyId());
			oldEntity.setMicroRateStrategyId(bussiness.getMicroRateStrategyId());
			return this.updateById(oldEntity);
		}

		return false;
	}

	@Override
	public String generateApiByBussiness(Bussiness bussiness) {
		return this.generateApiFile(bussiness.getId(),bussiness.getSecret());
	}

	@Override
	public boolean updateRemain(Bussiness bussiness) {
		return this.baseMapper.updateRemain(bussiness.getVersion(),bussiness.getId(),bussiness.getRemain());
	}

	@Override
	public boolean updateFreeze(Bussiness bussiness) {
		return this.baseMapper.updateFreeze(bussiness.getVersion(),bussiness.getId(),bussiness.getFreeze());
	}

	@Override
	public boolean updateRemainFreeze(Bussiness bussiness) {
		return this.baseMapper.updateRemainFreeze(bussiness.getVersion(),bussiness.getId(),bussiness.getFreeze(), bussiness.getRemain());
	}

	@Override
	@Transactional
	public boolean enable(Long bussinessId, Integer enable) {
		Bussiness bussiness = baseMapper.selectById(bussinessId);
		Assert.notNull(bussiness, "采购商不存在");
		bussiness.setEnable(enable);
		boolean update = baseMapper.updateById(bussiness) > 0;
		if(update){
			//逻辑删除后台用户
			if(enable == 1){
				CacheUtil.clear(USER_CACHE);
				return userService.removeUser(String.valueOf(bussiness.getAccountId()));
			}else if(enable == 0){ //启用
				return userService.enable(bussiness.getAccountId());
			}
			return true;
		}else{
			return update;
		}
	}

	//TODO 调试专用
	@Override
	public R<BigDecimal> queryBalance(String merchantNo) {
		BigDecimal balance = new BigDecimal(0.00);
		R result = yeePayService.queryBalance(merchantNo);
		JSONObject data = JSONUtil.parseObj(result.getData());
		String returnCode = data.getStr("returnCode");
		if(returnCode.equals("UA00000")){
			JSONArray accountInfoList = data.getJSONArray("accountInfoList");
			for(Object obj : accountInfoList){
				JSONObject accountInfo = JSONUtil.parseObj(obj);
				String accountType = accountInfo.getStr("accountType");
				if(accountType.equals("FUND_ACCOUNT")){
					Double yeeBalance = accountInfo.getDouble("balance");
					DecimalFormat decimalFormat = new DecimalFormat("0.00");
					balance = balance.add(new BigDecimal(decimalFormat.format(yeeBalance)));
				}
			}
			log.info("=================查询商户<" + merchantNo + ">资金账户余额:" + balance.toString());
			return R.data(balance);
		}else{
			return R.fail(data.getStr("returnMsg"));
		}
	}

	@Override
	public R deleteBussiness(String ids) {
		List<Long> idList = Func.toLongList(ids);
		for(Long bussinessId : idList){
			Bussiness bussiness = this.getById(bussinessId);
			if(bussiness != null){
				Long accountId = bussiness.getAccountId();
				CacheUtil.clear(USER_CACHE);
				userService.removeUser(String.valueOf(accountId));
			}else{
				return R.fail("【 + " + bussiness.getName() + "】" + "不存在，请重新选择删除");
			}
		}
		return R.status(this.deleteLogic(Func.toLongList(ids)));
	}

	@Override
	public Bussiness getByMerchantNo(String merchantNo) {
		LambdaQueryWrapper<Bussiness> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Bussiness::getMerchantNo, merchantNo);
		return baseMapper.selectOne(lambdaQueryWrapper);
	}

	@Override
	public boolean testSaveOrUpdate(Bussiness bussiness) {
		if(bussiness.getId() == null){//新增
			//先创建平台账号，首先要效验下是否已存在相同的账号
			List<Object> users = userService.listObjs(Wrappers.<User>query().lambda().eq(User::getAccount, bussiness.getUserName()));
			if (users != null && users.size() > 0) {
				throw new ServiceException(StringUtil.format("当前体验用户 [{}] 已存在!", bussiness.getUserName()));
			}
			User user = new User();
			user.setPassword(DigestUtil.hex(bussiness.getUserPassword()));//密码为前端md5加密后
			user.setRoleId(SystemConstant.TEST_BUSSINESS_ROLE_ID);
			user.setDeptId(SystemConstant.BUSSINESS_DEPT_ID);
			user.setAccount(bussiness.getUserName());
			if(userService.save(user)){
				bussiness.setAccountId(user.getId());
				bussiness.setUserPassword(DigestUtil.hex(bussiness.getUserPassword()));
				boolean flag = true;
				String secret = null;
				while (flag){
					secret = generateSecret();
					Bussiness isUsed = this.getBaseMapper().selectOne(new QueryWrapper<>(new Bussiness()).lambda()
							.eq(Bussiness::getSecret, secret));
					if(isUsed != null){
						flag = true;
					}else{
						flag = false;
					}
				}
				bussiness.setSecret(secret);
				//余额设置为0
				bussiness.setRemain(MoneyDesUtil.encrypt("0", MoneyDesUtil.KEY_FOR_UC));

				boolean result = this.save(bussiness);
				if(result){
					String remoteUrl = this.generateApiFile(bussiness.getId(), secret);
					bussiness.setApiFilePath(remoteUrl);
					this.updateById(bussiness);
				}

				return result;
			}else {
				System.out.println(0/1);
			}

		}else{//修改
			User user = userService.getById(bussiness.getAccountId());
			user.setAccount(bussiness.getUserName());
			if(StringUtil.isNotBlank(bussiness.getUserPassword())){
				user.setPassword(DigestUtil.hex(bussiness.getUserPassword()));
			}
			userService.updateById(user);
			Bussiness oldEntity = this.getById(bussiness.getId());
			if(StringUtil.isNotBlank(bussiness.getUserPassword())){
				oldEntity.setUserPassword(DigestUtil.hex(bussiness.getUserPassword()));
			}
			oldEntity.setBusinessLicense(bussiness.getBusinessLicense());
			oldEntity.setIcon(bussiness.getIcon());
			oldEntity.setName(bussiness.getName());
			oldEntity.setOrganizationCodeLicense(bussiness.getOrganizationCodeLicense());
			oldEntity.setRecallUrl(bussiness.getRecallUrl());
			oldEntity.setTaxAffairsLicense(bussiness.getTaxAffairsLicense());
			oldEntity.setServiceRate(bussiness.getServiceRate());
			oldEntity.setMaxLimit(bussiness.getMaxLimit());
			oldEntity.setLeastPrice(bussiness.getLeastPrice());
			return this.updateById(oldEntity);
		}

		return false;
	}

	@Override
	public List<Bussiness> getByBussinessType(Integer bussinessType) {
		LambdaQueryWrapper<Bussiness> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Bussiness::getBussinessType, bussinessType);
		return baseMapper.selectList(lambdaQueryWrapper);
	}


	private  String generateSecret(){
		String uuid = UUID.randomUUID().toString();
		char[] cs = new char[32];
		char c = 0;
		for (int i = uuid.length() / 2, j = 1; i-- > 0; ) {
			if ((c = uuid.charAt(i)) != '-') {
				cs[j++] = c;
			}
		}
		return String.valueOf(cs).trim();
	}

	/**
	 * //生成加密的代付接口文档api,打开密码为商户的密钥
	 * @param bussinessId  商户id
	 * @param secret  商户密钥，用于加密api文档
	 * @return
	 */

	private   String generateApiFile(Long bussinessId,String secret){

		String filePath = "pay.pdf";
		String fileName = bussinessId + "pay.pdf";

		FileInputStream fis;
		FileOutputStream fos;
		try {
			fis = new FileInputStream(new File(filePath));
			fos = new FileOutputStream(new File(fileName));
			PdfReader.unethicalreading = true;
			PdfReader reader = new PdfReader(fis);
			PdfStamper stamper = new PdfStamper(reader, fos);
			stamper.setEncryption(secret.getBytes(), secret.getBytes(), PdfWriter.ALLOW_PRINTING, PdfWriter.ENCRYPTION_AES_128);
			stamper.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

			//读取文件
		InputStream in = null;
		try {
			in = new FileInputStream(fileName);

		//上传文件
			String remoteUrl = obsService.postObject(in, fileName);


			File dbfFile = new File(fileName);
			if (dbfFile.exists()) {
				dbfFile.delete();
			}
			return remoteUrl;
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;


	}





}
