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.StockInfo;
import com.yingpai.stock.domain.StockPool;
import com.yingpai.stock.domain.StockQuoteData;
import com.yingpai.stock.domain.bo.StockInfoBo;
import com.yingpai.stock.domain.vo.StockInfoVo;
import com.yingpai.stock.mapper.StockInfoMapper;
import com.yingpai.stock.mapper.StockPoolMapper;
import com.yingpai.stock.service.IStockInfoService;
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.springframework.stereotype.Service;

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

/**
 * 股票信息服务实现类
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class StockInfoServiceImpl implements IStockInfoService {

    private final StockInfoMapper baseMapper;
    private final StockPoolMapper stockPoolMapper;
    private final IStockQuoteService stockQuoteService;

    @Override
    public TableDataInfo<StockInfoVo> queryPageList(StockInfoBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<StockInfo> lqw = buildQueryWrapper(bo);
        Page<StockInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        // 填充池状态和实时行情
        fillPoolStatus(result.getRecords());
        fillRealTimeData(result.getRecords());
        return TableDataInfo.build(result);
    }

    @Override
    public List<StockInfoVo> queryList(StockInfoBo bo) {
        LambdaQueryWrapper<StockInfo> lqw = buildQueryWrapper(bo);
        List<StockInfoVo> list = baseMapper.selectVoList(lqw);
        fillPoolStatus(list);
        fillRealTimeData(list);
        return list;
    }

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

    @Override
    public Boolean insertByBo(StockInfoBo bo) {
        StockInfo entity = BeanUtil.toBean(bo, StockInfo.class);
        entity.setCreateTime(LocalDateTime.now());
        entity.setUpdateTime(LocalDateTime.now());
        boolean flag = baseMapper.insert(entity) > 0;
        if (flag) {
            bo.setId(entity.getId());
        }
        return flag;
    }

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

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return false;
        }
        // 先查询要删除的股票代码
        List<StockInfo> stocks = baseMapper.selectByIds(ids);
        List<String> stockCodes = stocks.stream()
            .map(StockInfo::getStockCode)
            .collect(Collectors.toList());
        
        // 级联删除股票池中的记录
        if (!stockCodes.isEmpty()) {
            LambdaQueryWrapper<StockPool> poolWrapper = Wrappers.lambdaQuery();
            poolWrapper.in(StockPool::getStockCode, stockCodes);
            stockPoolMapper.delete(poolWrapper);
        }
        
        // 删除股票信息
        return baseMapper.deleteByIds(ids) > 0;
    }

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

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

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

        for (StockInfoVo vo : list) {
            StockQuoteData quote = quoteMap.get(vo.getStockCode());
            if (quote != null) {
                vo.setCurrentPrice(quote.getCurrentPrice());
                vo.setYesterdayClose(quote.getYesterdayClose());
                vo.setChangePercent(quote.getChangePercent());
                vo.setTurnoverRate(quote.getTurnoverRate());
                vo.setTradeAmount(quote.getTradeAmount());
            }
        }
    }

    /**
     * 填充池状态
     */
    private void fillPoolStatus(List<StockInfoVo> list) {
        if (list == null || list.isEmpty()) {
            return;
        }

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

        LambdaQueryWrapper<StockPool> poolWrapper = Wrappers.lambdaQuery();
        poolWrapper.in(StockPool::getStockCode, codes)
            .eq(StockPool::getStatus, 1);
        List<StockPool> pools = stockPoolMapper.selectList(poolWrapper);

        Map<String, Set<Integer>> poolMap = new HashMap<>();
        for (StockPool pool : pools) {
            poolMap.computeIfAbsent(pool.getStockCode(), k -> new HashSet<>())
                .add(pool.getPoolType());
        }

        for (StockInfoVo vo : list) {
            Set<Integer> types = poolMap.get(vo.getStockCode());
            vo.setInShortPool(types != null && types.contains(1));
            vo.setInStrongPool(types != null && types.contains(2));

            List<String> statusList = new ArrayList<>();
            if (Boolean.TRUE.equals(vo.getInShortPool())) {
                statusList.add("超短池");
            }
            if (Boolean.TRUE.equals(vo.getInStrongPool())) {
                statusList.add("强势池");
            }
            vo.setPoolStatus(statusList.isEmpty() ? "未入池" : String.join(",", statusList));
        }
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<StockInfo> buildQueryWrapper(StockInfoBo bo) {
        LambdaQueryWrapper<StockInfo> lqw = Wrappers.lambdaQuery();
        lqw.eq(ObjectUtil.isNotNull(bo.getId()), StockInfo::getId, bo.getId());
        lqw.like(StringUtils.isNotBlank(bo.getStockCode()), StockInfo::getStockCode, bo.getStockCode());
        lqw.like(StringUtils.isNotBlank(bo.getStockName()), StockInfo::getStockName, bo.getStockName());
        lqw.eq(StringUtils.isNotBlank(bo.getMarket()), StockInfo::getMarket, bo.getMarket());
        lqw.orderByAsc(StockInfo::getId);
        return lqw;
    }
}
