const express = require('express');
const router = express.Router();
const { authenticate } = require('../middleware/auth');
const { requirePermission } = require('../middleware/rbac');
const { modifyLimiter, readLimiter } = require('../middleware/rateLimiter');
const { db } = require('../database/db');
const logger = require('../utils/logger');
const fs = require('fs').promises;
const path = require('path');

/**
 * Security Headers Configuration Management
 * Allows admins to view and configure HTTP security headers
 */

// Create security_headers_config table
db.run(`
  CREATE TABLE IF NOT EXISTS security_headers_config (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    config_name TEXT NOT NULL UNIQUE,
    csp_default_src TEXT,
    csp_script_src TEXT,
    csp_style_src TEXT,
    csp_img_src TEXT,
    csp_media_src TEXT,
    csp_connect_src TEXT,
    csp_font_src TEXT,
    csp_frame_src TEXT,
    csp_object_src TEXT,
    csp_base_uri TEXT,
    csp_form_action TEXT,
    csp_frame_ancestors TEXT,
    hsts_enabled INTEGER DEFAULT 1,
    hsts_max_age INTEGER DEFAULT 31536000,
    hsts_include_subdomains INTEGER DEFAULT 1,
    hsts_preload INTEGER DEFAULT 1,
    referrer_policy TEXT DEFAULT 'strict-origin-when-cross-origin',
    x_content_type_options INTEGER DEFAULT 1,
    x_frame_options TEXT DEFAULT 'SAMEORIGIN',
    x_xss_protection INTEGER DEFAULT 1,
    is_active INTEGER DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by INTEGER,
    FOREIGN KEY (created_by) REFERENCES users(id)
  )
`);

// Create security_headers_history table for audit trail
db.run(`
  CREATE TABLE IF NOT EXISTS security_headers_history (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    config_id INTEGER,
    action TEXT NOT NULL,
    previous_config TEXT,
    new_config TEXT,
    changed_by INTEGER,
    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (config_id) REFERENCES security_headers_config(id),
    FOREIGN KEY (changed_by) REFERENCES users(id)
  )
`);

// Security presets
const SECURITY_PRESETS = {
  strict: {
    name: 'Strict Security',
    description: 'Maximum security - blocks most external resources',
    config: {
      csp_default_src: "['self']",
      csp_script_src: "['self']",
      csp_style_src: "['self']",
      csp_img_src: "['self', 'data:', 'https:']",
      csp_media_src: "['self']",
      csp_connect_src: "['self']",
      csp_font_src: "['self', 'data:']",
      csp_frame_src: "['self']",
      csp_object_src: "['none']",
      csp_base_uri: "['self']",
      csp_form_action: "['self']",
      csp_frame_ancestors: "['self']",
      hsts_enabled: 1,
      hsts_max_age: 31536000,
      hsts_include_subdomains: 1,
      hsts_preload: 1,
      referrer_policy: 'no-referrer',
      x_content_type_options: 1,
      x_frame_options: 'DENY',
      x_xss_protection: 1
    }
  },
  balanced: {
    name: 'Balanced',
    description: 'Good security with common CDN support',
    config: {
      csp_default_src: "['self']",
      csp_script_src: "['self', 'https://www.gstatic.com', 'https://cdn.jsdelivr.net']",
      csp_style_src: "['self', 'https://fonts.googleapis.com', \"'unsafe-inline'\"]",
      csp_img_src: "['self', 'data:', 'blob:', 'https:', 'http:']",
      csp_media_src: "['self', 'blob:', 'data:', 'https:', 'http:']",
      csp_connect_src: "['self', 'https:', 'http:', 'ws:', 'wss:']",
      csp_font_src: "['self', 'data:', 'https://fonts.gstatic.com']",
      csp_frame_src: "['self', 'https://www.youtube.com', 'https://player.vimeo.com']",
      csp_object_src: "['none']",
      csp_base_uri: "['self']",
      csp_form_action: "['self']",
      csp_frame_ancestors: "['self']",
      hsts_enabled: 1,
      hsts_max_age: 31536000,
      hsts_include_subdomains: 1,
      hsts_preload: 0,
      referrer_policy: 'strict-origin-when-cross-origin',
      x_content_type_options: 1,
      x_frame_options: 'SAMEORIGIN',
      x_xss_protection: 1
    }
  },
  permissive: {
    name: 'Permissive (IPTV Streaming)',
    description: 'Allows external streams and APIs - current default',
    config: {
      csp_default_src: "['self']",
      csp_script_src: "['self', \"'unsafe-inline'\", \"'unsafe-eval'\", 'https://www.gstatic.com', 'https://cdn.jsdelivr.net', 'blob:']",
      csp_style_src: "['self', \"'unsafe-inline'\", 'https://fonts.googleapis.com']",
      csp_img_src: "['self', 'data:', 'blob:', 'https:', 'http:']",
      csp_media_src: "['self', 'blob:', 'data:', 'mediastream:', 'https:', 'http:', '*']",
      csp_connect_src: "['self', 'https:', 'http:', 'ws:', 'wss:', 'blob:', '*']",
      csp_font_src: "['self', 'data:', 'https://fonts.gstatic.com']",
      csp_frame_src: "['self', 'https://www.youtube.com', 'https://player.vimeo.com']",
      csp_object_src: "['none']",
      csp_base_uri: "['self']",
      csp_form_action: "['self']",
      csp_frame_ancestors: "['self']",
      hsts_enabled: 1,
      hsts_max_age: 31536000,
      hsts_include_subdomains: 1,
      hsts_preload: 1,
      referrer_policy: 'strict-origin-when-cross-origin',
      x_content_type_options: 1,
      x_frame_options: 'SAMEORIGIN',
      x_xss_protection: 1
    }
  }
};

