package com.yingpai.stock.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yingpai.stock.domain.StockPool;
import com.yingpai.stock.domain.StockQuoteData;
import com.yingpai.stock.domain.bo.StockPoolBo;
import com.yingpai.stock.domain.vo.StockPoolVo;
import com.yingpai.stock.mapper.StockPoolMapper;
import com.yingpai.stock.service.IStockPoolService;
import com.yingpai.stock.service.IStockQuoteService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 股票池服务实现类
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class StockPoolServiceImpl implements IStockPoolService {

    private final StockPoolMapper baseMapper;
    private final IStockQuoteService stockQuoteService;

    @Override
    public TableDataInfo<StockPoolVo> queryPageList(StockPoolBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<StockPool> lqw = buildQueryWrapper(bo);
        Page<StockPoolVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);

        // 填充实时数据
        fillRealTimeData(result.getRecords());

        return TableDataInfo.build(result);
    }

    @Override
    public List<StockPoolVo> queryList(StockPoolBo bo) {
        LambdaQueryWrapper<StockPool> lqw = buildQueryWrapper(bo);
        List<StockPoolVo> list = baseMapper.selectVoList(lqw);

        // 填充实时数据
        fillRealTimeData(list);

        return list;
    }

    @Override
    public StockPoolVo queryById(Long id) {
        StockPoolVo vo = baseMapper.selectVoById(id);
        if (vo != null) {
            fillRealTimeData(List.of(vo));
        }
        return vo;
    }

    @Override
    public Boolean insertByBo(StockPoolBo bo) {
        // 先检查是否已存在（不限制status，因为唯一索引包含status）
        LambdaQueryWrapper<StockPool> checkWrapper = Wrappers.lambdaQuery();
        checkWrapper.eq(StockPool::getStockCode, bo.getStockCode())
            .eq(StockPool::getPoolType, bo.getPoolType())
            .orderByDesc(StockPool::getId)
            .last("LIMIT 1");
        StockPool existing = baseMapper.selectOne(checkWrapper);

        if (existing != null) {
            if (existing.getStatus() == 1) {
                // 已经在池中，无需操作
                return true;
            }
            // 已移除的记录，恢复状态
            existing.setStatus(1);
            existing.setAdminId(LoginHelper.getUserId());
            existing.setUpdateTime(LocalDateTime.now());
            existing.setAddDate(LocalDate.now());
            // 更新入池价格
            BigDecimal price = fetchCurrentPrice(bo.getStockCode());
            existing.setAddPrice(price != null ? price : BigDecimal.ZERO);
            return baseMapper.updateById(existing) > 0;
        }

        // 不存在，新增
        StockPool entity = BeanUtil.toBean(bo, StockPool.class);
        entity.setStatus(1);
        entity.setAdminId(LoginHelper.getUserId());
        entity.setCreateTime(LocalDateTime.now());
        entity.setUpdateTime(LocalDateTime.now());

        if (entity.getAddDate() == null) {
            entity.setAddDate(LocalDate.now());
        }

        // 如果没有传入价格，尝试获取实时价格
        if (entity.getAddPrice() == null) {
            BigDecimal price = fetchCurrentPrice(entity.getStockCode());
            entity.setAddPrice(price != null ? price : BigDecimal.ZERO);
        }

        boolean flag = baseMapper.insert(entity) > 0;
        if (flag) {
            bo.setId(entity.getId());
        }
        return flag;
    }

    @Override
    public Boolean updateByBo(StockPoolBo bo) {
        StockPool entity = BeanUtil.toBean(bo, StockPool.class);
        entity.setUpdateTime(LocalDateTime.now());
        return baseMapper.updateById(entity) > 0;
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public Boolean softDeleteByIds(Collection<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return false;
        }
        // 批量更新状态为0（已移除）
        return baseMapper.update(null, Wrappers.<StockPool>lambdaUpdate()
            .set(StockPool::getStatus, 0)
            .set(StockPool::getUpdateTime, LocalDateTime.now())
            .in(StockPool::getId, ids)) > 0;
    }

    @Override
    public Boolean removeByCodeAndType(String stockCode, Integer poolType) {
        LambdaQueryWrapper<StockPool> lqw = Wrappers.lambdaQuery();
        lqw.eq(StockPool::getStockCode, stockCode)
            .eq(StockPool::getPoolType, poolType)
            .eq(StockPool::getStatus, 1);
        StockPool pool = baseMapper.selectOne(lqw);
        if (pool != null) {
            pool.setStatus(0);
            return baseMapper.updateById(pool) > 0;
        }
        return false;
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<StockPool> buildQueryWrapper(StockPoolBo bo) {
        LambdaQueryWrapper<StockPool> lqw = Wrappers.lambdaQuery();
        lqw.eq(ObjectUtil.isNotNull(bo.getId()), StockPool::getId, bo.getId());
        lqw.like(StringUtils.isNotBlank(bo.getStockCode()), StockPool::getStockCode, bo.getStockCode());
        lqw.like(StringUtils.isNotBlank(bo.getStockName()), StockPool::getStockName, bo.getStockName());
        lqw.eq(ObjectUtil.isNotNull(bo.getPoolType()), StockPool::getPoolType, bo.getPoolType());
        lqw.eq(ObjectUtil.isNotNull(bo.getStatus()), StockPool::getStatus, bo.getStatus());
        lqw.ge(ObjectUtil.isNotNull(bo.getStartDate()), StockPool::getAddDate, bo.getStartDate());
        lqw.le(ObjectUtil.isNotNull(bo.getEndDate()), StockPool::getAddDate, bo.getEndDate());
        lqw.orderByDesc(StockPool::getAddDate);
        return lqw;
    }

    /**
     * 填充实时数据（使用多线程服务）
     */
    private void fillRealTimeData(List<StockPoolVo> list) {
        if (list == null || list.isEmpty()) {
            return;
        }

        List<String> codes = list.stream()
            .map(StockPoolVo::getStockCode)
            .collect(Collectors.toList());

        // 使用多线程行情服务
        Map<String, StockQuoteData> quoteMap = stockQuoteService.batchFetchQuotesParallel(codes);

        for (StockPoolVo vo : list) {
            // 设置池类型名称
            vo.setPoolTypeName(vo.getPoolType() == 1 ? "超短池" : "强势池");

            StockQuoteData quote = quoteMap.get(vo.getStockCode());
            if (quote != null) {
                vo.setCurrentPrice(quote.getCurrentPrice());
                vo.setYesterdayClose(quote.getYesterdayClose());
                vo.setChangeAmount(quote.getChangeAmount());
                vo.setChangePercent(quote.getChangePercent());
                vo.setTurnoverRate(quote.getTurnoverRate());
                vo.setTradeAmount(quote.getTradeAmount());

                // 计算入池收益率
                if (vo.getAddPrice() != null && vo.getCurrentPrice() != null
                    && vo.getAddPrice().compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal profit = vo.getCurrentPrice().subtract(vo.getAddPrice())
                        .divide(vo.getAddPrice(), 4, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal("100"));
                    vo.setProfitPercent(profit.setScale(2, RoundingMode.HALF_UP));
                }
            }
        }
    }

    /**
     * 获取单个股票当前价格
     */
    private BigDecimal fetchCurrentPrice(String code) {
        Map<String, StockQuoteData> quotes = stockQuoteService.batchFetchQuotesParallel(List.of(code));
        StockQuoteData quote = quotes.get(code);
        return quote != null ? quote.getCurrentPrice() : null;
    }
}
