package org.springblade.modules.api.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
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 io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springblade.common.constant.CommonConstant;
import org.springblade.common.enums.TrademarkTypeEnum;
import org.springblade.common.utils.RedisTool;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.activities.service.ISignInService;
import org.springblade.modules.activities.vo.SignInVO;
import org.springblade.modules.api.request.*;
import org.springblade.modules.api.service.IApiService;
import org.springblade.modules.custom.entity.Trademark;
import org.springblade.modules.custom.service.ITrademarkAuthService;
import org.springblade.modules.custom.service.ITrademarkService;
import org.springblade.modules.custom.vo.TrademarkAuthVO;
import org.springblade.modules.custom.vo.TrademarkVO;
import org.springblade.modules.platform.entity.*;
import org.springblade.modules.platform.service.*;
import org.springblade.modules.platform.vo.*;
import org.springblade.modules.platform.wrapper.UserAddressWrapper;
import org.springblade.modules.platform.wrapper.UserBankCardsWrapper;
import org.springblade.modules.system.entity.Region;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.entity.UserApp;
import org.springblade.modules.system.entity.UserWeChat;
import org.springblade.modules.system.service.IRegionService;
import org.springblade.modules.system.service.IUserService;
import org.springblade.modules.system.service.IUserWeChatService;
import org.springblade.modules.system.vo.UserAppVO;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;

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

/**
 * 控制器
 *
 * @author xuwei
 * @since 2022-02-12
 */
@RestController
@AllArgsConstructor
@RequestMapping(CommonConstant.API_URL)
@Api(value = "我的", tags = "04.个人中心")
public class UserCenterController extends BladeController {

	private final IUserAddressService userAddressService;
	private final IUserFeedbacksService userFeedbacksService;
	private final IUserService userService;
	private final IUserRecomService userRecomService;
	private final IUserBankCardsService userBankCardsService;
	private final IVersionUpgradeService versionUpgradeService;
	private final IApiService apiService;
	private final IRegionService regionService;
	private final IFreightService freightService;
	private final IUserCardInfoService userCardInfoService;
	private final BladeRedis bladeRedis;
	private final IUserIntegralService userScoresService;
	private final ISignInService signInService;
	private final IMerchantSettleService merchantSettleService;
	private final ITrademarkService trademarkService;
	private final ITrademarkAuthService trademarkAuthService;
	private final IUserWeChatService userWeChatService;
	private final IUserAppService userAppService;

	@Resource
	private RedisTool redisTool;
	@Resource
	private IUserAppService IUserAppService;