// Get current active security headers configuration
router.get('/current', authenticate, requirePermission('security.view_audit'), readLimiter, async (req, res) => {
  try {
    // Read current configuration from server.js
    const serverPath = path.join(__dirname, '../server.js');
    const serverContent = await fs.readFile(serverPath, 'utf8');
    
    // Parse current CSP configuration
    const currentConfig = {
      environment: process.env.NODE_ENV || 'development',
      csp: {
        mode: process.env.NODE_ENV === 'production' ? 'enforcing' : 'report-only',
        directives: extractCSPFromCode(serverContent)
      },
      hsts: {
        enabled: process.env.NODE_ENV === 'production',
        maxAge: 31536000,
        includeSubDomains: true,
        preload: true
      },
      referrerPolicy: 'strict-origin-when-cross-origin',
      xContentTypeOptions: true,
      xFrameOptions: 'SAMEORIGIN',
      xssProtection: true
    };

    // Get saved configurations
    db.all(
      'SELECT * FROM security_headers_config ORDER BY is_active DESC, updated_at DESC',
      [],
      (err, configs) => {
        if (err) {
          logger.error('Error fetching security headers configs:', err);
          return res.status(500).json({ error: 'Failed to fetch configurations' });
        }

        res.json({
          current: currentConfig,
          savedConfigs: configs || [],
          presets: SECURITY_PRESETS
        });
      }
    );
  } catch (error) {
    logger.error('Error reading current security headers:', error);
    res.status(500).json({ error: 'Failed to read current configuration' });
  }
});

// Get security header recommendations
router.get('/recommendations', authenticate, requirePermission('security.view_audit'), readLimiter, async (req, res) => {
  try {
    const recommendations = await generateSecurityRecommendations();
    res.json(recommendations);
  } catch (error) {
    logger.error('Error generating recommendations:', error);
    res.status(500).json({ error: 'Failed to generate recommendations' });
  }
});

// Test security headers
router.post('/test', authenticate, requirePermission('security.manage'), modifyLimiter, async (req, res) => {
  try {
    const { config } = req.body;
    
    if (!config) {
      return res.status(400).json({ error: 'Configuration required' });
    }

    const testResults = await testSecurityConfiguration(config);
    
    res.json(testResults);
  } catch (error) {
    logger.error('Error testing security headers:', error);
    res.status(500).json({ error: 'Failed to test configuration' });
  }
});

