package com.crm.globex.service.impl;

import com.alibaba.fastjson.JSON;
import com.crm.globex.dao.mapper.MTMapper;
import com.crm.globex.dao.repository.FinanceDepositRepository;
import com.crm.globex.service.FinanceDepositService;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.constant.StatusConstants;
import com.crm.rely.backend.core.entity.manager.FinanceBalanceToManagerEntity;
import com.crm.rely.backend.core.entity.manager.callback.FinanceCallbackEntity;
import com.crm.rely.backend.core.exception.ServiceException;
import com.crm.rely.backend.model.pojo.table.FinanceDepositTable;
import com.crm.rely.backend.service.MqSendService;
import com.crm.rely.backend.util.SynchronizedKey;
import com.google.common.base.Strings;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @Author: houn
 * @Date: 2022-04-12 0:07
 * @Description:
 */
@Log4j
@Service
public class FinanceDepositServiceImpl implements FinanceDepositService {

    @Autowired
    private FinanceDepositRepository repository;

    @Autowired
    private MTMapper mtMapper;

    @Autowired
    private MqSendService mqSendService;

    @Override
    public void scheduleAutomaticTrade() throws ServiceException {

        List<FinanceDepositTable> tables =
                repository.findAllByStatusAndDepositStatus(StatusConstants.PASSED_STATUS, StatusConstants.MANAGER_PENDING_STATUS);
        for (FinanceDepositTable table : tables) {

            try {
                automaticTrade(table);
            } catch (Exception e) {
                log.error(e.getMessage());
                e.printStackTrace();
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void automaticTrade(FinanceDepositTable table) throws ServiceException {
        SynchronizedKey.exec(table.getId().toString(), new Thread(() -> {
            Long order = mtMapper.getOrder("MT4", table.getLogin(), table.getSerial());
            if (order != null) {
                table.setDepositTicket(order.toString());
                table.setDepositStatus(StatusConstants.MANAGER_COMPLETED_STATUS);
                repository.save(table);
                return;
            }
            table.setDepositStatus(StatusConstants.MANAGER_PROCESSING_STATUS);
            repository.save(table);
            sendMq(table);
        }));
    }

    private void sendMq(FinanceDepositTable table) {

        FinanceBalanceToManagerEntity financeBalanceToManagerEntity = new FinanceBalanceToManagerEntity();
        financeBalanceToManagerEntity.setAmount(table.getAmount());
        financeBalanceToManagerEntity.setComment(table.getSerial());
        financeBalanceToManagerEntity.setSerial(table.getSerial());
        financeBalanceToManagerEntity.setLogin(table.getLogin());
        financeBalanceToManagerEntity.setType(1);
        financeBalanceToManagerEntity.setRouteType(Constants.TRADE_TRANS_INFO);

        mqSendService.send(Constants.MT4_TRADE_TRANS_INFO, JSON.toJSONString(financeBalanceToManagerEntity));
    }

    @Transactional(rollbackFor = Exception.class)
    public void callbackAutomaticTrade(FinanceCallbackEntity callbackEntity) throws ServiceException {

        if (callbackEntity != null && callbackEntity.getCode() == Constants.SUCCESS_CODE && callbackEntity.getData() != null) {
            callbackEntity.getData().setStatus(StatusConstants.MANAGER_COMPLETED_STATUS);
        } else {
            callbackEntity.getData().setStatus(StatusConstants.MANAGER_PENDING_STATUS);

            System.out.println("manager异常,callback data:" + callbackEntity);
        }
        callbackAutomaticAmount(callbackEntity.getCode(), callbackEntity.getData());
    }

    /**
     * 开始回调入金订单 manager成功失败
     *
     * @param entity
     * @throws ServiceException
     */
    @Transactional(rollbackFor = Exception.class)
    public void callbackAutomaticAmount(Integer code, FinanceBalanceToManagerEntity entity) throws ServiceException {
        FinanceDepositTable table = repository.findFirstBySerial(entity.getSerial());

        if (table != null) {
            SynchronizedKey.exec(table.getId().toString(), new Thread(() -> {
                if (table.getDepositStatus() != null && StatusConstants.MANAGER_COMPLETED_STATUS.equals(table.getDepositStatus())) {
                    return;
                }
                if (code != null && code.equals(200)) {
                    if (entity.getOrder() != null && entity.getOrder().compareTo(0) > 0) {
                        table.setDepositTicket(entity.getOrder().toString());
                        table.setDepositStatus(entity.getStatus());
                    }
                }
                //判断返回的状态码 如果是134 则因为账号没有足够的金钱
                else if (code != null && code.equals(134)) {
                    table.setDepositStatus(StatusConstants.MANAGER_FAIL_STATUS);
                } else {
                    setStatus(table, code);
                }
                //判断是否是返回了订单号 null和0都是没有返回
                if (Strings.isNullOrEmpty(table.getDepositTicket())) {
                    //可以是因为调用api的返回的问题 根据条件-账号和备注去数据库查推送的订单数据 如果存在 则放回成功
                    //如果不存在 则正常进行判断
                    Long order = mtMapper.getOrder("MT4", table.getLogin(), table.getSerial());
                    if (order != null) {
                        table.setDepositTicket(order.toString());
                        table.setDepositStatus(StatusConstants.MANAGER_COMPLETED_STATUS);
                    }
                }

                table.setModifyTime(new Date());
                repository.save(table);
            }));
        }
    }

    private FinanceDepositTable setStatus(FinanceDepositTable table, Integer code) {
        if (code == null) {
            code = 0;
        }
        table = setMT4Status(table, code);

        return table;
    }


    private FinanceDepositTable setMT4Status(FinanceDepositTable table, Integer code) {
        if (code == null) {
            code = 0;
        }

        switch (code.intValue()) {
            case -1000:
                table.setStatus(StatusConstants.MANAGER_FAIL_STATUS);
                table.setNote("104");
                break;

            default:
                table.setDepositStatus(StatusConstants.MANAGER_PENDING_STATUS);
                break;
        }
        return table;
    }
}
