/**
 * State Middleware
 * FE-STATE-010: Add middleware for logging, analytics, error handling
 * 
 * Provides a comprehensive middleware for Zustand stores that handles:
 * - State change logging
 * - Analytics tracking
 * - Error handling and reporting
 */

import { StateCreator } from 'zustand';
import { logger } from './logger';

/**
 * Analytics event types
 */
export type AnalyticsEventType =
  | 'state_change'
  | 'action_called'
  | 'error_occurred'
  | 'performance_metric';

/**
 * Analytics event
 */
export interface AnalyticsEvent {
  type: AnalyticsEventType;
  store: string;
  action?: string;
  timestamp: number;
  metadata?: Record<string, unknown>;
}

/**
 * Analytics handler function
 */
export type AnalyticsHandler = (event: AnalyticsEvent) => void;

/**
 * Error handler function
 */
export type ErrorHandler = (error: Error, context: {
  store: string;
  action?: string;
  state?: unknown;
}) => void;

/**
 * Options for state middleware
 */
export interface StateMiddlewareOptions {
  /** Store name for logging and analytics */
  storeName: string;
  /** Enable logging (default: true in dev, false in prod) */
  enableLogging?: boolean;
  /** Enable analytics tracking (default: true) */
  enableAnalytics?: boolean;
  /** Enable error handling (default: true) */
  enableErrorHandling?: boolean;
  /** Custom analytics handler */
  analyticsHandler?: AnalyticsHandler;
  /** Custom error handler */
  errorHandler?: ErrorHandler;
  /** Filter state changes to log (return false to skip) */
  shouldLog?: (state: unknown, prevState: unknown) => boolean;
  /** Filter actions to track (return false to skip) */
  shouldTrack?: (action: string, args: unknown[]) => boolean;
  /** Sanitize state for logging (remove sensitive data) */
  sanitizeState?: (state: unknown) => unknown;
}

/**
 * Default analytics handler (can be overridden)
 */
let defaultAnalyticsHandler: AnalyticsHandler | null = null;

/**
 * Set default analytics handler
 */
export function setAnalyticsHandler(handler: AnalyticsHandler): void {
  defaultAnalyticsHandler = handler;
}

/**
 * Default error handler (can be overridden)
 */
let defaultErrorHandler: ErrorHandler | null = null;

/**
 * Set default error handler
 */
export function setErrorHandler(handler: ErrorHandler): void {
  defaultErrorHandler = handler;
}

/**
 * Track analytics event
 */
function trackAnalytics(
  event: Omit<AnalyticsEvent, 'timestamp'>,
  handler?: AnalyticsHandler,
): void {
  const analyticsHandler = handler || defaultAnalyticsHandler;
  if (!analyticsHandler) {
    return;
  }

  try {
    analyticsHandler({
      ...event,
      timestamp: Date.now(),
    });
  } catch (error) {
    logger.error('[StateMiddleware] Analytics tracking failed:', error);
  }
}

/**
 * Handle error
 */
function handleError(
  error: Error,
  context: {
    store: string;
    action?: string;
    state?: unknown;
  },
  handler?: ErrorHandler,
): void {
  const errorHandler = handler || defaultErrorHandler;
  
  // Always log errors
  logger.error(`[StateMiddleware] Error in ${context.store}:`, {
    error: error.message,
    stack: error.stack,
    action: context.action,
    context,
  });

  // Call custom error handler if provided
  if (errorHandler) {
    try {
      errorHandler(error, context);
    } catch (handlerError) {
      logger.error('[StateMiddleware] Error handler failed:', handlerError);
    }
  }

  // Track error analytics (use default handler, not error handler)
  trackAnalytics(
    {
      type: 'error_occurred',
      store: context.store,
      action: context.action,
      metadata: {
        error: error.message,
        errorName: error.name,
      },
    },
  );
}

/**
 * Sanitize state for logging (remove sensitive data)
 */
function sanitizeState(state: unknown, customSanitize?: (state: unknown) => unknown): unknown {
  if (customSanitize) {
    return customSanitize(state);
  }

  // Default sanitization: remove common sensitive fields
  if (typeof state === 'object' && state !== null) {
    const sanitized = { ...state as Record<string, unknown> };
    const sensitiveKeys = ['password', 'token', 'secret', 'apiKey', 'accessToken', 'refreshToken'];
    
    for (const key of sensitiveKeys) {
      if (key in sanitized) {
        sanitized[key] = '[REDACTED]';
      }
    }
    
    return sanitized;
  }

  return state;
}

/**
 * Zustand middleware for logging, analytics, and error handling
 * 
 * @example
 * ```typescript
 * export const useMyStore = create<MyState>()(
 *   stateMiddleware(
 *     (set, get) => ({
 *       // store implementation
 *     }),
 *     { storeName: 'MyStore' }
 *   )
 * );
 * ```
 */