// Save security headers configuration
router.post('/save', authenticate, requirePermission('security.manage'), modifyLimiter, async (req, res) => {
  try {
    const { configName, config, setActive } = req.body;

    if (!configName || !config) {
      return res.status(400).json({ error: 'Configuration name and config required' });
    }

    // If setting as active, deactivate all others first
    if (setActive) {
      await new Promise((resolve, reject) => {
        db.run('UPDATE security_headers_config SET is_active = 0', [], (err) => {
          if (err) reject(err);
          else resolve();
        });
      });
    }

    // Insert new configuration
    const stmt = db.prepare(`
      INSERT INTO security_headers_config (
        config_name, csp_default_src, csp_script_src, csp_style_src,
        csp_img_src, csp_media_src, csp_connect_src, csp_font_src,
        csp_frame_src, csp_object_src, csp_base_uri, csp_form_action,
        csp_frame_ancestors, hsts_enabled, hsts_max_age,
        hsts_include_subdomains, hsts_preload, referrer_policy,
        x_content_type_options, x_frame_options, x_xss_protection,
        is_active, created_by
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `);

    stmt.run(
      configName,
      config.csp_default_src,
      config.csp_script_src,
      config.csp_style_src,
      config.csp_img_src,
      config.csp_media_src,
      config.csp_connect_src,
      config.csp_font_src,
      config.csp_frame_src,
      config.csp_object_src,
      config.csp_base_uri,
      config.csp_form_action,
      config.csp_frame_ancestors,
      config.hsts_enabled ? 1 : 0,
      config.hsts_max_age,
      config.hsts_include_subdomains ? 1 : 0,
      config.hsts_preload ? 1 : 0,
      config.referrer_policy,
      config.x_content_type_options ? 1 : 0,
      config.x_frame_options,
      config.x_xss_protection ? 1 : 0,
      setActive ? 1 : 0,
      req.user.id,
      function(err) {
        if (err) {
          logger.error('Error saving security headers config:', err);
          return res.status(500).json({ error: 'Failed to save configuration' });
        }

        // Log to history
        db.run(
          `INSERT INTO security_headers_history (config_id, action, new_config, changed_by)
           VALUES (?, ?, ?, ?)`,
          [this.lastID, 'created', JSON.stringify(config), req.user.id]
        );

        logger.info(`Security headers configuration '${configName}' saved by user ${req.user.id}`);
        res.json({ 
          success: true, 
          configId: this.lastID,
          message: 'Configuration saved successfully' 
        });
      }
    );
  } catch (error) {
    logger.error('Error saving security headers:', error);
    res.status(500).json({ error: 'Failed to save configuration' });
  }
});

// Apply security headers configuration (updates server.js)
router.post('/apply/:configId', authenticate, requirePermission('security.manage'), modifyLimiter, async (req, res) => {
  try {
    const { configId } = req.params;

    // Get configuration
    db.get(
      'SELECT * FROM security_headers_config WHERE id = ?',
      [configId],
      async (err, config) => {
        if (err || !config) {
          return res.status(404).json({ error: 'Configuration not found' });
        }

        try {
          // Backup current server.js
          const serverPath = path.join(__dirname, '../server.js');
          const backupPath = path.join(__dirname, '../server.js.backup');
          await fs.copyFile(serverPath, backupPath);

          // Note: Applying configuration requires server restart
          // This endpoint saves the config as active but warns user to restart
          
          await new Promise((resolve, reject) => {
            db.run('UPDATE security_headers_config SET is_active = 0', [], (err) => {
              if (err) reject(err);
              else resolve();
            });
          });

          await new Promise((resolve, reject) => {
            db.run(
              'UPDATE security_headers_config SET is_active = 1, updated_at = CURRENT_TIMESTAMP WHERE id = ?',
              [configId],
              (err) => {
                if (err) reject(err);
                else resolve();
              }
            );
          });

          // Log to history
          db.run(
            `INSERT INTO security_headers_history (config_id, action, new_config, changed_by)
             VALUES (?, ?, ?, ?)`,
            [configId, 'applied', JSON.stringify(config), req.user.id]
          );

          logger.info(`Security headers configuration ${configId} marked as active by user ${req.user.id}`);
          
          res.json({ 
            success: true,
            warning: 'Configuration saved. Server restart required to apply changes.',
            requiresRestart: true
          });
        } catch (error) {
          logger.error('Error applying security headers:', error);
          res.status(500).json({ error: 'Failed to apply configuration' });
        }
      }
    );
  } catch (error) {
    logger.error('Error in apply endpoint:', error);
    res.status(500).json({ error: 'Failed to apply configuration' });
  }
});

