package com.jeequan.jeepay.mgr.ctrl.config;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.device.DeviceParams;
import com.jeequan.jeepay.core.model.device.PluginProviderParams;
import com.jeequan.jeepay.core.model.device.PosParams;
import com.jeequan.jeepay.core.utils.StringKit;
import com.jeequan.jeepay.db.entity.DeviceProvideConfig;
import com.jeequan.jeepay.db.entity.MchStoreDevice;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.DeviceProvideConfigService;
import com.jeequan.jeepay.service.impl.MchStoreDeviceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.security.SecureRandom;

/**
 * 设备厂商配置管理类
 *
 * @author zx
 * 
 * @date 2021-12-28 09:15
 */
@Slf4j
@RestController
@RequestMapping("/api/device/provider")
public class DeviceProvideConfigController extends CommonCtrl {

	@Autowired private DeviceProvideConfigService deviceProvideConfigService;
	@Autowired private MchStoreDeviceService mchStoreDeviceService;

	/**
	 * @author: zx
	 * @date: 2021-12-28 09:15
	 * @describe: 厂商配置列表
	 */
	@PreAuthorize("hasAnyAuthority('ENT_DEVICE_SPEAKER_LIST', 'ENT_DEVICE_PRINTER_LIST', 'ENT_DEVICE_POS_LIST', 'ENT_DEVICE_PLUGIN_LIST')")
	@GetMapping
	public ApiRes pages() {
		LambdaQueryWrapper<DeviceProvideConfig> gw = DeviceProvideConfig.gw();
		gw.select(DeviceProvideConfig::getConfigId, DeviceProvideConfig::getConfigDesc, DeviceProvideConfig::getDeviceType, DeviceProvideConfig::getProvider,
				DeviceProvideConfig::getCreatedAt, DeviceProvideConfig::getAppId, DeviceProvideConfig::getState);
		gw.orderByDesc(DeviceProvideConfig::getCreatedAt);

		if (null != getValLong("configId")) {
			gw.eq(DeviceProvideConfig::getConfigId, getValLong("configId"));
		}
		if (null != getValByte("deviceType")) {
			gw.eq(DeviceProvideConfig::getDeviceType, getValByte("deviceType"));
		}
		if (StringUtils.isNotBlank(getValString("provider"))) {
			gw.eq(DeviceProvideConfig::getProvider, getValString("provider"));
		}
		if (StringUtils.isNotBlank(getValString("configDesc"))) {
			gw.like(DeviceProvideConfig::getConfigDesc, getValString("configDesc"));
		}
        if (null != getValByte("state")) {
            gw.eq(DeviceProvideConfig::getState, getValByte("state"));
        }

		IPage<DeviceProvideConfig> page = deviceProvideConfigService.page(getIPage(true), gw);

		//返回数据
		return ApiRes.page(page);
	}

