package com.yiqi.api.controller;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yiqi.app.domain.AppUserAddress;
import com.yiqi.app.domain.AppUserPointLog;
import com.yiqi.app.service.IAppUserPointLogService;
import com.yiqi.common.exception.ServiceException;
import com.yiqi.app.domain.AppCouponItem;
import com.yiqi.app.domain.AppUser;
import com.yiqi.app.domain.dto.AppUserLoginDTO;
import com.yiqi.app.domain.dto.AppUserRegistDTO;
import com.yiqi.app.domain.dto.AppUserUpdateDTO;
import com.yiqi.app.domain.dto.AppUserUpdatePassDTO;
import com.yiqi.app.domain.dto.weapp.WeAppUserSetPayPasswordDTO;
import com.yiqi.app.domain.dto.weapp.WeAppWxLoginDTO;
import com.yiqi.app.domain.vo.AppUserLoginVO;
import com.yiqi.app.domain.vo.AppUserVO;
import com.yiqi.app.domain.vo.weapp.WeAppUserCashVO;
import com.yiqi.app.service.IAppCouponItemService;
import com.yiqi.app.service.IAppUserService;
import com.yiqi.app.service.IWeAppTokenService;
import com.yiqi.common.config.CompositeWxMaService;
import com.yiqi.common.constant.UrlConstants;
import com.yiqi.common.core.controller.BaseController;
import com.yiqi.common.core.domain.AuthHolder;
import com.yiqi.common.core.domain.AuthInfoDO;
import com.yiqi.common.core.domain.R;
import com.yiqi.common.enums.*;
import com.yiqi.common.utils.DateUtils;
import com.yiqi.common.utils.StringUtils;
import com.yiqi.recharge.domain.RechargePasswordCard;
import com.yiqi.recharge.service.IRechargePasswordCardService;
import com.yiqi.system.domain.SysSessionRecord;
import com.yiqi.system.domain.SysSms;
import com.yiqi.system.service.ISysSessionRecordService;
import com.yiqi.system.service.ISysSmsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * @author xiaohei
 * @date 2023/10/3
 */
@Api(tags = "用户")
@RequestMapping(UrlConstants.wxappApi + "/user")
@RestController
public class WeAppUserController extends BaseController {

    @Autowired
    private IAppUserService appUserService;
    @Autowired
    private IAppUserPointLogService appUserPointLogService;
    @Autowired
    private IWeAppTokenService weAppTokenService;
    @Autowired
    private ISysSmsService sysSmsService;
    @Autowired
    private IRechargePasswordCardService rechargePasswordCardService;
    @Autowired
    private IAppCouponItemService appCouponItemService;
    @Autowired
    private CompositeWxMaService compositeWxMaService;
    @Autowired
    private ISysSessionRecordService sysSessionRecordService;


    @ApiOperation("查询用户中心明细")
    @GetMapping(value = "getCashInfo")
    public R<WeAppUserCashVO> getCashInfo(@RequestParam(required = false) @ApiParam("订单类型（0=洗衣订单，1=商品订单，2=生活服务订单，3=汽车美容订单）") String orderType) throws Exception {
        RechargePasswordCard rechargePasswordCard = rechargePasswordCardService.selectTotalBalanceGroupByAppUser(AuthHolder.userId(), orderType);
        AppUser appUser = appUserService.getById(AuthHolder.userId());
        WeAppUserCashVO weAppUserCashVO = new WeAppUserCashVO();
        if (rechargePasswordCard != null) {
            weAppUserCashVO.setRechargeBalance(rechargePasswordCard.getRechargeBalance());
            weAppUserCashVO.setGiveBalance(rechargePasswordCard.getGiveBalance());
            weAppUserCashVO.setWelfareBalance(rechargePasswordCard.getWelfareBalance());
        } else {
            weAppUserCashVO.setRechargeBalance(BigDecimal.ZERO);
            weAppUserCashVO.setGiveBalance(BigDecimal.ZERO);
            weAppUserCashVO.setPointBalance(0);
            weAppUserCashVO.setWelfareBalance(BigDecimal.ZERO);
        }
        weAppUserCashVO.setPointBalance(appUser.getPoint());
        weAppUserCashVO.setCouponNum(appCouponItemService.count(new QueryWrapper<AppCouponItem>().lambda()
                .eq(AppCouponItem::getAppUserId, AuthHolder.userId())
                .ge(AppCouponItem::getEndDate, DateUtils.getNowDate())
                .eq(AppCouponItem::getIsUsed, SysBoolType.NO.getCode())));
        return R.ok(weAppUserCashVO);
    }

