import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '@common/prisma/prisma.service';
import { RedisService } from '@common/redis/redis.service';
import { KLineData, TickData, MarketOverview, Product } from './interfaces/market.interface';

@Injectable()
export class MarketService {
  constructor(
    private readonly prisma: PrismaService,
    private readonly redis: RedisService,
  ) {}

  // 获取品种列表
  async getProducts(category?: string, page = 1, size = 20): Promise<{ list: Product[]; total: number }> {
    const where = category && category !== 'all' ? { category } : {};

    const [products, total] = await Promise.all([
      this.prisma.product.findMany({
        where,
        skip: (page - 1) * size,
        take: size,
        orderBy: { id: 'asc' },
      }),
      this.prisma.product.count({ where }),
    ]);

    // 合并Redis中的实时数据
    const list = await Promise.all(
      products.map(async (product) => {
        const tick = await this.redis.getTick(product.symbol);
        return this.mergeProductWithTick(product, tick);
      }),
    );

    return { list, total };
  }

  // 获取单个品种详情
  async getProduct(symbol: string): Promise<Product> {
    const product = await this.prisma.product.findUnique({
      where: { symbol: symbol.toUpperCase() },
    });

    if (!product) {
      throw new NotFoundException(`品种 ${symbol} 不存在`);
    }

    const tick = await this.redis.getTick(product.symbol);
    return this.mergeProductWithTick(product, tick);
  }

  // 获取K线数据
  async getKlineData(
    symbol: string,
    period: string,
    count = 100,
    startTime?: Date,
    endTime?: Date,
  ): Promise<KLineData[]> {
    const product = await this.prisma.product.findUnique({
      where: { symbol: symbol.toUpperCase() },
    });

    if (!product) {
      throw new NotFoundException(`品种 ${symbol} 不存在`);
    }

    // 优先从Redis获取
    const cachedKlines = await this.redis.getKlines(symbol, period, count);
    if (cachedKlines.length >= count / 2) {
      return cachedKlines.map((k) => JSON.parse(k)).reverse();
    }

    // 从数据库查询
    const where: any = {
      productId: product.id,
      period,
    };

    if (startTime) {
      where.time = { ...where.time, gte: startTime };
    }
    if (endTime) {
      where.time = { ...where.time, lte: endTime };
    }

    const klines = await this.prisma.klineData.findMany({
      where,
      orderBy: { time: 'desc' },
      take: count,
    });

    return klines.reverse().map((k) => ({
      time: k.time.toISOString(),
      open: Number(k.open),
      high: Number(k.high),
      low: Number(k.low),
      close: Number(k.close),
      volume: Number(k.volume),
    }));
  }

  // 获取实时Tick数据
  async getTickData(symbol: string): Promise<TickData> {
    const product = await this.prisma.product.findUnique({
      where: { symbol: symbol.toUpperCase() },
    });

    if (!product) {
      throw new NotFoundException(`品种 ${symbol} 不存在`);
    }

    const tick = await this.redis.getTick(symbol);

    if (!tick || Object.keys(tick).length === 0) {
      // 如果没有缓存数据，返回模拟数据
      return this.generateMockTick(product.symbol);
    }

    return {
      symbol: product.symbol,
      price: parseFloat(tick.price) || 0,
      change: parseFloat(tick.change) || 0,
      changePercent: parseFloat(tick.changePercent) || 0,
      open: parseFloat(tick.open) || 0,
      high: parseFloat(tick.high) || 0,
      low: parseFloat(tick.low) || 0,
      volume: parseInt(tick.volume) || 0,
      openInterest: tick.openInterest ? parseInt(tick.openInterest) : undefined,
      bidPrice: tick.bidPrice ? parseFloat(tick.bidPrice) : undefined,
      askPrice: tick.askPrice ? parseFloat(tick.askPrice) : undefined,
      bidVolume: tick.bidVolume ? parseInt(tick.bidVolume) : undefined,
      askVolume: tick.askVolume ? parseInt(tick.askVolume) : undefined,
      timestamp: parseInt(tick.timestamp) || Date.now(),
    };
  }