	/**
	 * @author: zx
	 * @date: 2021-12-28 09:15
	 * @describe: 新增设备厂商配置
	 */
    @PreAuthorize("hasAnyAuthority('ENT_DEVICE_SPEAKER_ADD', 'ENT_DEVICE_PRINTER_ADD', 'ENT_DEVICE_POS_ADD', 'ENT_DEVICE_PLUGIN_ADD')")
	@MethodLog(remark = "新增设备厂商配置")
	@PostMapping
	public ApiRes add() {
		DeviceProvideConfig deviceProvideConfig = getObject(DeviceProvideConfig.class);
		deviceProvideConfig.setState(CS.YES);

		// 根据不同设别类型，设置其他参数
		setOtherParamsByDeviceType(deviceProvideConfig);

		if (deviceProvideConfigService.save(deviceProvideConfig)) {
			return ApiRes.ok();
		}
		return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE);
	}

	/**
	 * @author: zx
	 * @date: 2021-12-28 09:15
	 * @describe: 设备厂商配置修改
	 */
    @PreAuthorize("hasAnyAuthority('ENT_DEVICE_SPEAKER_EDIT', 'ENT_DEVICE_PRINTER_EDIT', 'ENT_DEVICE_POS_EDIT', 'ENT_DEVICE_PLUGIN_EDIT')")
	@MethodLog(remark = "设备厂商配置修改")
	@PutMapping("/{configId}")
	public ApiRes update(@PathVariable("configId") Long configId) {
		DeviceProvideConfig updateRecord = getObject(DeviceProvideConfig.class);
		updateRecord.setConfigId(configId);

		DeviceProvideConfig dbRecord = deviceProvideConfigService.getById(configId);
		if (dbRecord == null) {
			return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_SEARCH);
		}

		// 根据不同设别类型，设置其他参数
		updateOtherParamsByDeviceType(dbRecord, updateRecord);

		if(!deviceProvideConfigService.updateById(updateRecord)) {
            return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "更新失败");
        }
		return ApiRes.ok();
	}

	/**
     * @author: zx
     * @date: 2021-12-28 09:15
     * @describe: 根据ID获取设备厂商配置
     */
    @PreAuthorize("hasAnyAuthority('ENT_DEVICE_SPEAKER_VIEW', 'ENT_DEVICE_PRINTER_VIEW', 'ENT_DEVICE_POS_VIEW', 'ENT_DEVICE_PLUGIN_VIEW')")
    @GetMapping("/{configId}")
    public ApiRes get(@PathVariable("configId") Long configId) {

		DeviceProvideConfig provideConfig = deviceProvideConfigService.getById(configId);

		// POS 参数脱敏特殊处理
		if (provideConfig.getDeviceType() == DeviceProvideConfig.DEVICE_TYPE_POS) {
			PosParams posParams = JSONObject.parseObject(provideConfig.getProviderParams(), PosParams.class);
			provideConfig.setProviderParams(posParams.deSenData());

		// 收银插件 参数脱敏特殊处理
		} else if (provideConfig.getDeviceType() == DeviceProvideConfig.DEVICE_TYPE_PLUGIN) {
			PluginProviderParams posParams = JSONObject.parseObject(provideConfig.getProviderParams(), PluginProviderParams.class);
			provideConfig.setProviderParams(posParams.deSenData());
		} else {
			DeviceParams deviceParams = DeviceParams.factory(provideConfig.getProvider(), provideConfig.getProviderParams());
			provideConfig.setProviderParams(deviceParams.deSenData());
		}

		return ApiRes.ok(provideConfig);
    }

	/**
	 * @author: zx
	 * @date: 2021-12-28 09:15
	 * @describe: 删除设备厂商配置
	 */
    @PreAuthorize("hasAnyAuthority('ENT_DEVICE_SPEAKER_DEL', 'ENT_DEVICE_PRINTER_DEL', 'ENT_DEVICE_POS_DEL', 'ENT_DEVICE_PLUGIN_DEL')")
	@MethodLog(remark = "删除设备厂商配置")
	@DeleteMapping("/{configId}")
	public ApiRes delete(@PathVariable("configId") Long configId) {
		if (mchStoreDeviceService.count(MchStoreDevice.gw().eq(MchStoreDevice::getConfigId, configId)) > 0) {
			return ApiRes.customFail("已有设备使用此配置，不可删除！");
		}

		if(deviceProvideConfigService.removeById(configId)) {
			return ApiRes.ok();
		}

		return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_DELETE);
	}


	/** 不同设备类型  单独的参数配置 */
	public void setOtherParamsByDeviceType(DeviceProvideConfig deviceProvideConfig) {
		// 扫码POS  定义appId和appSecret
		if (deviceProvideConfig.getDeviceType() == DeviceProvideConfig.DEVICE_TYPE_POS) {
			String appId = IdUtil.fastSimpleUUID();

			SecureRandom random = RandomUtil.getSecureRandom();
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < 128; i++) {
				sb.append(RandomUtil.BASE_CHAR_NUMBER.charAt(random.nextInt(RandomUtil.BASE_CHAR_NUMBER.length())));
			}

			JSONObject posParams = new JSONObject();
			posParams.put("appId", appId);
			posParams.put("appSecret", sb.toString());

			deviceProvideConfig.setAppId(appId);
			deviceProvideConfig.setProviderParams(posParams.toJSONString());
		}

		// 收银插件  定义appSecret
		else if (deviceProvideConfig.getDeviceType() == DeviceProvideConfig.DEVICE_TYPE_PLUGIN) {
			// SecureRandom random = RandomUtil.getSecureRandom();
			// StringBuilder sb = new StringBuilder();
			// for (int i = 0; i < 64; i++) {
			// 	sb.append(RandomUtil.BASE_CHAR_NUMBER.charAt(random.nextInt(RandomUtil.BASE_CHAR_NUMBER.length())));
			// }
			PluginProviderParams providerParams = JSONObject.parseObject(deviceProvideConfig.getProviderParams(), PluginProviderParams.class);
			deviceProvideConfig.setAppId(providerParams.getAppSecret());
		}

		// 校验APPID唯一
		if (StringUtils.isNotBlank(deviceProvideConfig.getAppId()) &&
				deviceProvideConfigService.count(DeviceProvideConfig.gw().eq(DeviceProvideConfig::getAppId, deviceProvideConfig.getAppId())) > 0) {
			throw new BizException("appId已存在");
		}
	}

	/** 不同设备类型  单独的参数配置 */
	private void updateOtherParamsByDeviceType(DeviceProvideConfig dbRecord, DeviceProvideConfig updateRecord) {
		// 扫码POS 修改appid和appsecret
		if (dbRecord.getDeviceType() == DeviceProvideConfig.DEVICE_TYPE_POS) {
			// 待更新的参数
			PosParams updatePosParams = JSONObject.parseObject(updateRecord.getProviderParams(), PosParams.class);

			// 前端未传入appSecret，需复制数据库的appSecret 再更新
			if (StringUtils.isBlank(updatePosParams.getAppSecret())) {
				PosParams dbPosParams = JSONObject.parseObject(dbRecord.getProviderParams(), PosParams.class);
				updatePosParams.setAppSecret(dbPosParams.getAppSecret());

				updateRecord.setProviderParams(JSON.toJSONString(updatePosParams));
			}
			updateRecord.setAppId(updatePosParams.getAppId());
		}

		// 收银插件 修改appid和appsecret
		else if (dbRecord.getDeviceType() == DeviceProvideConfig.DEVICE_TYPE_PLUGIN) {
			// 待更新的参数
			if (StringUtils.isNotBlank(updateRecord.getProviderParams())) {
				PluginProviderParams updatePluginParams = JSONObject.parseObject(updateRecord.getProviderParams(), PluginProviderParams.class);

				// 前端未传入appSecret，需复制数据库的appSecret 再更新
				if (StringUtils.isBlank(updatePluginParams.getAppSecret())) {
					PluginProviderParams dbPluginParams = JSONObject.parseObject(dbRecord.getProviderParams(), PluginProviderParams.class);
					updatePluginParams.setAppSecret(dbPluginParams.getAppSecret());

					updateRecord.setProviderParams(JSON.toJSONString(updatePluginParams));
				}
				updateRecord.setAppId(updatePluginParams.getAppSecret());
			}
		}

		if (StringUtils.isNotBlank(updateRecord.getProviderParams())) {
			updateRecord.setProviderParams(StringKit.marge(dbRecord.getProviderParams(), updateRecord.getProviderParams(), null));
		}

		// 校验APPID唯一
		if (StringUtils.isNotBlank(updateRecord.getAppId()) &&
				deviceProvideConfigService.count(DeviceProvideConfig.gw()
						.eq(DeviceProvideConfig::getAppId, updateRecord.getAppId())
						.ne(DeviceProvideConfig::getConfigId, dbRecord.getConfigId())) > 0) {
			throw new BizException("appId已存在");
		}
	}

}