    @ApiOperation("登录")
    @PostMapping(value = "login")
    public R<AppUserLoginVO> login(@RequestBody @Valid AppUserLoginDTO appUserLoginDTO) throws Exception {
        AppUser appUser = appUserService.getOne(new QueryWrapper<AppUser>().lambda()
                .eq(AppUser::getPhoneNumber, appUserLoginDTO.getPhone()), false);
        if (appUser == null) {
            throw new ServiceException("该手机号的用户不存在");
        }
        if (!appUser.getPassword().equals(appUserLoginDTO.getPassword())) {
            throw new ServiceException("密码不正确");
        }

        String token = weAppTokenService.createToken(new AuthInfoDO(appUser));

        //持久化存储token
        SysSessionRecord sysSessionRecord = sysSessionRecordService.getOne(new QueryWrapper<SysSessionRecord>()
                .lambda().eq(SysSessionRecord::getAppUserId, appUser.getId())
                .eq(SysSessionRecord::getPlatformType, PlatformType.USER.getCode())
                .eq(SysSessionRecord::getSessionPlatformType, appUserLoginDTO.getPlatform()));
        if (sysSessionRecord == null) {
            sysSessionRecord = new SysSessionRecord();
            sysSessionRecord.setAppUserId(appUser.getId());
            sysSessionRecord.setSessionPlatformType(appUserLoginDTO.getPlatform());
            sysSessionRecord.setPlatformType(PlatformType.USER.getCode());
            sysSessionRecord.setUnionId(null);
            sysSessionRecord.setToken(token);
        } else {//清楚之前的缓存记录
            weAppTokenService.delLoginUser(sysSessionRecord.getToken());
            sysSessionRecord.setToken(token);
        }
        sysSessionRecordService.saveOrUpdate(sysSessionRecord);

        AppUserLoginVO appUserLoginVO = new AppUserLoginVO();
        BeanUtils.copyProperties(appUser, appUserLoginVO);
        appUserLoginVO.setToken(token);
        return R.ok(appUserLoginVO);
    }

    @ApiOperation("修改密码")
    @PostMapping(value = "updatePassword")
    public R updatePassword(@RequestBody @Valid AppUserUpdatePassDTO appUserUpdatePassDTO) throws Exception {
        AppUser appUser = appUserService.getOne(new QueryWrapper<AppUser>().lambda()
                .eq(AppUser::getPhoneNumber, appUserUpdatePassDTO.getPhone()), false);
        if (appUser == null) {
            throw new ServiceException("该手机号的用户不存在");
        }
        SysSms sysSms = sysSmsService.getOne(new QueryWrapper<SysSms>().lambda()
                .eq(SysSms::getPhone, appUserUpdatePassDTO.getPhone())
                .eq(SysSms::getSmsType, SmsType.UPDATE_PASS.getCode()).ge(SysSms::getCreateTime, new Date(System.currentTimeMillis() - 300000)));
        if (sysSms == null) {
            throw new ServiceException("验证码不正确");
        }
        appUserService.update(new UpdateWrapper<AppUser>().lambda()
                .eq(AppUser::getPhoneNumber, appUserUpdatePassDTO.getPhone())
                .set(AppUser::getPassword, appUserUpdatePassDTO.getPassword()));
        return R.ok();
    }

    @ApiOperation("注册")
    @PostMapping(value = "regist")
    public R regist(@RequestBody @Valid AppUserRegistDTO appUserRegistDTO) throws Exception {
        if (appUserService.count(new QueryWrapper<AppUser>().lambda().eq(AppUser::getPhoneNumber, appUserRegistDTO.getPhone())) > 0) {
            throw new ServiceException("该手机号已注册");
        }
        SysSms sysSms = sysSmsService.getOne(new QueryWrapper<SysSms>().lambda()
                .eq(SysSms::getPhone, appUserRegistDTO.getPhone())
                .eq(SysSms::getSmsType, SmsType.REGIST.getCode()).ge(SysSms::getCreateTime, new Date(System.currentTimeMillis() - 300000)));
        if (sysSms == null) {
            throw new ServiceException("验证码不正确");
        }

        AppUser appUser = new AppUser();
        appUser.setPhoneNumber(appUserRegistDTO.getPhone());
        appUser.setRealName(appUserRegistDTO.getRealName());
        appUser.setNickName(appUserRegistDTO.getRealName());
        if (StringUtils.isEmpty(appUserRegistDTO.getRealName())) {
            appUser.setNickName("用户" + RandomUtil.randomNumbers(8));
        }
        appUser.setIsUsePayPassword(SysBoolType.NO.getCode());
        appUser.setLevel(1);
        appUser.setPassword(appUserRegistDTO.getPassword());
        appUser.setStatus(StatusType.OK.getCode());
        appUser.setCreateTime(DateUtils.getNowDate());
        appUserService.save(appUser);
        return R.ok();
    }

