import winston from 'winston';
import { captureException, captureMessage, addBreadcrumb } from './sentry';

// Define log levels
const logLevels = {
  error: 0,
  warn: 1,
  info: 2,
  http: 3,
  debug: 4,
};

// Define log colors
const logColors = {
  error: 'red',
  warn: 'yellow',
  info: 'green',
  http: 'magenta',
  debug: 'white',
};

// Add colors to winston
winston.addColors(logColors);

// Define log format
const logFormat = winston.format.combine(
  winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms' }),
  winston.format.colorize({ all: true }),
  winston.format.printf(
    (info) => `${info.timestamp} ${info.level}: ${info.message}`
  ),
);

// Define transports
const transports = [
  // Console transport
  new winston.transports.Console({
    format: logFormat,
  }),
  
  // Error log file
  new winston.transports.File({
    filename: 'logs/error.log',
    level: 'error',
    format: winston.format.combine(
      winston.format.timestamp(),
      winston.format.json()
    ),
  }),
  
  // Combined log file
  new winston.transports.File({
    filename: 'logs/combined.log',
    format: winston.format.combine(
      winston.format.timestamp(),
      winston.format.json()
    ),
  }),
];

// Create logger instance
const logger = winston.createLogger({
  level: process.env.NODE_ENV === 'development' ? 'debug' : 'info',
  levels: logLevels,
  transports,
});

// Security event logging
export interface SecurityEvent {
  type: 'auth_failure' | 'rate_limit' | 'suspicious_activity' | 'access_denied' | 'data_breach';
  userId?: string;
  ipAddress?: string;
  userAgent?: string;
  details?: Record<string, any>;
  severity: 'low' | 'medium' | 'high' | 'critical';
}

export function logSecurityEvent(event: SecurityEvent) {
  logger.warn('SECURITY_EVENT', {
    type: event.type,
    userId: event.userId,
    ipAddress: event.ipAddress,
    userAgent: event.userAgent,
    severity: event.severity,
    details: event.details,
    timestamp: new Date().toISOString(),
  });
  
  // In production, you might also send this to a security monitoring service
  if (event.severity === 'critical') {
    logger.error('CRITICAL_SECURITY_EVENT', event);
    // TODO: Send alert to security team
  }
}

// API request logging
export interface APILogEntry {
  method: string;
  url: string;
  statusCode: number;
  responseTime: number;
  userId?: string;
  ipAddress?: string;
  userAgent?: string;
  error?: string;
}

export function logAPIRequest(entry: APILogEntry) {
  const level = entry.statusCode >= 500 ? 'error' : 
               entry.statusCode >= 400 ? 'warn' : 'info';
  
  logger.log(level, 'API_REQUEST', {
    method: entry.method,
    url: entry.url,
    statusCode: entry.statusCode,
    responseTime: entry.responseTime,
    userId: entry.userId,
    ipAddress: entry.ipAddress,
    userAgent: entry.userAgent,
    error: entry.error,
    timestamp: new Date().toISOString(),
  });
}

// Payment event logging
export interface PaymentEvent {
  type: 'payment_started' | 'payment_completed' | 'payment_failed' | 'refund_requested' | 'refund_completed';
  userId?: string;
  amount: number;
  currency: string;
  paymentIntentId?: string;
  eventId?: string;
  error?: string;
}

export function logPaymentEvent(event: PaymentEvent) {
  const level = event.type.includes('failed') ? 'error' : 'info';
  
  logger.log(level, 'PAYMENT_EVENT', {
    type: event.type,
    userId: event.userId,
    amount: event.amount,
    currency: event.currency,
    paymentIntentId: event.paymentIntentId,
    eventId: event.eventId,
    error: event.error,
    timestamp: new Date().toISOString(),
  });
}

// User activity logging
export interface UserActivity {
  action: string;
  userId: string;
  resourceType?: string;
  resourceId?: string;
  ipAddress?: string;
  userAgent?: string;
  details?: Record<string, any>;
}

export function logUserActivity(activity: UserActivity) {
  logger.info('USER_ACTIVITY', {
    action: activity.action,
    userId: activity.userId,
    resourceType: activity.resourceType,
    resourceId: activity.resourceId,
    ipAddress: activity.ipAddress,
    userAgent: activity.userAgent,
    details: activity.details,
    timestamp: new Date().toISOString(),
  });
}

// Error logging with context
export interface ErrorContext {
  userId?: string;
  ipAddress?: string;
  userAgent?: string;
  requestId?: string;
  additionalContext?: Record<string, any>;
}

export function logError(error: Error, context?: ErrorContext) {
  logger.error('APPLICATION_ERROR', {
    message: error.message,
    stack: error.stack,
    name: error.name,
    userId: context?.userId,
    ipAddress: context?.ipAddress,
    userAgent: context?.userAgent,
    requestId: context?.requestId,
    additionalContext: context?.additionalContext,
    timestamp: new Date().toISOString(),
  });

  // Also send to Sentry
  captureException(error, {
    userId: context?.userId,
    userEmail: context?.userAgent, // We don't have email in context, would need to be added
    requestId: context?.requestId,
    additionalData: {
      ipAddress: context?.ipAddress,
      userAgent: context?.userAgent,
      ...context?.additionalContext
    }
  });
}

// Performance logging
export interface PerformanceMetrics {
  operation: string;
  duration: number;
  userId?: string;
  additionalMetrics?: Record<string, number>;
}

export function logPerformance(metrics: PerformanceMetrics) {
  logger.info('PERFORMANCE_METRICS', {
    operation: metrics.operation,
    duration: metrics.duration,
    userId: metrics.userId,
    additionalMetrics: metrics.additionalMetrics,
    timestamp: new Date().toISOString(),
  });
}

// Business metrics logging
export interface BusinessMetrics {
  metric: string;
  value: number;
  tags?: Record<string, string>;
}

export function logBusinessMetrics(metrics: BusinessMetrics) {
  logger.info('BUSINESS_METRICS', {
    metric: metrics.metric,
    value: metrics.value,
    tags: metrics.tags,
    timestamp: new Date().toISOString(),
  });
}

// Audit trail logging
export interface AuditEvent {
  action: string;
  userId: string;
  resourceType: string;
  resourceId: string;
  oldValues?: Record<string, any>;
  newValues?: Record<string, any>;
  ipAddress?: string;
  userAgent?: string;
}

export function logAuditEvent(event: AuditEvent) {
  logger.info('AUDIT_TRAIL', {
    action: event.action,
    userId: event.userId,
    resourceType: event.resourceType,
    resourceId: event.resourceId,
    oldValues: event.oldValues,
    newValues: event.newValues,
    ipAddress: event.ipAddress,
    userAgent: event.userAgent,
    timestamp: new Date().toISOString(),
  });
  
  // Also log to database for compliance
  // This would integrate with your audit_logs table
}

// Export the main logger instance
export default logger;