package com.zhongshu.card.server.core.service.pay;

import com.github.microservice.components.data.base.page.PageableModel;
import com.github.microservice.pay.client.model.UpdateMetaFieldModel;
import com.github.microservice.pay.client.model.ledger.*;
import com.github.microservice.pay.client.model.ledger.transaction.GeneralLedgerQueryTransactionLogModel;
import com.github.microservice.pay.client.model.ledger.transaction.TransactionLogAggregateNotPageRetModel;
import com.github.microservice.pay.client.model.ledger.transaction.TransactionLogAggregateRetModel;
import com.github.microservice.pay.client.ret.ResultContent;
import com.github.microservice.pay.client.ret.ResultState;
import com.github.microservice.pay.client.service.ledger.TransactionLogService;
import com.github.microservice.pay.client.type.ledger.TransactionStatus;
import com.github.microservice.pay.client.type.ledger.TransactionType;
import com.github.microservice.types.payment.PaymentChannelType;
import com.github.microservice.types.payment.PaymentType;
import com.zhongshu.card.client.type.SettleStatus;
import com.zhongshu.card.client.utils.DateUtils;
import com.zhongshu.card.server.core.domain.pay.PayAccount;
import com.zhongshu.card.server.core.util.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SettleService {

    @Autowired
    PayAccountService payAccountService;

    @Autowired
    TransactionLogService transactionLogService;

    @Autowired
    SettleService settleService;

    @Transactional
    public ResultContent settle(String projectOid, String oid, Long endTime, String remark, PaymentType paymentType) {
        //获取机构-待结算子账
        PayAccount waitSettleAccount = payAccountService.getOrgChildren(projectOid, oid, PaymentChannelType.WaitSettle);
        //查询时间内所有待结算账单
        GeneralLedgerQueryTransactionLogModel queryModel = new GeneralLedgerQueryTransactionLogModel();
//        queryModel.setStartTime(startTime);
        queryModel.setEndTime(endTime);
        queryModel.setGeneralLedgerId(new String[]{waitSettleAccount.getLedgerId()});
        //过滤出对应支付渠道的账单
//        queryModel.setFilter(Map.of("meta.paymentType", paymentType));
        queryModel.setFilter(Map.of("meta.paymentType", paymentType, "$or", Arrays.asList(
                new Document()
                        .append("meta.settleStatus", new Document()
                                .append("$exists", false)
                        ),
                new Document()
                        .append("meta.settleStatus", "WaitSettle")
        )));
        ResultContent<TransactionLogAggregateNotPageRetModel> aggregateResult = transactionLogService.aggregateNotPage(queryModel);


        if (!aggregateResult.getState().equals(ResultState.Success)) {
            log.info("资金结算：查询待结算账单失败");
            throw new RuntimeException(aggregateResult.getMsg());
        }
        if (aggregateResult.getContent().getList().isEmpty()) {
            return ResultContent.buildContent(new HashSet<>());
        }
        List<TransactionLogModel> transactionLogModelList = aggregateResult.getContent().getList();
        Set<String> orderNoSet = new HashSet<>();
        List<String> settleList = transactionLogModelList.stream().map(it -> {
            orderNoSet.add(it.getOrderNumber());
            return it.getId();
        }).toList();

        log.info("结算账单集合：{}", transactionLogModelList);
        log.info("结算订单集合：{}", orderNoSet);


        //收入-支出=可提现金额
        long settleAmount = aggregateResult.getContent().getStatistics().getCreditCount() + aggregateResult.getContent().getStatistics().getDebitCount();

        if (settleAmount <= 0L) {
            log.info("该账户可结算金额小于或等于0, 账户：{}，可提现金额：{}, 时间{}", waitSettleAccount.getLedgerId(), settleAmount, endTime);
            throw new RuntimeException("该账户可结算金额小于或等于0");
        }
        //转账 机构待结算子账户-  机构待提现子账户+
        PayAccount settleAccount = payAccountService.getOrgChildren(projectOid, oid, PaymentChannelType.Settle);

        //构建转账参数
        TransferTransactionsModel transferModel = new TransferTransactionsModel();
        String settleNo = CommonUtil.UUID();
        //构建出账账户
        TransferTransactionsModel.GeneralLedgerTransaction sourceTransaction = new TransferTransactionsModel.GeneralLedgerTransaction();
        sourceTransaction.setGeneralLedgerId(waitSettleAccount.getLedgerId());
        sourceTransaction.setOrderNumber(settleNo);
        sourceTransaction.setTransactionType(TransactionType.Settle);
        sourceTransaction.setTransactionStatus(TransactionStatus.Success);
        sourceTransaction.setAmount(-settleAmount);
        sourceTransaction.setRemark(remark);
        sourceTransaction.setMeta(Map.of("orderSize", orderNoSet.size(), "transactionLogList", settleList, "paymentType", paymentType, "paymentChannelType", paymentType.getChannelType(), "description", "结算"));
        transferModel.setSource(new TransferTransactionsModel.GeneralLedgerTransaction[]{sourceTransaction});
        //构建入账账户
        TransferTransactionsModel.GeneralLedgerTransaction destinationTransaction = new TransferTransactionsModel.GeneralLedgerTransaction();
        destinationTransaction.setGeneralLedgerId(settleAccount.getLedgerId());
        destinationTransaction.setOrderNumber(settleNo);
        destinationTransaction.setTransactionType(TransactionType.Settle);
        destinationTransaction.setTransactionStatus(TransactionStatus.Success);
        destinationTransaction.setAmount(settleAmount);
        destinationTransaction.setRemark(remark);
        destinationTransaction.setMeta(Map.of("orderSize", orderNoSet.size(), "transactionLogList", settleList, "paymentType", paymentType, "paymentChannelType", paymentType.getChannelType(), "description", "结算"));
        transferModel.setDestinations(new TransferTransactionsModel.GeneralLedgerTransaction[]{destinationTransaction});
        ResultContent<List<TransactionLogModel>> transfer = transactionLogService.transfer(transferModel);

        if (!transfer.getState().equals(ResultState.Success)) {
            log.error("结算划账失败， projectOid: {}, paymentType: {}", projectOid, paymentType);
            throw new RuntimeException(transfer.getMsg());
        }

        UpdateMetaFieldModel updateMetaFieldModel = new UpdateMetaFieldModel();
        updateMetaFieldModel.setIds(settleList);
        updateMetaFieldModel.setMetaField(Map.of("settleStatus", SettleStatus.Settle,"settleTime", DateUtils.paresTime(new Date().getTime(), DateUtils.pattern)));
        ResultContent<Void> updateManyMetaField = transactionLogService.updateManyMetaField(updateMetaFieldModel);
        if (!updateManyMetaField.getState().equals(ResultState.Success)) {
            log.error("修改账单meta字段失败， projectOid: {}, paymentType: {}", projectOid, paymentType);
            throw new RuntimeException(updateManyMetaField.getMsg());
        }
        return ResultContent.buildContent(orderNoSet);
    }
}
