const { Candle1h, Symbol } = require('../models');
const { Op } = require('sequelize');

class CandleController {
  // Get candles for a symbol
  async getCandles(req, res, next) {
    try {
      const {
        symbolId,
        startTime,
        endTime,
        limit = 100,
        offset = 0
      } = req.query;

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

      const where = { symbolId: parseInt(symbolId) };

      if (startTime) {
        where.openTime = {
          ...where.openTime,
          [Op.gte]: new Date(startTime)
        };
      }

      if (endTime) {
        where.openTime = {
          ...where.openTime,
          [Op.lte]: new Date(endTime)
        };
      }

      const candles = await Candle1h.findAndCountAll({
        where,
        limit: parseInt(limit),
        offset: parseInt(offset),
        order: [['openTime', 'DESC']],
        include: [{
          model: Symbol,
          as: 'symbol',
          attributes: ['symbol', 'exchange', 'instrumentType']
        }]
      });

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

  // Get latest candle for a symbol
  async getLatestCandle(req, res, next) {
    try {
      const { symbolId } = req.params;

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

      const candle = await Candle1h.findOne({
        where: { symbolId: parseInt(symbolId) },
        order: [['openTime', 'DESC']],
        include: [{
          model: Symbol,
          as: 'symbol',
          attributes: ['symbol', 'exchange', 'instrumentType']
        }]
      });

      if (!candle) {
        const error = new Error('No candle data found for this symbol');
        error.statusCode = 404;
        return next(error);
      }

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

  // Create new candle
  async createCandle(req, res, next) {
    try {
      const candleData = {
        ...req.body,
        symbolId: parseInt(req.body.symbolId)
      };

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

      const candle = await Candle1h.create(candleData);

      res.status(201).json({
        success: true,
        data: candle,
        message: 'Candle created successfully'
      });
    } catch (error) {
      next(error);
    }
  }

  // Bulk create candles
  async bulkCreateCandles(req, res, next) {
    try {
      const { candles } = req.body;

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

      // Verify all symbols exist
      const symbolIds = [...new Set(candles.map(c => c.symbolId))];
      const existingSymbols = await Symbol.findAll({
        where: { id: symbolIds },
        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 symbol IDs: ${invalidSymbolIds.join(', ')}`);
        error.statusCode = 400;
        return next(error);
      }

      const createdCandles = await Candle1h.bulkCreate(candles);

      res.status(201).json({
        success: true,
        data: createdCandles,
        message: `${createdCandles.length} candles created successfully`
      });
    } catch (error) {
      next(error);
    }
  }

  // Get OHLC data aggregated by time period
  async getOHLC(req, res, next) {
    try {
      const { symbolId, period = '1h', limit = 100 } = req.query;

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

      // For now, only support 1h period since we only have candles_1h table
      if (period !== '1h') {
        const error = new Error('Only 1h period is currently supported');
        error.statusCode = 400;
        return next(error);
      }

      const candles = await Candle1h.findAll({
        where: { symbolId: parseInt(symbolId) },
        limit: parseInt(limit),
        order: [['openTime', 'DESC']],
        attributes: ['openTime', 'open', 'high', 'low', 'close', 'volume']
      });

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

  // Clean up old candles, keep latest N candles
  async cleanupCandles(req, res, next) {
    try {
      const { symbolId } = req.params;
      const { keep = 1000 } = req.query;

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

      // Get total count of candles for this symbol
      const totalCandles = await Candle1h.count({
        where: { symbolId: parseInt(symbolId) }
      });

      if (totalCandles <= keep) {
        return res.json({
          success: true,
          message: `No cleanup needed. Only ${totalCandles} candles exist (keep: ${keep})`,
          deletedCount: 0
        });
      }

      // Get the IDs of candles to keep (latest N candles)
      const candlesToKeep = await Candle1h.findAll({
        where: { symbolId: parseInt(symbolId) },
        order: [['openTime', 'DESC']],
        limit: parseInt(keep),
        attributes: ['id']
      });

      const keepIds = candlesToKeep.map(candle => candle.id);

      // Delete older candles (those not in keepIds)
      const deletedCount = await Candle1h.destroy({
        where: {
          symbolId: parseInt(symbolId),
          id: {
            [Op.notIn]: keepIds
          }
        }
      });

      res.json({
        success: true,
        message: `Cleanup completed. Deleted ${deletedCount} old candles, kept ${keepIds.length} latest candles`,
        deletedCount,
        keptCount: keepIds.length,
        symbol: symbol.symbol
      });
    } catch (error) {
      next(error);
    }
  }
}

module.exports = new CandleController();