export function stateMiddleware<T extends object>(
  config: StateCreator<T>,
  options: StateMiddlewareOptions,
): StateCreator<T> {
  const {
    storeName,
    enableLogging = import.meta.env.DEV,
    enableAnalytics = true,
    enableErrorHandling = true,
    analyticsHandler,
    errorHandler,
    shouldLog = () => true,
    shouldTrack = () => true,
    sanitizeState: customSanitize,
  } = options;

  return (set, get, api) => {
    let previousState: T | null = null;
    let actionCallCount = 0;

    // Wrap set function to intercept state changes
    const wrappedSet: typeof set = (...args) => {
      const currentState = get();
      
      // Log state changes
      if (enableLogging && shouldLog(currentState, previousState)) {
        const sanitizedCurrent = sanitizeState(currentState, customSanitize);
        const sanitizedPrevious = sanitizeState(previousState, customSanitize);
        
        logger.debug(`[StateMiddleware:${storeName}] State change:`, {
          previous: sanitizedPrevious,
          current: sanitizedCurrent,
        });
      }

      // Track analytics
      if (enableAnalytics) {
        trackAnalytics(
          {
            type: 'state_change',
            store: storeName,
            metadata: {
              hasPreviousState: previousState !== null,
            },
          },
          analyticsHandler,
        );
      }

      // Call original set
      try {
        set(...args);
        previousState = get();
      } catch (error) {
        if (enableErrorHandling) {
          handleError(
            error instanceof Error ? error : new Error(String(error)),
            {
              store: storeName,
              state: currentState,
            },
            errorHandler,
          );
        }
        throw error;
      }
    };

    // Create store with wrapped set
    const store = config(wrappedSet, get, api);

    // Wrap store actions to track calls
    if (enableAnalytics || enableLogging) {
      const wrappedStore = { ...store } as Record<string, unknown>;
      
      // Wrap all functions in the store
      for (const [key, value] of Object.entries(wrappedStore)) {
        if (typeof value === 'function' && key !== 'setState') {
          const originalAction = value as (...args: unknown[]) => unknown;
          
          wrappedStore[key] = ((...args: unknown[]) => {
            actionCallCount++;
            const startTime = performance.now();

            // Track action call
            if (enableAnalytics && shouldTrack(key, args)) {
              trackAnalytics(
                {
                  type: 'action_called',
                  store: storeName,
                  action: key,
                  metadata: {
                    callCount: actionCallCount,
                    argsCount: args.length,
                  },
                },
                analyticsHandler,
              );
            }

            // Log action call
            if (enableLogging) {
              logger.debug(`[StateMiddleware:${storeName}] Action called: ${key}`, {
                args: args.length > 0 ? args : undefined,
              });
            }

            try {
              const result = originalAction(...args);
              
              // Track performance if it's a promise
              if (result instanceof Promise) {
                const endTime = performance.now();
                const duration = endTime - startTime;
                
                if (enableAnalytics) {
                  trackAnalytics(
                    {
                      type: 'performance_metric',
                      store: storeName,
                      action: key,
                      metadata: {
                        duration,
                        isAsync: true,
                      },
                    },
                    analyticsHandler,
                  );
                }

                // Handle promise errors
                if (enableErrorHandling) {
                  result.catch((error) => {
                    handleError(
                      error instanceof Error ? error : new Error(String(error)),
                      {
                        store: storeName,
                        action: key,
                        state: get(),
                      },
                      errorHandler,
                    );
                  });
                }
              } else {
                // Track synchronous action performance
                const endTime = performance.now();
                const duration = endTime - startTime;
                
                if (enableAnalytics && duration > 10) {
                  // Only track if it takes more than 10ms
                  trackAnalytics(
                    {
                      type: 'performance_metric',
                      store: storeName,
                      action: key,
                      metadata: {
                        duration,
                        isAsync: false,
                      },
                    },
                    analyticsHandler,
                  );
                }
              }

              return result;
            } catch (error) {
              if (enableErrorHandling) {
                handleError(
                  error instanceof Error ? error : new Error(String(error)),
                  {
                    store: storeName,
                    action: key,
                    state: get(),
                  },
                  errorHandler,
                );
              }
              throw error;
            }
          }) as typeof originalAction;
        }
      }

      return wrappedStore as T;
    }

    return store;
  };
}

/**
 * Helper to create a store with state middleware
 * 
 * @example
 * ```typescript
 * export const useMyStore = createWithMiddleware<MyState>(
 *   (set, get) => ({
 *     // store implementation
 *   }),
 *   { storeName: 'MyStore' }
 * );
 * ```
 */
export function createWithMiddleware<T extends object>(
  config: StateCreator<T>,
  options: StateMiddlewareOptions,
): StateCreator<T> {
  return stateMiddleware(config, options);
}

