package org.springblade.gateway.common_gateway.controller;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.aliyuncs.ram.model.v20150501.ListUsersForGroupResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.bouncycastle.util.encoders.UTF8;
import org.springblade.common.enums.AppConstant;
import org.springblade.common.enums.ResCode;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.tenant.mp.TenantEntity;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.DigestUtil;
import org.springblade.gateway.shop_gateway.entity.dto.AppAccountDto;
import org.springblade.ldt.account.entity.Account;
import org.springblade.ldt.account.service.IAccountService;
import org.springblade.ldt.mall.entity.Mall;
import org.springblade.ldt.mall.service.IMallService;
import org.springblade.ldt.shop.entity.Shop;
import org.springblade.ldt.shop.service.IShopService;
import org.springblade.modules.auth.utils.TokenUtil;
import org.springblade.modules.resource.enums.SmsCodeEnum;
import org.springblade.modules.resource.utils.SmsUtil;
import org.springblade.modules.system.entity.Tenant;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.entity.UserInfo;
import org.springblade.modules.system.service.ITenantService;
import org.springblade.modules.system.service.IUserService;
import org.springblade.modules.system.service.impl.UserServiceImpl;
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.RestController;

import javax.validation.Valid;
import java.util.*;

/**
 * @author cy-computer
 */
@Api(tags = "商户登录模块")
@RestController
@RequestMapping("/common/account")
@AllArgsConstructor
public class AppAccountController {

	private IAccountService accountService;
	private IShopService shopService;
	private IMallService mallService;
	private UserServiceImpl userService;

	@PostMapping("login")
	@ApiOperation(value = "商户登录")
	@SneakyThrows
	public R login(@RequestBody Account account) throws ServiceException {
		Assert.notNull(account.getPhone(), "手机号不能为空");
		Assert.notNull(account.getSecret(), "密码不能为空");
		Account user = accountService.getOne(new QueryWrapper<Account>().lambda()
			.eq(Account::getPhone, account.getPhone())
			.eq(Account::getType, account.getType()));
		Assert.notNull(user, () -> {
			throw new ServiceException(ResCode.USER_NOT_FOUNT);
		});

		Assert.isTrue(Objects.equals(user.getSecret(), DigestUtil.hex(account.getSecret())), () -> {
			throw new ServiceException(ResCode.USER_PWS_ERROR);
		});
		return R.data(buildRes(account.getType(),account.getPhone()));
	}


	@PostMapping("register")
	@ApiOperation(value = "注册账号")
	@SneakyThrows
	public R register(@RequestBody @Valid AppAccountDto appAccountDto) {
		Assert.notNull(appAccountDto.getSecret(), "密码不能为空");
		Account isExit = accountService.getOne(Condition.getQueryWrapper(new Account()).lambda()
			.eq(Account::getPhone, appAccountDto.getPhone())
			.eq(Account::getType, AppConstant.PLATFORM.SHOP.name()));
		Assert.isNull(isExit, "该手机号已注册");

		Assert.isTrue(SmsUtil.validateMessage(SmsCodeEnum.VALIDATE.name(), appAccountDto.getSmsId(), appAccountDto.getValue(), appAccountDto.getPhone()),
			() -> {
				throw new ServiceException(ResCode.VALIDATE_FAIL);
			});
		Account account = new Account();
		BeanUtil.copyProperties(appAccountDto, account);
		account.setType(AppConstant.PLATFORM.SHOP.name());
		account.setSecret(DigestUtil.hex(account.getSecret()));
		Assert.isTrue(accountService.saveOrUpdate(account), () -> {
			throw new ServiceException(ResCode.SHOP_REGISTER_ERROR);
		});
		return R.data(account);
	}

	@PostMapping("phoneLogin")
	@ApiOperation(value = "手机号登录")
	@SneakyThrows
	public R phoneLogin(@RequestBody @Valid AppAccountDto appAccountDto) {
		this.VerifyCode(appAccountDto);
		return R.data(buildRes(appAccountDto.getType(),appAccountDto.getPhone()));
	}

