package com.willalp.web.controller.app;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.willalp.canteen.domain.HsCanteenDiningPlace;
import com.willalp.canteen.domain.HsCanteenOrder;
import com.willalp.canteen.domain.HsCanteenOrderDetail;
import com.willalp.canteen.domain.req.CustomReq;
import com.willalp.canteen.domain.req.DeviceOrderSubmissionReq;
import com.willalp.canteen.domain.resp.CuisineListResp;
import com.willalp.canteen.service.IHsCanteenDiningPlaceService;
import com.willalp.canteen.service.IHsCanteenMenuRegisterService;
import com.willalp.canteen.service.IHsCanteenOrderDetailService;
import com.willalp.canteen.service.IHsCanteenOrderService;
import com.willalp.common.core.controller.BaseController;
import com.willalp.common.core.domain.AjaxResult;
import com.willalp.common.core.domain.entity.SysUser;
import com.willalp.common.core.domain.model.LoginUser;
import com.willalp.common.core.redis.RedisCache;
import com.willalp.common.enums.NumberRuleEnum;
import com.willalp.common.exception.base.BaseException;
import com.willalp.common.utils.StringUtils;
import com.willalp.common.utils.bean.BeanUtils;
import com.willalp.device.domain.Device;
import com.willalp.device.service.IDeviceService;
import com.willalp.number.domain.req.NumberRuleReq;
import com.willalp.number.service.IHsSysNumberRuleService;
import com.willalp.system.domain.SysCardInfo;
import com.willalp.system.domain.SysUserOrganization;
import com.willalp.system.service.ISysCardInfoService;
import com.willalp.system.service.ISysUserOrganizationService;
import io.swagger.annotations.Api;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Api("APP消费机接口")
@RestController
@RequestMapping("/api/cm")
public class AppConsumerMachineController extends BaseController {

    @Resource
    private IHsCanteenMenuRegisterService canteenMenuRegisterService;

    @Resource
    private RedisCache redisCache;

    @Resource
    private CustomController customController;

    @Resource
    private IDeviceService deviceService;

    @Resource
    private IHsSysNumberRuleService numberRuleService;

    @Resource
    private IHsCanteenOrderService canteenOrderService;

    @Resource
    private IHsCanteenOrderDetailService canteenOrderDetailService;

    @Resource
    private ISysUserOrganizationService uoService;

    @Resource
    private IHsCanteenDiningPlaceService canteenDiningPlaceService;

    @Resource
    private ISysCardInfoService cardInfoService;

    /**
     * 获取点餐消费菜单
     *
     * @param dn 设备编号
     */
    @GetMapping("/orderMenu")
    public AjaxResult appNoticeList(@RequestParam String dn, Integer pageNum, Integer pageSize) {
        return AjaxResult.success(canteenMenuRegisterService.appGetDeviceOrderMenu(dn, pageNum, pageSize));
    }

    public JSONObject scannerUpload(String dn, int num) throws BaseException {
        while (true) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (num >= 20) {
                throw new BaseException("支付超时");
            }
            if (null == redisCache.getCacheObject(dn)) {
                return null;
            } else {
                try {
                    if (StringUtils.isBlank(dn)) {
                        throw new BaseException("设备标识为空");
                    }
                    QueryWrapper<Device> deviceQw = new QueryWrapper<Device>()
                            .eq("device_no", dn);
                    Device deviceDb = deviceService.getBaseMapper().selectOne(deviceQw);
                    if (null == deviceDb) {
                        throw new BaseException("设备不存在");
                    }
                    JSONObject jsonObject = new JSONObject(redisCache.getCacheObject(dn));
                    if (ObjectUtil.isNotEmpty(jsonObject)) {
                        redisCache.deleteObject(dn);
                        return jsonObject;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new BaseException("无效扫码请刷新或者重试");
                }
            }
        }
    }

    private final String IC_CARD = "IC_CARD";
    private final String HS_CODE = "HS_CODE";


