/**
 * Enhanced Tracking Routes for Redirect Intelligence v2
 * 
 * Provides the new v2 tracking endpoints with database persistence and enhanced features
 */

import express from 'express';
import { z } from 'zod';
import rateLimit from 'express-rate-limit';
import { RedirectTrackerService } from '../services/redirect-tracker.service';
import { optionalAuth, requireAuth, AuthenticatedRequest } from '../middleware/auth.middleware';
import { logger } from '../lib/logger';

const router = express.Router();
const redirectTracker = new RedirectTrackerService();

// Rate limiting for tracking endpoints
const trackingLimiter = rateLimit({
  windowMs: 60 * 60 * 1000, // 1 hour
  max: 200, // Higher limit for v2 API (vs 100 for legacy)
  message: {
    success: false,
    error: 'Rate limit exceeded',
    message: 'Too many tracking requests. Please try again later.'
  },
  standardHeaders: true,
  legacyHeaders: false,
  keyGenerator: (req: AuthenticatedRequest) => {
    // Use user ID for authenticated requests, IP for anonymous
    return req.user ? `user:${req.user.id}` : `ip:${req.ip}`;
  },
});

// Anonymous tracking has lower limits
const anonymousTrackingLimiter = rateLimit({
  windowMs: 60 * 60 * 1000, // 1 hour
  max: 50, // Lower limit for anonymous users
  message: {
    success: false,
    error: 'Rate limit exceeded',
    message: 'Anonymous users are limited to 50 requests per hour. Please register for higher limits.'
  },
  standardHeaders: true,
  legacyHeaders: false,
  skip: (req: AuthenticatedRequest) => !!req.user, // Skip for authenticated users
});

// Input validation schemas
const trackUrlSchema = z.object({
  url: z.string().min(1, 'URL is required'),
  method: z.enum(['GET', 'POST', 'HEAD']).default('GET'),
  userAgent: z.string().optional(),
  headers: z.record(z.string()).optional(),
  projectId: z.string().optional(),
  followJS: z.boolean().default(false),
  maxHops: z.number().min(1).max(20).default(10),
  timeout: z.number().min(1000).max(30000).default(15000),
});

const listChecksSchema = z.object({
  projectId: z.string(),
  limit: z.number().min(1).max(100).default(50),
  offset: z.number().min(0).default(0),
});

/**
 * POST /api/v2/track
 * Enhanced redirect tracking with database persistence
 */
router.post('/track', 
  optionalAuth, 
  trackingLimiter, 
  anonymousTrackingLimiter, 
  async (req: AuthenticatedRequest, res) => {
    try {
      // Validate input
      const validatedData = trackUrlSchema.parse(req.body);
      
      // Normalize URL
      let { url } = validatedData;
      if (!url.startsWith('http://') && !url.startsWith('https://')) {
        url = 'http://' + url;
      }

      // If user is authenticated but no projectId specified, use their default project
      if (req.user && !validatedData.projectId) {
        // Find user's first project (simplified for Phase 2)
        // In production, this would be more sophisticated
        const userMembership = req.user.memberships[0];
        if (userMembership) {
          // This is a simplified approach - in reality we'd query for projects
          validatedData.projectId = 'default-project'; // Placeholder
        }
      }

      // Perform tracking
      const result = await redirectTracker.trackUrl(
        { ...validatedData, url },
        req.user?.id
      );

      logger.info(`Enhanced tracking completed: ${url}`, {
        userId: req.user?.id,
        checkId: result.id,
        status: result.status,
        redirectCount: result.redirectCount
      });

      res.json({
        success: true,
        status: 200,
        data: {
          check: result,
          // Legacy compatibility fields
          url,
          method: result.method,
          redirectCount: result.redirectCount,
          finalUrl: result.finalUrl,
          finalStatusCode: result.hops[result.hops.length - 1]?.statusCode,
        },
        meta: {
          version: 'v2',
          enhanced: true,
          persisted: true,
          checkId: result.id,
        }
      });

    } catch (error) {
      logger.error('Enhanced tracking failed:', error);

      if (error instanceof z.ZodError) {
        return res.status(400).json({
          success: false,
          error: 'Validation error',
          message: error.errors[0]?.message || 'Invalid input',
          details: error.errors
        });
      }

      res.status(500).json({
        success: false,
        error: 'Tracking failed',
        message: error instanceof Error ? error.message : 'Unknown error occurred'
      });
    }
  }
);

