/**
 * Sentry Utilities for Quote2Contract
 * Provides error tracking, performance monitoring, and user feedback
 */

import * as Sentry from '@sentry/nextjs';

/**
 * Initialize Sentry with user context
 */
export function setSentryUser(user: { id: string; email?: string; name?: string }) {
  Sentry.setUser({
    id: user.id,
    email: user.email,
    username: user.name,
  });
}

/**
 * Clear Sentry user context (on logout)
 */
export function clearSentryUser() {
  Sentry.setUser(null);
}

/**
 * Add breadcrumb for tracking user actions
 */
export function addBreadcrumb(message: string, category: string, data?: Record<string, any>) {
  Sentry.addBreadcrumb({
    message,
    category,
    level: 'info',
    data,
  });
}

/**
 * Capture exception with context
 */
export function captureException(error: Error, context?: Record<string, any>) {
  Sentry.captureException(error, {
    extra: context,
  });
}

/**
 * Capture message (for non-error events)
 */
export function captureMessage(message: string, level: 'info' | 'warning' | 'error' = 'info') {
  Sentry.captureMessage(message, level);
}

/**
 * Set context tags for filtering in Sentry
 */
export function setTags(tags: Record<string, string>) {
  Sentry.setTags(tags);
}

/**
 * Start a span for performance monitoring
 */
export function startSpan(name: string, op: string) {
  return Sentry.startSpan({
    name,
    op,
  }, (span) => span);
}

/**
 * Track API performance
 */
export async function trackAPICall<T>(
  name: string,
  apiCall: () => Promise<T>
): Promise<T> {
  return Sentry.startSpan({
    name: `API: ${name}`,
    op: 'http.client',
  }, async (span) => {
    try {
      const result = await apiCall();
      span.setStatus({ code: 1 }); // OK
      return result;
    } catch (error) {
      span.setStatus({ code: 2 }); // ERROR
      Sentry.captureException(error);
      throw error;
    }
  });
}

/**
 * Track database query performance
 */
export async function trackDatabaseQuery<T>(
  query: string,
  dbCall: () => Promise<T>
): Promise<T> {
  const span = Sentry.startSpan({
    name: query,
    op: 'db.query',
  }, async (span) => {
    try {
      const result = await dbCall();
      span.setStatus({ code: 1 });
      return result;
    } catch (error) {
      span.setStatus({ code: 2 });
      throw error;
    }
  });

  return span;
}

/**
 * Custom error classes for better error tracking
 */
export class ValidationError extends Error {
  constructor(message: string, public field?: string) {
    super(message);
    this.name = 'ValidationError';
  }
}

export class AuthenticationError extends Error {
  constructor(message: string = 'Authentication required') {
    super(message);
    this.name = 'AuthenticationError';
  }
}

export class AuthorizationError extends Error {
  constructor(message: string = 'Insufficient permissions') {
    super(message);
    this.name = 'AuthorizationError';
  }
}

export class NotFoundError extends Error {
  constructor(resource: string) {
    super(`${resource} not found`);
    this.name = 'NotFoundError';
  }
}

export class RateLimitError extends Error {
  constructor(message: string = 'Rate limit exceeded') {
    super(message);
    this.name = 'RateLimitError';
  }
}

/**
 * Error reporter with automatic Sentry integration
 */
export class ErrorReporter {
  static report(error: Error, context?: Record<string, any>) {
    // Log to console in development
    if (process.env.NODE_ENV === 'development') {
      console.error('Error:', error);
      if (context) {
        console.error('Context:', context);
      }
    }

    // Send to Sentry
    Sentry.captureException(error, {
      extra: context,
      tags: {
        errorType: error.name,
      },
    });
  }

  static reportMessage(message: string, level: 'info' | 'warning' | 'error' = 'info') {
    if (process.env.NODE_ENV === 'development') {
      console.log(`[${level.toUpperCase()}]`, message);
    }

    Sentry.captureMessage(message, level);
  }
}

/**
 * Initialize Sentry for the application
 */
export function initializeSentry() {
  if (!process.env.NEXT_PUBLIC_SENTRY_DSN) {
    console.warn('Sentry DSN not configured. Error tracking disabled.');
    return;
  }

  console.log('Sentry initialized successfully');
}
