const { LivePrice, Symbol } = require('../models');

class LivePriceController {
  // Get all live prices
  async getAllLivePrices(req, res, next) {
    try {
      const { limit = 100, offset = 0 } = req.query;

      const livePrices = await LivePrice.findAndCountAll({
        limit: parseInt(limit),
        offset: parseInt(offset),
        order: [['lastUpdated', 'DESC']],
        include: [{
          model: Symbol,
          as: 'livePriceSymbol',
          attributes: ['symbol', 'exchange', 'instrumentType', 'isActive']
        }]
      });

      res.json({
        success: true,
        data: livePrices.rows,
        pagination: {
          total: livePrices.count,
          limit: parseInt(limit),
          offset: parseInt(offset),
          hasMore: offset + livePrices.rows.length < livePrices.count
        }
      });
    } catch (error) {
      next(error);
    }
  }

  // Get live price for a specific symbol
  async getLivePrice(req, res, next) {
    try {
      const { symbolId } = req.params;

      const livePrice = await LivePrice.findOne({
        where: { symbolId: parseInt(symbolId) },
        include: [{
          model: Symbol,
          as: 'livePriceSymbol',
          attributes: ['symbol', 'exchange', 'instrumentType', 'isActive']
        }]
      });

      if (!livePrice) {
        const error = new Error('Live price not found for this symbol');
        error.statusCode = 404;
        return next(error);
      }

      res.json({
        success: true,
        data: livePrice
      });
    } catch (error) {
      next(error);
    }
  }

  // Update or create live price
  async upsertLivePrice(req, res, next) {
    try {
      const { symbolId, price, bid, ask, bidSize, askSize } = req.body;

      // Verify symbol exists and is active
      const symbol = await Symbol.findByPk(symbolId);
      if (!symbol) {
        const error = new Error('Symbol not found');
        error.statusCode = 404;
        return next(error);
      }

      if (!symbol.isActive) {
        const error = new Error('Cannot update live price for inactive symbol');
        error.statusCode = 400;
        return next(error);
      }

      const [livePrice, created] = await LivePrice.upsert({
        symbolId: parseInt(symbolId),
        price,
        bid,
        ask,
        bidSize,
        askSize,
        lastUpdated: new Date()
      });

      res.status(created ? 201 : 200).json({
        success: true,
        data: livePrice,
        message: created ? 'Live price created successfully' : 'Live price updated successfully'
      });
    } catch (error) {
      next(error);
    }
  }

  // Bulk update live prices
  async bulkUpdateLivePrices(req, res, next) {
    try {
      const { prices } = req.body;

      if (!Array.isArray(prices) || prices.length === 0) {
        const error = new Error('Prices array is required');
        error.statusCode = 400;
        return next(error);
      }

      // Verify all symbols exist and are active
      const symbolIds = prices.map(p => p.symbolId);
      const existingSymbols = await Symbol.findAll({
        where: {
          id: symbolIds,
          isActive: true
        },
        attributes: ['id']
      });

      const existingSymbolIds = existingSymbols.map(s => s.id);
      const invalidSymbolIds = symbolIds.filter(id => !existingSymbolIds.includes(id));

      if (invalidSymbolIds.length > 0) {
        const error = new Error(`Invalid or inactive symbol IDs: ${invalidSymbolIds.join(', ')}`);
        error.statusCode = 400;
        return next(error);
      }

      // Prepare data for bulk upsert
      const upsertData = prices.map(price => ({
        symbolId: parseInt(price.symbolId),
        price: price.price,
        bid: price.bid,
        ask: price.ask,
        bidSize: price.bidSize,
        askSize: price.askSize,
        lastUpdated: new Date()
      }));

      const updatedPrices = [];
      for (const data of upsertData) {
        const [livePrice] = await LivePrice.upsert(data);
        updatedPrices.push(livePrice);
      }

      res.json({
        success: true,
        data: updatedPrices,
        message: `${updatedPrices.length} live prices updated successfully`
      });
    } catch (error) {
      next(error);
    }
  }

  // Get live prices by exchange
  async getLivePricesByExchange(req, res, next) {
    try {
      const { exchange } = req.params;
      const { limit = 100, offset = 0 } = req.query;

      const livePrices = await LivePrice.findAndCountAll({
        limit: parseInt(limit),
        offset: parseInt(offset),
        order: [['lastUpdated', 'DESC']],
        include: [{
          model: Symbol,
          as: 'livePriceSymbol',
          where: { exchange, isActive: true },
          attributes: ['symbol', 'exchange', 'instrumentType']
        }]
      });

      res.json({
        success: true,
        data: livePrices.rows,
        pagination: {
          total: livePrices.count,
          limit: parseInt(limit),
          offset: parseInt(offset),
          hasMore: offset + livePrices.rows.length < livePrices.count
        }
      });
    } catch (error) {
      next(error);
    }
  }

  // Get live prices by instrument type
  async getLivePricesByType(req, res, next) {
    try {
      const { type } = req.params;
      const { limit = 100, offset = 0 } = req.query;

      const livePrices = await LivePrice.findAndCountAll({
        limit: parseInt(limit),
        offset: parseInt(offset),
        order: [['lastUpdated', 'DESC']],
        include: [{
          model: Symbol,
          as: 'livePriceSymbol',
          where: { instrumentType: type, isActive: true },
          attributes: ['symbol', 'exchange', 'instrumentType']
        }]
      });

      res.json({
        success: true,
        data: livePrices.rows,
        pagination: {
          total: livePrices.count,
          limit: parseInt(limit),
          offset: parseInt(offset),
          hasMore: offset + livePrices.rows.length < livePrices.count
        }
      });
    } catch (error) {
      next(error);
    }
  }

  // Delete live price for a symbol
  async deleteLivePrice(req, res, next) {
    try {
      const { symbolId } = req.params;

      const deletedRowsCount = await LivePrice.destroy({
        where: { symbolId: parseInt(symbolId) }
      });

      if (deletedRowsCount === 0) {
        const error = new Error('Live price not found for this symbol');
        error.statusCode = 404;
        return next(error);
      }

      res.json({
        success: true,
        message: 'Live price deleted successfully'
      });
    } catch (error) {
      next(error);
    }
  }
}

module.exports = new LivePriceController();