    /**
     * 直接消费
     *
     * @param dn 设备编号
     */
    @Transactional(rollbackFor = Exception.class)
    @RequestMapping("/dPay")
    public AjaxResult directPay(@RequestBody DeviceOrderSubmissionReq dn) {
        String deviceNumber = dn.getDeviceNumber();
        JSONObject jsonObject;
        try {
            if (null == (jsonObject = scannerUpload(dn.getDeviceNumber(), dn.getNum()))) {
                return AjaxResult.success();
            }
        } catch (BaseException e) {
            return AjaxResult.error(e.getMessage());
        }
        String type = jsonObject.getString("type");
        String userCode = null;
        String nickName = null;
        String orgCode = null;
        LoginUser user = null;
        if (StringUtils.isNotBlank(type)) {
            if (StringUtils.equals(type, IC_CARD)) {
                SysCardInfo sysCardInfo = cardInfoService.getBaseMapper().selectOne(new QueryWrapper<SysCardInfo>()
                        .eq("card_code", jsonObject.getString("data")));
                if (null == sysCardInfo) {
                    throw new BaseException("无效IC卡");
                }
                Integer cardState = sysCardInfo.getCardState();
                if (0 == cardState) {
                    String userId = sysCardInfo.getUserId();
                    if (StringUtils.isBlank(userId)) {
                        user = new LoginUser();
                        user.setUser(new SysUser());
                        user.getUser().setUserName(sysCardInfo.getUserId());
                        user.getUser().setNickName(sysCardInfo.getCardUsername());
                    } else {
                        return AjaxResult.error("支付异常，请重新刷卡");
                    }
                } else {
                    return AjaxResult.error("支付异常，请重新刷卡");
                }
            } else if (StringUtils.equals(type, HS_CODE)) {
                JSONObject data = jsonObject.getJSONObject("data");
                if (null == data) {
                    throw new BaseException("无效二维码，请使用HS码");
                }
                userCode = data.getString("u");
                nickName = data.getString("un");
                orgCode = data.getString("o");
                if (null == userCode) {
                    throw new BaseException("无效二维码，请使用HS码");
                }
                if (null == nickName) {
                    throw new BaseException("无效二维码，请使用HS码");
                }
                if (null == orgCode) {
                    throw new BaseException("无效二维码，请使用HS码");
                }
            } else {
                return AjaxResult.error("支付方式异常请重新支付");
            }
        } else {
            return AjaxResult.error("支付方式异常请重新支付");
        }
        BigDecimal orderTotal = dn.getOrderTotal();
        String placeNumber = dn.getPlaceNumber();
        HsCanteenOrder canteenOrder = new HsCanteenOrder();
        canteenOrder.setDeviceNumber(deviceNumber);
        canteenOrder.setNickName(nickName);
        canteenOrder.setPaytime(new Date());
        canteenOrder.setConsumeSign(0);
        canteenOrder.setMenuNumber("CM00000242");
        canteenOrder.setZfbz(2);
        canteenOrder.setOrderTotal(orderTotal);
        canteenOrder.setJgid(orgCode);
        canteenOrder.setPlaceNumber(placeNumber);
        canteenOrder.setUserNumber(userCode);
        NumberRuleReq numberRuleReq = new NumberRuleReq();
        numberRuleReq.setRuleId(NumberRuleEnum.ORDER.getValue());
        numberRuleReq.setInput(String.valueOf(DateUtil.year(canteenOrder.getPaytime())).substring(2, 4));
        String number = numberRuleService.getNumber(numberRuleReq);
        canteenOrder.setOrderNumber(number);
        SysUserOrganization sysUserOrganization = uoService.getBaseMapper().selectOne(new QueryWrapper<SysUserOrganization>().
                eq("login_name", userCode).eq("organization_code", orgCode));
        if (null != sysUserOrganization) {
            BigDecimal integral = sysUserOrganization.getIntegral();
            if (integral.compareTo(orderTotal) > 0) {
                BigDecimal subtract = integral.subtract(orderTotal);
                sysUserOrganization.setIntegral(subtract);
                if (uoService.updateById(sysUserOrganization)) {
                    canteenOrderService.save(canteenOrder);
                    return AjaxResult.success("PAYMENT_SUCCESSFUL");
                }
            } else {
                return AjaxResult.error("余额不足，请充值");
            }
        }
        return AjaxResult.success();
    }