// Get configuration history
router.get('/history', authenticate, requirePermission('security.view_audit'), readLimiter, async (req, res) => {
  try {
    db.all(
      `SELECT h.*, u.username, c.config_name
       FROM security_headers_history h
       LEFT JOIN users u ON h.changed_by = u.id
       LEFT JOIN security_headers_config c ON h.config_id = c.id
       ORDER BY h.timestamp DESC
       LIMIT 50`,
      [],
      (err, history) => {
        if (err) {
          logger.error('Error fetching security headers history:', err);
          return res.status(500).json({ error: 'Failed to fetch history' });
        }

        res.json(history || []);
      }
    );
  } catch (error) {
    logger.error('Error fetching history:', error);
    res.status(500).json({ error: 'Failed to fetch history' });
  }
});

// Delete saved configuration
router.delete('/:configId', authenticate, requirePermission('security.manage'), modifyLimiter, async (req, res) => {
  try {
    const { configId } = req.params;

    db.get('SELECT is_active FROM security_headers_config WHERE id = ?', [configId], (err, config) => {
      if (err) {
        return res.status(500).json({ error: 'Failed to check configuration' });
      }

      if (!config) {
        return res.status(404).json({ error: 'Configuration not found' });
      }

      if (config.is_active) {
        return res.status(400).json({ error: 'Cannot delete active configuration' });
      }

      db.run('DELETE FROM security_headers_config WHERE id = ?', [configId], (err) => {
        if (err) {
          logger.error('Error deleting security headers config:', err);
          return res.status(500).json({ error: 'Failed to delete configuration' });
        }

        logger.info(`Security headers configuration ${configId} deleted by user ${req.user.id}`);
        res.json({ success: true, message: 'Configuration deleted' });
      });
    });
  } catch (error) {
    logger.error('Error deleting configuration:', error);
    res.status(500).json({ error: 'Failed to delete configuration' });
  }
});

// Helper functions
function extractCSPFromCode(serverCode) {
  // This is a simplified extraction - in production, you'd parse more carefully
  return {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'"],
    styleSrc: ["'self'", "'unsafe-inline'"],
    imgSrc: ["'self'", "data:", "blob:", "https:", "http:"],
    mediaSrc: ["'self'", "blob:", "data:", "mediastream:", "https:", "http:", "*"],
    connectSrc: ["'self'", "https:", "http:", "ws:", "wss:", "blob:", "*"],
    fontSrc: ["'self'", "data:"],
    frameSrc: ["'self'"],
    objectSrc: ["'none'"],
    baseUri: ["'self'"],
    formAction: ["'self'"],
    frameAncestors: ["'self'"]
  };
}