    @ApiOperation("获取客户明细")
    @GetMapping(value = "getInfo")
    public R<AppUserLoginVO> getInfo() throws Exception {
        AppUser appUser = appUserService.getOne(new QueryWrapper<AppUser>().lambda().eq(AppUser::getId, AuthHolder.userId()), false);
        if (appUser == null) {
            throw new ServiceException("未查询到用户");
        }
        AppUserLoginVO appUserVO = new AppUserLoginVO();
        BeanUtils.copyProperties(appUser, appUserVO);
        return R.ok(appUserVO);
    }

    @ApiOperation("校验登录信息")
    @GetMapping(value = "checkToken")
    public R<AppUser> checkToken() throws Exception {
        return R.ok(appUserService.getOne(new QueryWrapper<AppUser>().lambda().eq(AppUser::getId, AuthHolder.userId())));
    }

    @ApiOperation("修改用户信息")
    @PostMapping(value = "update")
    public R update(@RequestBody @Valid AppUserUpdateDTO appUserUpdateDTO) throws Exception {
        appUserService.update(new UpdateWrapper<AppUser>().lambda()
                .eq(AppUser::getId, AuthHolder.userId())
                .set(AppUser::getAvatarUrl, appUserUpdateDTO.getAvatarUrl())
                .set(AppUser::getBirthday, appUserUpdateDTO.getBirthday())
                .set(AppUser::getRealName, appUserUpdateDTO.getRealName())
                .set(AppUser::getSex, appUserUpdateDTO.getSex()));
        return R.ok();
    }

    @Transactional
    @ApiOperation("设置支付密码")
    @PostMapping(value = "setPayPassword")
    public R setPayPassword(@RequestBody @Valid WeAppUserSetPayPasswordDTO weAppUserSetPayPasswordDTO) throws Exception {
        AppUser appUser = appUserService.getOne(new QueryWrapper<AppUser>().lambda().eq(AppUser::getId, AuthHolder.userId()), false);
        R smsResult = sysSmsService.checkSms(appUser.getPhoneNumber(), weAppUserSetPayPasswordDTO.getVerifyCode(), SmsType.UPDATE_PAY_PASS.getCode());
        if (R.isError(smsResult)) {
            return smsResult;
        }

        appUserService.update(new UpdateWrapper<AppUser>().lambda()
                .set(AppUser::getPayPassword, weAppUserSetPayPasswordDTO.getPayPassword()).eq(AppUser::getId, AuthHolder.userId()));
        return R.ok(null, "设置成功");
    }

    @ApiOperation("获取我的积分记录")
    @GetMapping(value = "pointLogList")
    public R<List<AppUserPointLog>> pointLogList() {
        return R.ok(appUserPointLogService.list(new QueryWrapper<AppUserPointLog>().lambda()
                .eq(AppUserPointLog::getAppUserId, AuthHolder.userId())
                .orderByDesc(AppUserPointLog::getId)));
    }

    @ApiOperation("设置是否开启支付密码")
    @GetMapping(value = "setIsOpenPayPass")
    public R setIsOpenPayPass(@RequestParam @ApiParam("Y=开启，N=关闭") String isOpen) throws Exception {
        appUserService.update(new UpdateWrapper<AppUser>().lambda().set(AppUser::getIsUsePayPassword, isOpen).eq(AppUser::getId, AuthHolder.userId()));
        return R.ok(null, "设置成功");
    }

    @ApiOperation("微信登录")
    @PostMapping(value = "wxLogin")
    public R<AppUserLoginVO> wxLogin(@RequestBody @Valid WeAppWxLoginDTO weAppWxLoginDTO) throws Exception {
        return appUserService.wxLogin(weAppWxLoginDTO);
    }
}