    /**
     * 获取点餐消费菜单
     *
     * @param dn 设备编号
     */
    @Transactional(rollbackFor = Exception.class)
    @RequestMapping("/ocPay")
    public AjaxResult ocPay(@RequestBody DeviceOrderSubmissionReq dn) {
        String deviceNumber = dn.getDeviceNumber();
        JSONObject jsonObject;
        try {
            if (null == (jsonObject = scannerUpload(deviceNumber, dn.getNum()))) {
                return AjaxResult.success();
            }
        } catch (BaseException e) {
            return AjaxResult.error(e.getMessage());
        }
        String type = jsonObject.getString("type");
        String userCode = null;
        String nickName = null;
        String orgCode = null;
        LoginUser user = null;
        if (StringUtils.isNotBlank(type)) {
            if (StringUtils.equals(type, IC_CARD)) {
                SysCardInfo sysCardInfo = cardInfoService.getBaseMapper().selectOne(new QueryWrapper<SysCardInfo>()
                        .eq("card_code", jsonObject.getString("data")));
                Integer cardState = sysCardInfo.getCardState();
                if (0 == cardState) {
                    String userId = sysCardInfo.getUserId();
                    if (StringUtils.isBlank(userId)) {
                        user = new LoginUser();
                        user.setUser(new SysUser());
                        user.getUser().setUserName(sysCardInfo.getUserId());
                        user.getUser().setNickName(sysCardInfo.getCardUsername());
                    } else {
                        return AjaxResult.error("卡片信息异常请联系发卡机构");
                    }
                } else {
                    return AjaxResult.error("卡片状态异常");
                }
            } else if (StringUtils.equals(type, HS_CODE)) {
                JSONObject data = jsonObject.getJSONObject("data");
                if (null == data) {
                    throw new BaseException("无效二维码，请使用HS码");
                }
                userCode = data.getString("u");
                nickName = data.getString("un");
                orgCode = data.getString("o");
                if (null == userCode) {
                    throw new BaseException("无效二维码，请使用HS码");
                }
                if (null == nickName) {
                    throw new BaseException("无效二维码，请使用HS码");
                }
                if (null == orgCode) {
                    throw new BaseException("无效二维码，请使用HS码");
                }
            } else {
                return AjaxResult.error("支付方式异常请重试");
            }
        }
        BigDecimal orderTotal = dn.getOrderTotal();
        List<CuisineListResp> details = dn.getDetails();
        String placeNumber = dn.getPlaceNumber();
        HsCanteenOrder canteenOrder = new HsCanteenOrder();
        canteenOrder.setDeviceNumber(deviceNumber);
        canteenOrder.setNickName(nickName);
        canteenOrder.setMenuNumber(details.get(0).getMenuNumber());
        canteenOrder.setPaytime(new Date());
        canteenOrder.setConsumeSign(0);
        canteenOrder.setZfbz(2);
        canteenOrder.setOrderTotal(orderTotal);
        canteenOrder.setJgid(orgCode);
        canteenOrder.setPlaceNumber(placeNumber);
        canteenOrder.setUserNumber(userCode);
        NumberRuleReq numberRuleReq = new NumberRuleReq();
        numberRuleReq.setRuleId(NumberRuleEnum.ORDER.getValue());
        numberRuleReq.setInput(String.valueOf(DateUtil.year(canteenOrder.getPaytime())).substring(2, 4));
        String number = numberRuleService.getNumber(numberRuleReq);
        canteenOrder.setOrderNumber(number);
        List<HsCanteenOrderDetail> list = new ArrayList<>();
        details.forEach(item -> {
            HsCanteenOrderDetail canteenOrderDetail = new HsCanteenOrderDetail();
            BeanUtils.copyProperties(item, canteenOrderDetail);
            canteenOrderDetail.setOrderNumber(number);
            list.add(canteenOrderDetail);
        });
        if (canteenOrderService.save(canteenOrder)) {
            if (canteenOrderDetailService.saveBatch(list)) {
                HsCanteenDiningPlace jcd = canteenDiningPlaceService.getBaseMapper().selectOne(new QueryWrapper<HsCanteenDiningPlace>()
                        .eq("place_number", placeNumber));
                String jgid = jcd.getJgid();
                SysUserOrganization sysUserOrganization = uoService.getBaseMapper().selectOne(new QueryWrapper<SysUserOrganization>().
                        eq("login_name", userCode).eq("organization_code", jgid));
                if (null != sysUserOrganization) {
                    BigDecimal integral = sysUserOrganization.getIntegral();
                    if (integral.compareTo(orderTotal) > 0) {
                        BigDecimal subtract = integral.subtract(orderTotal);
                        sysUserOrganization.setIntegral(subtract);
                        if (uoService.updateById(sysUserOrganization)) {
                            return AjaxResult.success("PAYMENT_SUCCESSFUL");
                        }
                    } else {
                        return AjaxResult.error("余额不足，请充值");
                    }
                }
            }
        }
        return AjaxResult.success();
    }