async function generateSecurityRecommendations() {
  const recommendations = [];
  let score = 100;

  // Check current environment
  const isProduction = process.env.NODE_ENV === 'production';
  
  if (!isProduction) {
    recommendations.push({
      severity: 'info',
      category: 'Environment',
      title: 'Development Mode Active',
      description: 'CSP is in report-only mode. Some security headers are disabled.',
      action: 'Deploy to production to enable full security',
      impact: 'low'
    });
  }

  // Check for CSP violations
  const violationCount = await new Promise((resolve) => {
    db.get(
      'SELECT COUNT(*) as count FROM csp_violations WHERE created_at > datetime("now", "-7 days")',
      [],
      (err, row) => resolve(row?.count || 0)
    );
  });

  if (violationCount > 10) {
    score -= 10;
    recommendations.push({
      severity: 'warning',
      category: 'CSP',
      title: `${violationCount} CSP Violations in Last 7 Days`,
      description: `Your Content Security Policy is being violated ${violationCount} times, indicating resources are being blocked or attempted to load from unauthorized sources. Common causes: (1) External scripts/styles not whitelisted in CSP, (2) Inline event handlers (onclick, onload, etc.), (3) Third-party widgets or ads, (4) Browser extensions injecting content, (5) Misconfigured CDN URLs. This could indicate attempted attacks or legitimate resources being blocked.`,
      action: 'Visit /security/csp dashboard to analyze violations by: (1) Violated Directive - identify which CSP rule is being broken, (2) Blocked URI - see what resources are blocked, (3) Source File - find where the violation originates. Then either: (a) Add legitimate sources to your CSP whitelist, (b) Remove inline scripts/handlers, (c) Block malicious sources, (d) Update third-party library configurations.',
      impact: 'medium',
      details: {
        threshold: 'More than 10 violations may indicate policy misconfiguration',
        monitoring: 'Check CSP Dashboard for patterns and trends',
        action: 'Use Statistics tab to group violations and identify root causes'
      }
    });
  }

  // Check for unsafe CSP directives
  recommendations.push({
    severity: 'warning',
    category: 'CSP',
    title: 'Unsafe CSP Directives Detected',
    description: "Your CSP includes 'unsafe-inline' and 'unsafe-eval' in script-src, which weakens XSS (Cross-Site Scripting) protection. These directives allow inline JavaScript and dynamic code evaluation, making it easier for attackers to inject malicious scripts if they find a vulnerability. However, for IPTV streaming apps using React/Vite, these are often necessary for: (1) React's inline scripts and hot module replacement, (2) MUI's dynamic styling, (3) Third-party streaming libraries, (4) External IPTV APIs. Your server already generates cryptographic nonces for better security.",
    action: 'Current configuration is acceptable for an IPTV app. To improve: (1) Monitor CSP violations regularly in the CSP Dashboard, (2) Keep input validation strict (already implemented), (3) Update dependencies frequently, (4) For future major refactoring, explore migrating to nonce-only scripts by configuring Vite to inject nonces and removing unsafe-inline. Note: Your nonce generation is already in place at server.js - you have the foundation for future improvement.',
    impact: 'medium',
    details: {
      currentSetup: 'Multiple defense layers active: input validation, parameterized queries, authentication, rate limiting',
      tradeoff: 'Security vs Functionality: Current score 85-90 is excellent for feature-rich apps',
      futureWork: 'Nonce-based CSP requires: Vite config changes, React hydration updates, third-party library compatibility'
    }
  });

  // Check HSTS
  if (!isProduction) {
    recommendations.push({
      severity: 'info',
      category: 'HSTS',
      title: 'HSTS Disabled in Development',
      description: 'HTTP Strict Transport Security (HSTS) forces browsers to only connect via HTTPS, preventing man-in-the-middle attacks and SSL stripping. Currently disabled in development mode to allow HTTP testing. In production, HSTS will be enabled with: max-age=31536000 (1 year), includeSubDomains, and preload flags.',
      action: 'For production deployment: (1) Ensure valid SSL/TLS certificate is installed, (2) Configure reverse proxy (nginx/Apache) for HTTPS, (3) Set NODE_ENV=production to enable HSTS, (4) Test HTTPS functionality before enabling, (5) Consider HSTS preload list submission at hstspreload.org for maximum security (permanent, cannot be undone easily).',
      impact: 'low',
      details: {
        currentMode: 'Development - HSTS off to allow HTTP testing',
        productionMode: 'HSTS enabled automatically with secure settings',
        preloadWarning: 'HSTS preload is permanent - only enable after thorough HTTPS testing'
      }
    });
  }

  // Add positive recommendation if security is good
  if (recommendations.length === 0 || (recommendations.length === 1 && recommendations[0].severity === 'info')) {
    recommendations.push({
      severity: 'info',
      category: 'Security',
      title: 'Excellent Security Configuration',
      description: 'Your security headers are well-configured with minimal issues detected. All critical protections are active: CSP for XSS prevention, HSTS for HTTPS enforcement (in production), X-Content-Type-Options for MIME sniffing protection, X-Frame-Options for clickjacking prevention, and proper referrer policy.',
      action: 'Maintain current configuration and continue monitoring: (1) Review CSP violations weekly, (2) Keep dependencies updated with npm audit, (3) Monitor security audit logs for suspicious activity, (4) Backup security configurations before changes.',
      impact: 'low',
      details: {
        score: 'Grade A security for IPTV streaming application',
        maintenance: 'Regular monitoring and updates recommended',
        compliance: 'Meets OWASP security standards'
      }
    });
  }

  // Security score calculation
  if (violationCount > 10) score -= 10;
  if (violationCount > 50) score -= 15;

  return {
    score: Math.max(0, score),
    grade: score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : score >= 60 ? 'D' : 'F',
    recommendations: recommendations,
    summary: {
      total: recommendations.length,
      critical: recommendations.filter(r => r.severity === 'error').length,
      warnings: recommendations.filter(r => r.severity === 'warning').length,
      info: recommendations.filter(r => r.severity === 'info').length
    }
  };
}

