package com.it.rattan.monisuo.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.it.rattan.monisuo.entity.AccountFlow;
import com.it.rattan.monisuo.entity.AccountFund;
import com.it.rattan.monisuo.entity.AccountTrade;
import com.it.rattan.monisuo.entity.Coin;
import com.it.rattan.monisuo.mapper.AccountFlowMapper;
import com.it.rattan.monisuo.mapper.AccountFundMapper;
import com.it.rattan.monisuo.mapper.AccountTradeMapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.it.rattan.monisuo.util.OrderNoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 资产服务
 */
@Service
public class AssetService {

    @Autowired
    private AccountFundMapper accountFundMapper;

    @Autowired
    private AccountTradeMapper accountTradeMapper;

    @Autowired
    private AccountFlowMapper accountFlowMapper;

    @Autowired
    private CoinService coinService;

    /**
     * 获取资产总览
     */
    public Map<String, Object> getOverview(Long userId) {
        Map<String, Object> result = new HashMap<>();

        // 资金账户
        AccountFund fund = getOrCreateFundAccount(userId);
        result.put("fundBalance", fund.getBalance());
        result.put("fundFrozen", fund.getFrozen());

        // 交易账户
        BigDecimal tradeValue = BigDecimal.ZERO;
        List<Map<String, Object>> positions = new ArrayList<>();

        LambdaQueryWrapper<AccountTrade> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountTrade::getUserId, userId)
                .gt(AccountTrade::getQuantity, BigDecimal.ZERO);
        List<AccountTrade> trades = accountTradeMapper.selectList(wrapper);

        for (AccountTrade trade : trades) {
            Coin coin = coinService.getCoinByCode(trade.getCoinCode());
            if (coin != null) {
                BigDecimal value = trade.getQuantity().multiply(coin.getPrice())
                        .setScale(8, RoundingMode.DOWN);
                tradeValue = tradeValue.add(value);

                Map<String, Object> position = new HashMap<>();
                position.put("coinCode", trade.getCoinCode());
                position.put("coinName", coin.getName());
                position.put("quantity", trade.getQuantity());
                position.put("price", coin.getPrice());
                position.put("value", value);
                position.put("avgPrice", trade.getAvgPrice());
                positions.add(position);
            }
        }

        result.put("tradeValue", tradeValue);
        result.put("positions", positions);

        // 总资产
        BigDecimal totalAssets = fund.getBalance().add(tradeValue);
        result.put("totalAssets", totalAssets);