/**
 * GET /api/v2/track/:checkId
 * Retrieve a specific check by ID
 */
router.get('/track/:checkId', 
  optionalAuth, 
  async (req: AuthenticatedRequest, res) => {
    try {
      const { checkId } = req.params;

      if (!checkId) {
        return res.status(400).json({
          success: false,
          error: 'Check ID required'
        });
      }

      const check = await redirectTracker.getCheck(checkId, req.user?.id);

      if (!check) {
        return res.status(404).json({
          success: false,
          error: 'Check not found',
          message: 'The requested check does not exist or you do not have access to it'
        });
      }

      res.json({
        success: true,
        status: 200,
        data: { check },
        meta: {
          version: 'v2',
          checkId: check.id,
        }
      });

    } catch (error) {
      logger.error('Failed to retrieve check:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to retrieve check',
        message: error instanceof Error ? error.message : 'Unknown error occurred'
      });
    }
  }
);

/**
 * GET /api/v2/projects/:projectId/checks
 * List checks for a project
 */
router.get('/projects/:projectId/checks', 
  requireAuth, 
  async (req: AuthenticatedRequest, res) => {
    try {
      const { projectId } = req.params;
      const { limit = 50, offset = 0 } = req.query;

      const validatedData = listChecksSchema.parse({
        projectId,
        limit: Number(limit),
        offset: Number(offset),
      });

      // TODO: Add proper project access checking in future phases
      // For now, basic validation
      if (!projectId) {
        return res.status(400).json({
          success: false,
          error: 'Project ID required'
        });
      }

      const checks = await redirectTracker.listChecks(
        validatedData.projectId,
        validatedData.limit,
        validatedData.offset
      );

      res.json({
        success: true,
        status: 200,
        data: {
          checks,
          pagination: {
            limit: validatedData.limit,
            offset: validatedData.offset,
            total: checks.length, // Simplified for Phase 2
          }
        },
        meta: {
          version: 'v2',
          projectId: validatedData.projectId,
        }
      });

    } catch (error) {
      logger.error('Failed to list checks:', error);

      if (error instanceof z.ZodError) {
        return res.status(400).json({
          success: false,
          error: 'Validation error',
          message: error.errors[0]?.message || 'Invalid input',
          details: error.errors
        });
      }

      res.status(500).json({
        success: false,
        error: 'Failed to list checks',
        message: error instanceof Error ? error.message : 'Unknown error occurred'
      });
    }
  }
);

/**
 * GET /api/v2/checks/recent
 * Get recent checks for authenticated user (across all their projects)
 */
router.get('/checks/recent', 
  requireAuth, 
  async (req: AuthenticatedRequest, res) => {
    try {
      const { limit = 20 } = req.query;

      // TODO: Implement cross-project recent checks in future phases
      // For Phase 2, return checks from anonymous project as placeholder
      const checks = await redirectTracker.listChecks(
        'anonymous-project',
        Number(limit),
        0
      );

      res.json({
        success: true,
        status: 200,
        data: {
          checks,
          message: 'Cross-project recent checks will be implemented in a future phase'
        },
        meta: {
          version: 'v2',
          userId: req.user!.id,
        }
      });

    } catch (error) {
      logger.error('Failed to get recent checks:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to get recent checks',
        message: error instanceof Error ? error.message : 'Unknown error occurred'
      });
    }
  }
);

/**
 * POST /api/v2/track/bulk
 * Bulk URL tracking (placeholder for Phase 6)
 */
router.post('/track/bulk', 
  requireAuth, 
  async (req: AuthenticatedRequest, res) => {
    try {
      // Placeholder implementation
      logger.info(`Bulk tracking request from user: ${req.user!.email}`);

      res.json({
        success: true,
        status: 200,
        data: {
          message: 'Bulk tracking will be implemented in Phase 6',
          bulkJobId: null,
        },
        meta: {
          version: 'v2',
          feature: 'bulk-tracking',
          phase: '6 (future)',
        }
      });

    } catch (error) {
      logger.error('Bulk tracking placeholder error:', error);
      res.status(500).json({
        success: false,
        error: 'Bulk tracking not yet available',
        message: 'This feature will be implemented in Phase 6'
      });
    }
  }
);

export default router;