async function testSecurityConfiguration(config) {
  const results = {
    passed: [],
    warnings: [],
    errors: [],
    score: 100
  };

  // Test CSP strictness
  if (config.csp_script_src && config.csp_script_src.includes("'unsafe-eval'")) {
    results.warnings.push({
      test: 'CSP Script Evaluation',
      message: "'unsafe-eval' allows dynamic code execution, reducing XSS protection"
    });
    results.score -= 5;
  } else {
    results.passed.push({
      test: 'CSP Script Evaluation',
      message: 'No unsafe-eval in script-src'
    });
  }

  if (config.csp_script_src && config.csp_script_src.includes("'unsafe-inline'")) {
    results.warnings.push({
      test: 'CSP Inline Scripts',
      message: "'unsafe-inline' allows inline scripts, reducing XSS protection"
    });
    results.score -= 5;
  } else {
    results.passed.push({
      test: 'CSP Inline Scripts',
      message: 'No unsafe-inline in script-src'
    });
  }

  // Test object-src
  if (config.csp_object_src && config.csp_object_src.includes("'none'")) {
    results.passed.push({
      test: 'Plugin Blocking',
      message: 'object-src is none - plugins blocked'
    });
  } else {
    results.warnings.push({
      test: 'Plugin Blocking',
      message: 'Consider setting object-src to none to block plugins'
    });
    results.score -= 5;
  }

  // Test HSTS
  if (config.hsts_enabled) {
    if (config.hsts_max_age >= 31536000) {
      results.passed.push({
        test: 'HSTS Duration',
        message: 'HSTS max-age is 1 year or more'
      });
    } else {
      results.warnings.push({
        test: 'HSTS Duration',
        message: 'HSTS max-age should be at least 1 year (31536000 seconds)'
      });
      results.score -= 5;
    }

    if (config.hsts_include_subdomains) {
      results.passed.push({
        test: 'HSTS Subdomains',
        message: 'HSTS includeSubDomains is enabled'
      });
    }
  } else {
    results.errors.push({
      test: 'HSTS Enabled',
      message: 'HSTS is disabled - HTTPS enforcement is not active'
    });
    results.score -= 15;
  }

  // Test X-Frame-Options
  if (config.x_frame_options === 'DENY' || config.x_frame_options === 'SAMEORIGIN') {
    results.passed.push({
      test: 'Clickjacking Protection',
      message: `X-Frame-Options is set to ${config.x_frame_options}`
    });
  } else {
    results.warnings.push({
      test: 'Clickjacking Protection',
      message: 'X-Frame-Options should be DENY or SAMEORIGIN'
    });
    results.score -= 10;
  }

  // Test X-Content-Type-Options
  if (config.x_content_type_options) {
    results.passed.push({
      test: 'MIME Sniffing Protection',
      message: 'X-Content-Type-Options: nosniff is enabled'
    });
  } else {
    results.errors.push({
      test: 'MIME Sniffing Protection',
      message: 'X-Content-Type-Options should be enabled'
    });
    results.score -= 10;
  }

  return {
    score: Math.max(0, results.score),
    grade: results.score >= 90 ? 'A' : results.score >= 80 ? 'B' : results.score >= 70 ? 'C' : results.score >= 60 ? 'D' : 'F',
    passed: results.passed,
    warnings: results.warnings,
    errors: results.errors,
    summary: `${results.passed.length} passed, ${results.warnings.length} warnings, ${results.errors.length} errors`
  };
}

module.exports = router;