  // 获取市场概览
  async getMarketOverview(): Promise<MarketOverview> {
    const products = await this.prisma.product.findMany();
    const ticks = await Promise.all(
      products.map((p) => this.redis.getTick(p.symbol)),
    );

    const validTicks = ticks.filter((t) => t && t.price);
    
    let upCount = 0;
    let downCount = 0;
    let totalChange = 0;
    let totalVolume = 0;

    validTicks.forEach((tick) => {
      const change = parseFloat(tick.change) || 0;
      if (change > 0) upCount++;
      else if (change < 0) downCount++;
      totalChange += Math.abs(change);
      totalVolume += parseInt(tick.volume) || 0;
    });

    // 计算市场热度指数 (0-100)
    const heatIndex = validTicks.length > 0
      ? Math.min(100, Math.max(0, 50 + (upCount - downCount) * 2))
      : 50;

    // 计算波动率指数 (基于涨跌幅标准差)
    const volatilityIndex = validTicks.length > 0
      ? (totalChange / validTicks.length) * 10
      : 20;

    return {
      heatIndex: Number(heatIndex.toFixed(1)),
      heatChange: Number(((Math.random() - 0.5) * 10).toFixed(1)),
      upCount,
      downCount,
      capitalFlow: Number((totalVolume / 10000).toFixed(1)),
      volatilityIndex: Number(volatilityIndex.toFixed(1)),
      volatilityChange: Number(((Math.random() - 0.5) * 5).toFixed(1)),
    };
  }

  // 批量获取Tick数据
  async getBatchTicks(symbols: string[]): Promise<Record<string, TickData>> {
    const result: Record<string, TickData> = {};
    
    await Promise.all(
      symbols.map(async (symbol) => {
        try {
          result[symbol] = await this.getTickData(symbol);
        } catch (error) {
          // 忽略不存在的品种
        }
      }),
    );

    return result;
  }

  // 存储Tick数据
  async storeTickData(symbol: string, data: TickData): Promise<void> {
    await this.redis.setTick(symbol, {
      price: data.price.toString(),
      change: data.change.toString(),
      changePercent: data.changePercent.toString(),
      open: data.open.toString(),
      high: data.high.toString(),
      low: data.low.toString(),
      volume: data.volume.toString(),
      openInterest: data.openInterest?.toString(),
      bidPrice: data.bidPrice?.toString(),
      askPrice: data.askPrice?.toString(),
      bidVolume: data.bidVolume?.toString(),
      askVolume: data.askVolume?.toString(),
      timestamp: data.timestamp.toString(),
    });
  }

  // 存储K线数据
  async storeKlineData(symbol: string, period: string, data: KLineData): Promise<void> {
    await this.redis.addKline(symbol, period, JSON.stringify(data));
  }

  private mergeProductWithTick(product: any, tick: Record<string, string>): Product {
    const basePrice = 500; // 基础价格，实际应从历史数据获取
    
    return {
      id: product.id.toString(),
      symbol: product.symbol,
      name: product.name,
      category: product.category,
      price: tick.price ? parseFloat(tick.price) : basePrice,
      change: tick.change ? parseFloat(tick.change) : 0,
      changePercent: tick.changePercent ? parseFloat(tick.changePercent) : 0,
      open: tick.open ? parseFloat(tick.open) : basePrice,
      high: tick.high ? parseFloat(tick.high) : basePrice,
      low: tick.low ? parseFloat(tick.low) : basePrice,
      volume: tick.volume ? parseInt(tick.volume) : 0,
      openInterest: tick.openInterest ? parseInt(tick.openInterest) : 0,
    };
  }

  private generateMockTick(symbol: string): TickData {
    const basePrice = 500;
    const change = (Math.random() - 0.5) * 20;
    
    return {
      symbol,
      price: basePrice + change,
      change,
      changePercent: (change / basePrice) * 100,
      open: basePrice,
      high: basePrice + Math.abs(change) + 10,
      low: basePrice - Math.abs(change) - 10,
      volume: Math.floor(Math.random() * 100000),
      timestamp: Date.now(),
    };
  }
}
