import express from 'express';
import { EventsService } from '../services/events.service.js';
import { TimeManager } from '../utils/time.utils.js';
import { RedisService } from '../services/redis.service.js';

// Import METRIC_IDS from events service
const METRIC_IDS = {
  PLACED_ORDER: 'Y8cqcF',
  SHIPPED_ORDER: 'VExpdL',
  ACCOUNT_CREATED: 'TeeypV',
  CANCELED_ORDER: 'YjVMNg',
  NEW_BLOG_POST: 'YcxeDr',
  PAYMENT_REFUNDED: 'R7XUYh'
};

export function createEventsRouter(apiKey, apiRevision) {
  const router = express.Router();
  const timeManager = new TimeManager();
  const eventsService = new EventsService(apiKey, apiRevision);
  const redisService = new RedisService();

  // Get events with optional filtering
  router.get('/', async (req, res) => {
    try {
      const params = {
        pageSize: parseInt(req.query.pageSize) || 50,
        sort: req.query.sort || '-datetime',
        metricId: req.query.metricId,
        startDate: req.query.startDate,
        endDate: req.query.endDate,
        pageCursor: req.query.pageCursor,
        fields: {}
      };

      // Parse fields parameter if provided
      if (req.query.fields) {
        try {
          params.fields = JSON.parse(req.query.fields);
        } catch (e) {
          console.warn('[Events Route] Invalid fields parameter:', e);
        }
      }

      console.log('[Events Route] Fetching events with params:', params);
      const data = await eventsService.getEvents(params);
      console.log('[Events Route] Success:', {
        count: data.data?.length || 0,
        included: data.included?.length || 0
      });
      res.json(data);
    } catch (error) {
      console.error('[Events Route] Error:', error);
      res.status(500).json({ 
        status: 'error', 
        message: error.message,
        details: error.response?.data || null
      });
    }
  });

  // Get events by time range
  router.get('/by-time/:timeRange', async (req, res) => {
    try {
      const { timeRange } = req.params;
      const { metricId, startDate, endDate } = req.query;

      let result;
      if (timeRange === 'custom') {
        if (!startDate || !endDate) {
          return res.status(400).json({ error: 'Custom range requires startDate and endDate' });
        }

        const range = timeManager.getCustomRange(startDate, endDate);
        if (!range) {
          return res.status(400).json({ error: 'Invalid date range' });
        }

        result = await eventsService.getEvents({
          metricId,
          startDate: range.start.toISO(),
          endDate: range.end.toISO()
        });
      } else {
        result = await eventsService.getEventsByTimeRange(
          timeRange,
          { metricId }
        );
      }

      res.json(result);
    } catch (error) {
      console.error("[Events Route] Error:", error);
      res.status(500).json({ error: error.message });
    }
  });

  // Get comprehensive statistics for a time period
  router.get('/stats', async (req, res) => {
    try {
      const { timeRange, startDate, endDate } = req.query;
      console.log('[Events Route] Stats request:', {
        timeRange,
        startDate,
        endDate
      });

      let range;
      if (startDate && endDate) {
        range = timeManager.getCustomRange(startDate, endDate);
      } else if (timeRange) {
        range = timeManager.getDateRange(timeRange);
      } else {
        return res.status(400).json({ error: 'Must provide either timeRange or startDate and endDate' });
      }

      if (!range) {
        return res.status(400).json({ error: 'Invalid time range' });
      }

      const params = {
        timeRange,
        startDate: range.start.toISO(),
        endDate: range.end.toISO()
      };

      console.log('[Events Route] Calculating period stats with params:', params);
      const stats = await eventsService.calculatePeriodStats(params);
      console.log('[Events Route] Stats response:', {
        timeRange: {
          start: range.start.toISO(),
          end: range.end.toISO()
        },
        shippedCount: stats?.shipping?.shippedCount,
        totalOrders: stats?.orderCount
      });

      res.json({
        timeRange: {
          start: range.start.toISO(),
          end: range.end.toISO(),
          displayStart: timeManager.formatForDisplay(range.start),
          displayEnd: timeManager.formatForDisplay(range.end)
        },
        stats
      });
    } catch (error) {
      console.error("[Events Route] Error:", error);
      res.status(500).json({ error: error.message });
    }
  });

  // Add new route for detailed stats
  router.get('/stats/details', async (req, res) => {
    try {
      const { timeRange, startDate, endDate, metric, daily = false } = req.query;

      let range;
      if (startDate && endDate) {
        range = timeManager.getCustomRange(startDate, endDate);
      } else if (timeRange) {
        range = timeManager.getDateRange(timeRange);
      } else {
        return res.status(400).json({ error: 'Must provide either timeRange or startDate and endDate' });
      }

      if (!range) {
        return res.status(400).json({ error: 'Invalid time range' });
      }

      const params = {
        timeRange,
        startDate: range.start.toISO(),
        endDate: range.end.toISO(),
        metric,
        daily: daily === 'true' || daily === true
      };

      // Try to get from cache first
      const cacheKey = redisService._getCacheKey('stats:details', params);
      const cachedData = await redisService.get(cacheKey);
      
      if (cachedData) {
        console.log('[Events Route] Cache hit for detailed stats');
        return res.json({
          timeRange: {
            start: range.start.toISO(),
            end: range.end.toISO(),
            displayStart: timeManager.formatForDisplay(range.start),
            displayEnd: timeManager.formatForDisplay(range.end)
          },
          stats: cachedData
        });
      }

      const stats = await eventsService.calculateDetailedStats(params);

      // Cache the results
      const ttl = redisService._getTTL(timeRange);
      await redisService.set(cacheKey, stats, ttl);

      res.json({
        timeRange: {
          start: range.start.toISO(),
          end: range.end.toISO(),
          displayStart: timeManager.formatForDisplay(range.start),
          displayEnd: timeManager.formatForDisplay(range.end)
        },
        stats
      });
    } catch (error) {
      console.error("[Events Route] Error:", error);
      res.status(500).json({ error: error.message });
    }
  });

  // Get product statistics for a time period
  router.get('/products', async (req, res) => {
    try {
      const { timeRange, startDate, endDate } = req.query;

      let range;
      if (startDate && endDate) {
        range = timeManager.getCustomRange(startDate, endDate);
      } else if (timeRange) {
        range = timeManager.getDateRange(timeRange);
      } else {
        return res.status(400).json({ error: 'Must provide either timeRange or startDate and endDate' });
      }

      if (!range) {
        return res.status(400).json({ error: 'Invalid time range' });
      }

      const params = {
        timeRange,
        startDate: range.start.toISO(),
        endDate: range.end.toISO()
      };

      // Try to get from cache first
      const cacheKey = redisService._getCacheKey('events', params);
      const cachedData = await redisService.getEventData('products', params);
      
      if (cachedData) {
        console.log('[Events Route] Cache hit for products');
        return res.json({
          timeRange: {
            start: range.start.toISO(),
            end: range.end.toISO(),
            displayStart: timeManager.formatForDisplay(range.start),
            displayEnd: timeManager.formatForDisplay(range.end)
          },
          stats: {
            products: cachedData
          }
        });
      }

      const stats = await eventsService.calculatePeriodStats(params);

      res.json({
        timeRange: {
          start: range.start.toISO(),
          end: range.end.toISO(),
          displayStart: timeManager.formatForDisplay(range.start),
          displayEnd: timeManager.formatForDisplay(range.end)
        },
        stats
      });
    } catch (error) {
      console.error("[Events Route] Error:", error);
      res.status(500).json({ error: error.message });
    }
  });

  // Get event feed (multiple event types sorted by time)
  router.get('/feed', async (req, res) => {
    try {
      const { timeRange, startDate, endDate, metricIds } = req.query;

      let range;
      if (startDate && endDate) {
        range = timeManager.getCustomRange(startDate, endDate);
      } else if (timeRange) {
        range = timeManager.getDateRange(timeRange);
      } else {
        return res.status(400).json({ error: 'Must provide either timeRange or startDate and endDate' });
      }

      if (!range) {
        return res.status(400).json({ error: 'Invalid time range' });
      }

      const params = {
        timeRange,
        startDate: range.start.toISO(),
        endDate: range.end.toISO(),
        metricIds: metricIds ? JSON.parse(metricIds) : null
      };

      const result = await eventsService.getMultiMetricEvents(params);

      res.json({
        timeRange: {
          start: range.start.toISO(),
          end: range.end.toISO(),
          displayStart: timeManager.formatForDisplay(range.start),
          displayEnd: timeManager.formatForDisplay(range.end)
        },
        ...result
      });
    } catch (error) {
      console.error("[Events Route] Error:", error);
      res.status(500).json({ error: error.message });
    }
  });

  // Get aggregated events data
  router.get('/aggregate', async (req, res) => {
    try {
      const { timeRange, startDate, endDate, interval = 'day', metricId, property } = req.query;

      let range;
      if (startDate && endDate) {
        range = timeManager.getCustomRange(startDate, endDate);
      } else if (timeRange) {
        range = timeManager.getDateRange(timeRange);
      } else {
        return res.status(400).json({ error: 'Must provide either timeRange or startDate and endDate' });
      }

      if (!range) {
        return res.status(400).json({ error: 'Invalid time range' });
      }

      const params = {
        timeRange,
        startDate: range.start.toISO(),
        endDate: range.end.toISO(),
        metricId,
        interval,
        property
      };

      const result = await eventsService.getEvents(params);
      const groupedData = timeManager.groupEventsByInterval(result.data, interval, property);

      res.json({
        timeRange: {
          start: range.start.toISO(),
          end: range.end.toISO(),
          displayStart: timeManager.formatForDisplay(range.start),
          displayEnd: timeManager.formatForDisplay(range.end)
        },
        data: groupedData
      });
    } catch (error) {
      console.error("[Events Route] Error:", error);
      res.status(500).json({ error: error.message });
    }
  });

  // Get date range for a given time period
  router.get("/dateRange", async (req, res) => {
    try {
      const { timeRange, startDate, endDate } = req.query;

      let range;
      if (startDate && endDate) {
        range = timeManager.getCustomRange(startDate, endDate);
      } else {
        range = timeManager.getDateRange(timeRange || 'today');
      }

      if (!range) {
        return res.status(400).json({ 
          error: "Invalid time range parameters" 
        });
      }

      res.json({
        start: range.start.toISO(),
        end: range.end.toISO(),
        displayStart: timeManager.formatForDisplay(range.start),
        displayEnd: timeManager.formatForDisplay(range.end)
      });
    } catch (error) {
      console.error('Error getting date range:', error);
      res.status(500).json({ 
        error: "Failed to get date range" 
      });
    }
  });

  // Clear cache for a specific time range
  router.post("/clearCache", async (req, res) => {
    try {
      const { timeRange, startDate, endDate } = req.body;
      await redisService.clearCache({ timeRange, startDate, endDate });
      res.json({ message: "Cache cleared successfully" });
    } catch (error) {
      console.error('Error clearing cache:', error);
      res.status(500).json({ error: "Failed to clear cache" });
    }
  });

  // Add new batch metrics endpoint
  router.get('/batch', async (req, res) => {
    try {
      const { timeRange, startDate, endDate, metrics } = req.query;
      
      // Parse metrics array from query
      const metricsList = metrics ? JSON.parse(metrics) : [];
      
      const params = timeRange === 'custom'
        ? { startDate, endDate, metrics: metricsList }
        : { timeRange, metrics: metricsList };

      const results = await eventsService.getBatchMetrics(params);
      
      res.json(results);
    } catch (error) {
      console.error('[Events Route] Error in batch request:', error);
      res.status(500).json({ error: error.message });
    }
  });

  return router;
} 