        return result;
    }

    /**
     * 获取资金账户
     */
    public AccountFund getOrCreateFundAccount(Long userId) {
        LambdaQueryWrapper<AccountFund> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountFund::getUserId, userId);
        AccountFund fund = accountFundMapper.selectOne(wrapper);

        if (fund == null) {
            fund = new AccountFund();
            fund.setUserId(userId);
            fund.setBalance(BigDecimal.ZERO);
            fund.setFrozen(BigDecimal.ZERO);
            fund.setTotalDeposit(BigDecimal.ZERO);
            fund.setTotalWithdraw(BigDecimal.ZERO);
            fund.setCreateTime(LocalDateTime.now());
            accountFundMapper.insert(fund);
        }

        return fund;
    }

    /**
     * 获取交易账户
     */
    public List<Map<String, Object>> getTradeAccount(Long userId) {
        List<Map<String, Object>> result = new ArrayList<>();

        LambdaQueryWrapper<AccountTrade> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountTrade::getUserId, userId)
                .gt(AccountTrade::getQuantity, BigDecimal.ZERO);
        List<AccountTrade> trades = accountTradeMapper.selectList(wrapper);

        for (AccountTrade trade : trades) {
            Coin coin = coinService.getCoinByCode(trade.getCoinCode());
            if (coin != null) {
                BigDecimal value = trade.getQuantity().multiply(coin.getPrice())
                        .setScale(8, RoundingMode.DOWN);

                Map<String, Object> item = new HashMap<>();
                item.put("coinCode", trade.getCoinCode());
                item.put("coinName", coin.getName());
                item.put("coinIcon", coin.getIcon());
                item.put("quantity", trade.getQuantity());
                item.put("price", coin.getPrice());
                item.put("value", value);
                item.put("avgPrice", trade.getAvgPrice());
                item.put("change24h", coin.getChange24h());
                result.add(item);
            }
        }

        return result;
    }

    /**
     * 资金划转
     */
    @Transactional
    public void transfer(Long userId, Integer direction, BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new RuntimeException("划转金额必须大于0");
        }

        AccountFund fund = getOrCreateFundAccount(userId);

        // 获取交易账户USDT持仓
        AccountTrade tradeUsdt = getOrCreateTradeAccount(userId, "USDT");

        if (direction == 1) {
            // 资金账户 -> 交易账户
            if (fund.getBalance().compareTo(amount) < 0) {
                throw new RuntimeException("资金账户余额不足");
            }
            fund.setBalance(fund.getBalance().subtract(amount));
            tradeUsdt.setQuantity(tradeUsdt.getQuantity().add(amount));

            // 记录流水
            createFlow(userId, 4, amount.negate(), fund.getBalance().add(amount),
                    fund.getBalance(), "USDT", null, "划转至交易账户");

        } else if (direction == 2) {
            // 交易账户 -> 资金账户
            if (tradeUsdt.getQuantity().compareTo(amount) < 0) {
                throw new RuntimeException("交易账户USDT余额不足");
            }
            tradeUsdt.setQuantity(tradeUsdt.getQuantity().subtract(amount));
            fund.setBalance(fund.getBalance().add(amount));

            // 记录流水
            createFlow(userId, 3, amount, fund.getBalance().subtract(amount),
                    fund.getBalance(), "USDT", null, "划转至资金账户");

        } else {
            throw new RuntimeException("无效的划转方向");
        }

        fund.setUpdateTime(LocalDateTime.now());
        accountFundMapper.updateById(fund);

        tradeUsdt.setUpdateTime(LocalDateTime.now());
        accountTradeMapper.updateById(tradeUsdt);
    }

    /**
     * 获取或创建交易账户
     */
    public AccountTrade getOrCreateTradeAccount(Long userId, String coinCode) {
        LambdaQueryWrapper<AccountTrade> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountTrade::getUserId, userId)
                .eq(AccountTrade::getCoinCode, coinCode.toUpperCase());
        AccountTrade trade = accountTradeMapper.selectOne(wrapper);

        if (trade == null) {
            trade = new AccountTrade();
            trade.setUserId(userId);
            trade.setCoinCode(coinCode.toUpperCase());
            trade.setQuantity(BigDecimal.ZERO);
            trade.setFrozen(BigDecimal.ZERO);
            trade.setAvgPrice(BigDecimal.ZERO);
            trade.setTotalBuy(BigDecimal.ZERO);
            trade.setTotalSell(BigDecimal.ZERO);
            trade.setCreateTime(LocalDateTime.now());
            accountTradeMapper.insert(trade);
        }

        return trade;
    }

    /**
     * 创建资金流水
     */
    public void createFlow(Long userId, Integer flowType, BigDecimal amount,
                           BigDecimal balanceBefore, BigDecimal balanceAfter,
                           String coinCode, String relatedOrderNo, String remark) {
        AccountFlow flow = new AccountFlow();
        flow.setUserId(userId);
        flow.setFlowNo(OrderNoUtil.flowNo());
        flow.setFlowType(flowType);
        flow.setAmount(amount);
        flow.setBalanceBefore(balanceBefore);
        flow.setBalanceAfter(balanceAfter);
        flow.setCoinCode(coinCode);
        flow.setRelatedOrderNo(relatedOrderNo);
        flow.setRemark(remark);
        flow.setCreateTime(LocalDateTime.now());
        accountFlowMapper.insert(flow);
    }

    /**
     * 获取资金流水
     */
    public List<AccountFlow> getFlows(Long userId, Integer flowType, int page, int size) {
        LambdaQueryWrapper<AccountFlow> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountFlow::getUserId, userId);
        if (flowType != null && flowType > 0) {
            wrapper.eq(AccountFlow::getFlowType, flowType);
        }
        wrapper.orderByDesc(AccountFlow::getCreateTime);
        wrapper.last("LIMIT " + (page - 1) * size + ", " + size);
        return accountFlowMapper.selectList(wrapper);
    }

    /**
     * 更新资金账户
     */
    public void updateFundAccount(LambdaUpdateWrapper<AccountFund> updateWrapper) {
        accountFundMapper.update(null, updateWrapper);
    }
}
