import { Request, Response, NextFunction } from 'express';
import { storage } from './storage';
import crypto from 'crypto';

export interface ApiAuthRequest extends Request {
  apiKey?: {
    id: number;
    name: string;
    permissions: string[];
  };
}

export function generateApiKey(): { key: string; hash: string; preview: string } {
  // Generate a 32-byte random key and encode as base64
  const key = crypto.randomBytes(32).toString('base64url');
  
  // Create SHA-256 hash for storage
  const hash = crypto.createHash('sha256').update(key).digest('hex');
  
  // Create preview (first 8 chars + "...")
  const preview = key.substring(0, 8) + '...';
  
  return { key, hash, preview };
}

export async function requireApiKey(permissions: string[] = []) {
  return async (req: ApiAuthRequest, res: Response, next: NextFunction) => {
    try {
      const authHeader = req.headers.authorization;
      
      if (!authHeader || !authHeader.startsWith('Bearer ')) {
        return res.status(401).json({ 
          error: 'API key required. Provide API key in Authorization header as "Bearer YOUR_KEY"' 
        });
      }
      
      const apiKey = authHeader.substring(7); // Remove "Bearer " prefix
      
      if (!apiKey) {
        return res.status(401).json({ error: 'API key not provided' });
      }
      
      // Hash the provided key to compare with stored hash
      const keyHash = crypto.createHash('sha256').update(apiKey).digest('hex');
      
      // Find the API key in database
      const storedKey = await storage.getApiKeyByHash(keyHash);
      
      if (!storedKey) {
        return res.status(401).json({ error: 'Invalid API key' });
      }
      
      if (!storedKey.isActive) {
        return res.status(401).json({ error: 'API key is disabled' });
      }
      
      // Check if key is expired
      if (storedKey.expiresAt && new Date() > storedKey.expiresAt) {
        return res.status(401).json({ error: 'API key has expired' });
      }
      
      // Check permissions
      if (permissions.length > 0) {
        const hasPermission = permissions.every(permission => 
          storedKey.permissions && storedKey.permissions.includes(permission)
        );
        
        if (!hasPermission) {
          return res.status(403).json({ error: 'Insufficient permissions' });
        }
      }
      
      // Update last used timestamp
      await storage.updateApiKeyLastUsed(storedKey.id);
      
      // Attach API key info to request
      req.apiKey = {
        id: storedKey.id,
        name: storedKey.name,
        permissions: storedKey.permissions || []
      };
      
      next();
    } catch (error) {
      console.error('API key authentication error:', error);
      return res.status(500).json({ error: 'Authentication error' });
    }
  };
}