	@GetMapping("/userInfo/get")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "获取用户信息")
	public R<UserAppVO> userDetailById() {
		return R.data(apiService.getUserAppVo(getUser().getUserId()));
	}

	@GetMapping("/userInfo/getByUserId")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "获取用户信息")
	public R<UserAppVO> getByUserId(@RequestParam Long userId) {
		Assert.notNull(userId, "userId 不能为空");
		return R.data(apiService.getUserAppVo(userId));
	}

	@PostMapping("/userInfo/save")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "修改用户资料", notes = "传入用户ID")
	public R userUpdateById(@Valid @RequestBody UserAppUpdateRequest request) {
		User user = new User();
		user.setId(request.getUserId());
		user.setName(request.getName());
		user.setAvatar(request.getAvatar());
		user.setSex(request.getSex());
		user.setBirthday(request.getBirthday());
		boolean flg = userService.updateById(user);
		if (flg){
			//清除缓存
			bladeRedis.del(String.valueOf(request.getUserId()));
			CacheUtil.clear(USER_CACHE);
			return R.success("操作成功");
		}
		return R.fail("操作失败");
	}

	@PostMapping("/userApp-updateByUserId")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "修改简介说明", notes = "传入用户ID")
	public R userAppUpdateByUserId(@ApiParam(value = "用户ID", required = true) @RequestParam Long userId,
								   @ApiParam(value = "简介说明", required = true) @RequestParam String userExplain) {
		UserApp userApp = new UserApp();
		userApp.setUserExplain(userExplain);
		boolean flg = userApp.update(Wrappers.<UserApp>lambdaQuery().eq(UserApp::getUserId,userId));
		if (flg){
			//清除缓存
			bladeRedis.del(String.valueOf(userId));
			return R.success("操作成功");
		}
		return R.fail("操作失败");
	}

	@GetMapping("/userAddress-page")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "查询用户地址数据", notes = "传入用户ID")
	public R<List<UserAddress>> userAddressPage(@ApiParam(value = "用户ID", required = true) @RequestParam Long userId, Query query) {
		UserAddress userAddress = new UserAddress();
		userAddress.setUserId(userId);
		IPage<UserAddress> list = userAddressService.page(Condition.getPage(query), Condition.getQueryWrapper(userAddress));
		return R.data(list.getRecords());
	}

	@GetMapping("/userAddress-detailById")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "查询用户地址详情", notes = "传入地址ID, 0获取地址详情（传入地址ID）,1默认地址状态（用户ID）, 2获取地址详情并返回运费（传入地址ID）")
	public R<UserAddressVO> userAddressDetailById(@ApiParam(value = "地址ID/用户ID", required = true) @RequestParam Long id,
												  @ApiParam(value = "类型,默认为0", required = true) @RequestParam Integer type) {
		UserAddress userAddress = new UserAddress();
		if (type == 1){
			userAddress.setUserId(id);
			userAddress.setDefaultState(2);//默认标识
			UserAddress query = userAddressService.getOne(Condition.getQueryWrapper(userAddress));
			if(query == null){
				return R.fail("该地址不存在");
			}
			UserAddressVO vo = UserAddressWrapper.build().entityVO(query);
			vo.setWlPrice(0D);
			return R.data(vo);
		}else if (type == 2){
			UserAddress query = userAddressService.getById(id);
			if(query == null){
				return R.fail("该地址不存在");
			}
			UserAddressVO vo = UserAddressWrapper.build().entityVO(query);
			Region region = regionService.getById(vo.getDistrictCode());
			vo.setWlPrice(0D);
			if (region != null){
				Freight freight = freightService.getOne(Wrappers.<Freight>lambdaQuery().eq(Freight::getCode, region.getProvinceCode()));
				if (freight != null){
					vo.setWlPrice(freight.getFreight());
				}
			}
			return R.data(vo);
		}else{
			UserAddress query = userAddressService.getById(id);
			if(query == null){
				return R.fail("该地址不存在");
			}
			UserAddressVO vo = UserAddressWrapper.build().entityVO(query);
			vo.setWlPrice(0D);
			return R.data(vo);
		}
	}

	@GetMapping("/userAddress-detailByUserId")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "查询用户默认地址", notes = "传入用户ID")
	public R<UserAddress> userAddressDetailByUserId(@ApiParam(value = "用户ID", required = true) @RequestParam Long userId) {
		UserAddress userAddress = new UserAddress();
		userAddress.setUserId(userId);
		userAddress.setDefaultState(2);//默认标识
		return R.data(userAddressService.getOne(Condition.getQueryWrapper(userAddress)));
	}

	@PostMapping("/userAddress-remove")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "删除用户地址", notes = "传入ids,可以批量删除，格式xx,xxx,xx")
	public R userAddressRemove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {

		return R.status(userAddressService.removeByIds(Func.toLongList(ids)));
	}

	@PostMapping("/userAddress-save")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "添加用户地址", notes = "添加用户地址")
	public R userAddressSave(@Valid @RequestBody AddressSaveRequest request) {
		if(StringUtil.isNotBlank(request.getPhone()) && !PhoneUtil.isMobile(request.getPhone())){
			return R.fail("请输入正确的手机号");
		}
		if(StringUtil.isEmpty(request.getUserId())){
			return R.fail("请求参数错误！");
		}
		UserAddress userAddress = Objects.requireNonNull(BeanUtil.copy(request, UserAddress.class));
		if (StringUtil.isEmpty(request.getDefaultState())){
			userAddress.setDefaultState(1);
		}
		if (StringUtil.isEmpty(request.getDetail())){
			return R.fail("请输入详细地址！");
		}
		userAddress.setCreateTime(DateUtil.now());
		//设置默认地址
		if (userAddress.getDefaultState() == 2){
			//用户所有的改为不默认
			UserAddress param = new UserAddress();
			param.setUserId(request.getUserId());
			UserAddress entity= new UserAddress();
			entity.setDefaultState(1);
			userAddressService.update(entity, Condition.getQueryWrapper(param));
			//清除缓存
			bladeRedis.del(String.valueOf(request.getUserId()));
		}
		return R.status(userAddressService.save(userAddress));
	}

	@PostMapping("/userAddress-update")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "修改用户收货地址", notes = "修改用户地址")
	public R userAddressUpdate(@Valid @RequestBody AddressUpdateRequest request) {
		/*if(StringUtil.isNotBlank(request.getPhone()) && !PhoneUtil.isMobile(request.getPhone())){
			return R.fail("请输入正确的手机号");
		}*/
		UserAddress userAddress = Objects.requireNonNull(BeanUtil.copy(request, UserAddress.class));
		userAddress.setUpdateTime(DateUtil.now());
		if (userAddress.getDefaultState() == 2){
			UserAddress entity= new UserAddress();
			entity.setDefaultState(1);
			UserAddress param = new UserAddress();
			param.setUserId(request.getUserId());
			userAddressService.update(entity, Condition.getQueryWrapper(param));
		}
		return R.status(userAddressService.updateById(userAddress));
	}

	@GetMapping("/userFeedbacks-page")
	@ApiOperationSupport(order = 9)
	@ApiOperation(value = "查询反馈意见数据", notes = "传入用户ID")
	public R<List<UserFeedbacks>> userFeedbacksPage(@ApiParam(value = "用户ID", required = true) @RequestParam Long userId, Query query) {
		UserFeedbacks userFeedbacks = new UserFeedbacks();
		userFeedbacks.setUserId(userId);
		IPage<UserFeedbacks> list = userFeedbacksService.page(Condition.getPage(query),
			Condition.getQueryWrapper(userFeedbacks).lambda().orderByAsc(UserFeedbacks::getCreateTime));
		return R.data(list.getRecords());
	}

	@GetMapping("/userFeedbacks-detailById")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "反馈意见详情", notes = "传入意见ID")
	public R<UserFeedbacks> userFeedbacksDetailById(@ApiParam(value = "意见ID", required = true) @RequestParam String id) {
		return R.data(userFeedbacksService.getById(id));
	}

	@PostMapping("/userFeedbacks-save")
	@ApiOperationSupport(order = 11)
	@ApiOperation(value = "添加反馈意见", notes = "添加反馈意见")
	public R userFeedbacksSave(@Valid @RequestBody UserFeedbacksSaveRequest request) {
		UserFeedbacks userFeedbacks = Objects.requireNonNull(BeanUtil.copy(request, UserFeedbacks.class));
		userFeedbacks.setCreateTime(DateUtil.now());
		return R.status(userFeedbacksService.save(userFeedbacks));
	}

	@PostMapping("/getMyDetail")
	@ApiOperationSupport(order = 12)
	@ApiOperation(value = "查询个人数据")
	public R getMyDetail(@ApiParam(value = "用户ID", required = true) @RequestParam Long userId){
		UserApp userApp = new UserApp();
		UserApp app = userApp.selectOne(Condition.getQueryWrapper(userApp).lambda().eq(UserApp::getUserId, userId));
		User user = userService.getById(userId);
		Map<Object, Object> map = new HashMap<>();
		map.put("nowMoney", app.getNowMoney());//余额
		map.put("redMoney", app.getRedMoney());//红包余额
		map.put("ticket", app.getTicket());//绿色积分
		map.put("account", user.getAccount());//账号
		return R.data(map);
	}

	@PostMapping("/getUserByAccount")
	@ApiOperationSupport(order = 13)
	@ApiOperation(value = "通过电话查询个人数据")
	public R getUserByAccount(@ApiParam(value = "用户电话", required = true) @RequestParam Long account){
		User user = userService.getOne(Wrappers.lambdaQuery(User.class).eq(User::getAccount, account));
		if(ObjectUtil.isNull(user)){
			return R.fail("用户电话不正确，查询不到用户请核实");
		}
		UserApp userApp = new UserApp();
		UserApp app = userApp.selectOne(Condition.getQueryWrapper(userApp).lambda().eq(UserApp::getUserId, user.getId()));
		User parentUser = userService.getById(app.getParentId());
		Map<Object, Object> map = new HashMap<>();
		map.put("nowMoney", app.getNowMoney());//余额
		map.put("redMoney", app.getRedMoney());//余额
		map.put("ticket", app.getTicket());//绿色积分
		map.put("integral", app.getIntegral());//红色积分
		map.put("userId", user.getId());//用户id
		map.put("userName", user.getRealName());//用户id
		map.put("account", account);//用户电话
		map.put("parentUserName", parentUser.getRealName());//推荐人名称
		map.put("parentUserAccount", parentUser.getAccount());//推荐人电话

		String roleName = "";
		if(app.getIsRole() == 1){
			roleName = "城市合伙人";
		}else if(app.getIsRole() == 2){
			roleName = "创客";
		}else {
			roleName = "城市合伙人,创客";
		}
		map.put("roleName", roleName);//用户角色名称
		return R.data(map);
	}




	@GetMapping("/userBankCards-page")
	@ApiOperationSupport(order = 14)
	@ApiOperation(value = "查询用户银行卡数据", notes = "传入用户ID")
	public R<List<UserBankCardsVO>> userBankCardsPage(@ApiParam(value = "用户ID", required = true) @RequestParam Long userId, Query query) {
		UserBankCards userBankCards = new UserBankCards();
		userBankCards.setUserId(userId);
		IPage<UserBankCards> list = userBankCardsService.page(Condition.getPage(query),
			Condition.getQueryWrapper(userBankCards).lambda().orderByAsc(UserBankCards::getSort));
		return R.data(UserBankCardsWrapper.build().listVO(list.getRecords()));
	}



	@PostMapping("/userBankCards-update")
	@ApiOperationSupport(order = 15)
	@ApiOperation(value = "修改银行卡", notes = "传入主键ID")
	public R userBankCardsUpdate(@Valid @RequestBody UserBankCardsUpdateRequest request) {
		UserBankCards userBankCards = Objects.requireNonNull(BeanUtil.copy(request, UserBankCards.class));
		userBankCards.setUpdateTime(DateUtil.now());
		return R.status(userBankCardsService.updateById(userBankCards));
	}



	@GetMapping("/versionUpgrade")
	@ApiOperationSupport(order = 16)
	@ApiOperation(value = "获取最新版本", notes = "获取最新版本")
	public R<VersionUpgrade> versionUpgrade(@RequestParam(value = "userVersionName", required = false) String userVersionName) {
		if (StrUtil.isNotBlank(userVersionName)) {
			// 记录用户版本号
			Long userId = AuthUtil.getUserId();
			User user = userService.getById(userId);
			if (user != null && userVersionName.equals(user.getUserAppVersion())) {
				user.setUserAppVersion(userVersionName);
				userService.updateById(user);
			}
		}
		VersionUpgrade versionUpgrade = versionUpgradeService.getOne(Wrappers.<VersionUpgrade>lambdaQuery()
			.eq(VersionUpgrade::getStatus ,2).orderByDesc(VersionUpgrade::getVersionCode).orderByDesc(VersionUpgrade::getSort),false);
		return R.data(versionUpgrade);
	}

	@GetMapping("/detail")
	@ApiOperationSupport(order = 17)
	@ApiOperation(value = "查询用户实名认证", notes = "传入userCardInfo")
	public R<UserCardInfo> detail(UserCardInfo userCardInfo) {
		UserCardInfo detail = userCardInfoService.getOne(Condition.getQueryWrapper(userCardInfo));
		return R.data(detail);
	}

	@ApiOperation(value = "获取信誉分记录")
	@ApiOperationSupport(order = 18)
	@GetMapping("/getCreditScoreRecords")
	public R<List<UserIntegral>> getCreditScoreRecords(Query query) {
		LambdaQueryWrapper<UserIntegral> wrapper = Wrappers.lambdaQuery(UserIntegral.class).eq(UserIntegral::getUserId, AuthUtil.getUserId()).orderByDesc(UserIntegral::getCreateTime);
		IPage<UserIntegral> pages = userScoresService.page(Condition.getPage(query), wrapper);
		return R.data(pages.getRecords());
	}

	@ApiOperation(value = "注销")
	@ApiOperationSupport(order = 19)
	@PostMapping("/logOut")
	public R logOut(){
		User user = userService.getById(AuthUtil.getUserId());
		if(ObjectUtil.isNotNull(user.getLogOut()) && user.getLogOut() == 1){
			return R.fail("用户已注销，无法重复注销");
		}
		user.setLogOut(1);
		return R.status(userService.updateUser(user));
	}

	@ApiOperation(value = "查询用户签到信息")
	@ApiOperationSupport(order = 20)
	@GetMapping("/sign-in/get")
	public R<SignInVO> getUserSignInfo(){
		return data(signInService.getUserSignInfo(AuthUtil.getUserId()));
	}

	@ApiOperation(value = "签到")
	@ApiOperationSupport(order = 21)
	@PostMapping("/sign-in/submit")
	public R signIn(){
		signInService.signIn(AuthUtil.getUserId());
		return success("ok");
	}

	@ApiOperation(value = "商家入驻申请")
	@ApiOperationSupport(order = 22)
	@PostMapping("/merchant-settle/apply")
	public R merchantSettleApply(@ApiParam(value = "厂家名称") String factoryName, @ApiParam(value = "姓名", required = true) String name,
								 @ApiParam(value = "联系电话", required = true) String phone){
		if (!Validator.isMobile(phone)) {
			return fail("非法的手机号");
		}
		List<MerchantSettle> list = merchantSettleService.lambdaQuery().eq(MerchantSettle::getContactNumber, phone).list();
		if (CollUtil.isNotEmpty(list)) {
			return fail("该手机号已提交申请，请勿重复提交");
		}
		MerchantSettle merchantSettle = new MerchantSettle();
		merchantSettle.setContactNumber(phone);
		merchantSettle.setContactPerson(name);
		merchantSettle.setFactoryName(factoryName);
		merchantSettleService.save(merchantSettle);
		return success("ok");
	}

	@ApiOperation(value = "上传商标")
	@ApiOperationSupport(order = 23)
	@PostMapping("/trademark/upload")
	public R uploadTrademark(@Valid @RequestBody UploadTrademarkRequest request) {
		Trademark trademark = BeanUtil.copy(request, Trademark.class);
		Assert.notNull(trademark, "参数异常");
		trademark.setType(TrademarkTypeEnum.USER.getValue());
		trademark.setUserId(AuthUtil.getUserId());
		trademarkService.save(trademark);
		return success("ok");
	}

	@ApiOperation(value = "查询授权记录")
	@ApiOperationSupport(order = 24)
	@GetMapping("/trademark/auth-record")
	public R<List<TrademarkAuthVO>> authRecord(@ApiParam("1-使用中 2-已失效") @RequestParam Integer type, Query query) {
		Assert.notNull(type, "type不能为空");
		if (!(type == 1 || type == 2)) {
			return fail("type参数错误");
		}
		IPage<TrademarkAuthVO> page = trademarkAuthService.authRecord(Condition.getPage(query), AuthUtil.getUserId(), type);
		return data(page.getRecords());
	}

	@ApiOperation(value = "查询我的商标")
	@ApiOperationSupport(order = 25)
	@GetMapping("/trademark/my")
	public R<List<Trademark>> myTrademark(@ApiParam("1-使用中 2-已失效")  @RequestParam Integer type, Query query) {
		Assert.notNull(type, "type不能为空");
		LambdaQueryWrapper<Trademark> wrapper = Wrappers.lambdaQuery(Trademark.class).eq(Trademark::getUserId, AuthUtil.getUserId());
		LocalDateTime now = LocalDateTime.now();
		if (type == 1) {
			wrapper.ge(Trademark::getUsePeriod, now);
		} else if (type == 2) {
			wrapper.lt(Trademark::getUsePeriod, now);
		} else {
			throw new ServiceException("参数异常");
		}
		wrapper.eq(Trademark::getUserId, AuthUtil.getUserId()).eq(Trademark::getType, TrademarkTypeEnum.USER.getValue());
		IPage<Trademark> pages = trademarkService.page(Condition.getPage(query), wrapper);
		return data(pages.getRecords());
	}

	@ApiOperation(value = "删除我的商标")
	@ApiOperationSupport(order = 26)
	@PostMapping("/trademark/remove")
	public R removeTrademark(@ApiParam("商标id") @RequestParam Long id) {
		Trademark trademark = trademarkService.getById(id);
		Assert.notNull(trademark, "数据不存在");
		return data(trademarkService.removeById(id));
	}

	@Transactional
	@ApiOperation(value = "删除我的商标")
	@ApiOperationSupport(order = 27)
	@PostMapping("/bind-wechat")
	public R<UserAppVO> bindWechatInfo(@ApiParam("openId") @RequestParam String openId,
							@ApiParam("unionId") @RequestParam String unionId,
							@ApiParam("nickname") @RequestParam String nickname,
							@ApiParam("headimgurl") @RequestParam String headimgurl) {
		Long userId = AuthUtil.getUserId();
		User user = userService.getById(userId);
		if (user == null) {
			return R.fail("用户数据不存在");
		}
		user.setAvatar(headimgurl);
		user.setName(nickname);
		userService.updateById(user);

		UserApp userApp = userAppService.getByUserId(userId);
		userApp.setIsBindWx(true);
		userAppService.updateById(userApp);

		UserWeChat one = userWeChatService.lambdaQuery().eq(UserWeChat::getUserId, userId).one();
		if (one == null) {
			one = new UserWeChat();
			one.setUnionId(unionId);
			one.setOpenId(openId);
			userWeChatService.save(one);
		} else {
			one.setUnionId(unionId);
			one.setOpenId(openId);
			userWeChatService.updateById(one);
		}

		return data(apiService.getUserAppVo(getUser().getUserId()));
	}
}