    /**
     * 设备扫描结果
     *
     * @param dnq 设备
     */
    @RequestMapping("/scPay")
    public AjaxResult scPay(@RequestBody DeviceOrderSubmissionReq dnq) {
        JSONObject jsonObject;
        String dn = dnq.getDeviceNumber();
        int num = dnq.getNum();
        try {
            if (null == (jsonObject = scannerUpload(dn, num))) {
                return AjaxResult.success();
            }
        } catch (BaseException e) {
            return AjaxResult.error(e.getMessage());
        }
        String type = jsonObject.getString("type");
        CustomReq customReq = new CustomReq();
        if (StringUtils.isNotBlank(type)) {
            if (StringUtils.equals(type, IC_CARD)) {
                SysCardInfo sysCardInfo = cardInfoService.getBaseMapper().selectOne(new QueryWrapper<SysCardInfo>()
                        .eq("card_code", jsonObject.getString("data")));
                Integer cardState = sysCardInfo.getCardState();
                if (0 == cardState) {
                    String userId = sysCardInfo.getUserId();
                    if (StringUtils.isBlank(userId)) {
                        customReq.setUserName(sysCardInfo.getUserId());
                        customReq.setJgid(dnq.getPlaceNumber());
                        customReq.setDeviceNo(dnq.getDeviceNumber());
                        return AjaxResult.success(customController.getOrder(customReq));
                    } else {
                        return AjaxResult.error("支付异常，请重新刷卡");
                    }
                } else {
                    return AjaxResult.error("支付异常，请重新刷卡");
                }
            } else if (StringUtils.equals(type, HS_CODE)) {
                JSONObject data = jsonObject.getJSONObject("data");
                if (ObjectUtil.isNotEmpty(data)) {
                    customReq.setToken(data.getString("u"));
                    customReq.setDeviceNo(dn);
                    customReq.setJgid(data.getString("o"));
                    customReq.setPlaceNumber(dnq.getPlaceNumber());
                    return AjaxResult.success(customController.getOrder(customReq));
                } else {
                    return AjaxResult.success();
                }
            } else {
                return AjaxResult.error("支付方式异常请重新支付");
            }
        }
        return AjaxResult.error("支付方式异常请重新支付");
    }
}