	@PostMapping("forgetPsw")
	@ApiOperation(value = "忘记密码")
	@SneakyThrows
	public R forgetPsw(@RequestBody @Valid AppAccountDto appAccountDto) {
		Assert.notNull(appAccountDto.getSecret(), "新密码不能为空");
		Account account = this.VerifyCode(appAccountDto);
		account.setSecret(DigestUtil.hex(appAccountDto.getSecret()));
		return R.data(accountService.updateById(account));
	}

	@PostMapping("updatePsw")
	@ApiOperation(value = "修改密码")
	@SneakyThrows
	public R updatePsw(@RequestBody AppAccountDto appAccountDto) {
		Assert.notNull(appAccountDto.getPhone(), "手机号不能为空");
		Assert.notNull(appAccountDto.getSecret(), "新密码不能为空");
		Assert.notNull(appAccountDto.getOldSecret(), "旧密码不能为空");
		Assert.notNull(appAccountDto.getType(), "类型不能为空");

		//通过旧密码获取账号
		Account account = accountService.getOne(Condition.getQueryWrapper(new Account()).lambda()
			.eq(Account::getSecret,DigestUtil.hex(appAccountDto.getOldSecret()) )
			.eq(Account::getPhone, appAccountDto.getPhone())
			.eq(Account::getType, appAccountDto.getType()));
		Assert.notNull(account, () -> {
			throw new ServiceException(ResCode.USER_PWS_ERROR);
		});
		account.setSecret(DigestUtil.hex(appAccountDto.getSecret()));
		return R.status(accountService.updateById(account));
	}

	/**
	 * 验证验证码
	 *
	 * @return
	 */
	@SneakyThrows
	private Account VerifyCode(AppAccountDto appAccountDto) {
		Account account = accountService.getOne(new QueryWrapper<Account>().lambda()
			.eq(Account::getPhone, appAccountDto.getPhone())
			.eq(Account::getType, appAccountDto.getType()));
		Assert.notNull(account, () -> {
			throw new ServiceException(ResCode.USER_NOT_FOUNT);
		});
		Assert.isTrue(SmsUtil.validateMessage(SmsCodeEnum.VALIDATE.getName(), appAccountDto.getSmsId(), appAccountDto.getValue(), appAccountDto.getPhone()),
			() -> {
				throw new ServiceException(ResCode.VALIDATE_FAIL);
			});
		return account;
	}


	private List getPlatform(String type, String phone) {
		List list;
		if (AppConstant.PLATFORM.SHOP.name().equals(type)){
			list= shopService.list(Condition.getQueryWrapper(new Shop()).lambda().eq(Shop::getPersonTel, phone));
		}else {
			list = mallService.list(Condition.getQueryWrapper(new Mall()).lambda().eq(Mall::getPersonTel, phone));
		}
		return list;
	}


	/***
	 * 封装回传参数
	 *
	 * @param type
	 * @param phone*/
	private Map<String,Object> buildRes(String type, String phone){
		//店铺列表
		List list = getPlatform(type, phone);
		//获取租户ID
		String tenantId = fetchTenant(list);
		//获取租户信息，构建Token
		User user = userService.getBaseMapper().selectOne(new QueryWrapper<User>().lambda().eq(User::getTenantId, tenantId).orderByAsc(User::getCreateTime).last("limit 1"));
		UserInfo userInfo = userService.buildUserInfo(user);
		Kv authInfo = TokenUtil.createAuthInfo(userInfo);
		authInfo.put("list",list);
		return authInfo;
	}

	/**
	 * 根据商场或者商家列表获取租户Id
	 *
	 * @return*/
	private String fetchTenant(List list) {
		if (list.size()==0){
			return AppConstant.PLATFORM_TENANT_ID;
		}
		Object item = list.get(0);

		if(item instanceof Shop){
			Shop shop = (Shop) item;
			Mall mall = mallService.getById(shop.getMallId());
			String tenantId = StrUtil.isNotEmpty(shop.getTenantId()) ?
				shop.getTenantId() :
				Optional.ofNullable(mall).map(Mall::getTenantId).orElse(AppConstant.PLATFORM_TENANT_ID);
			return tenantId;
		}

		if(item instanceof Mall){
			return ((Mall) item).getTenantId();
		}
		return AppConstant.PLATFORM_TENANT_ID;
	}
}
