import React, { Component, ReactNode } from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import { debugLogger } from '@/services/DebugLogger';
import { AppColors, Spacing, FontSizes, BorderRadius } from '@/constants/theme';

interface Props {
  children: ReactNode;
  fallback?: ReactNode;
  onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
  category?: string;
}

interface State {
  hasError: boolean;
  error: Error | null;
  errorInfo: React.ErrorInfo | null;
}

/**
 * ErrorBoundary - catches JavaScript errors in child components
 * Logs errors to DebugLogger and shows fallback UI
 */
export class ErrorBoundary extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = {
      hasError: false,
      error: null,
      errorInfo: null,
    };
  }

  static getDerivedStateFromError(error: Error): State {
    return {
      hasError: true,
      error,
      errorInfo: null,
    };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    const category = this.props.category || 'ErrorBoundary';

    // Log to debug console
    debugLogger.error(
      category,
      `💥 Component crashed: ${error.message}`,
      {
        error: error.toString(),
        stack: error.stack,
        componentStack: errorInfo.componentStack,
      }
    );

    // Update state with error info
    this.setState({
      errorInfo,
    });

    // Call optional error handler
    this.props.onError?.(error, errorInfo);
  }

  handleReset = () => {
    this.setState({
      hasError: false,
      error: null,
      errorInfo: null,
    });
  };

  render() {
    if (this.state.hasError) {
      // Custom fallback UI
      if (this.props.fallback) {
        return this.props.fallback;
      }

      // Default fallback UI
      return (
        <View style={styles.container}>
          <View style={styles.errorCard}>
            <Text style={styles.errorTitle}>Something went wrong</Text>
            <Text style={styles.errorMessage}>
              {this.state.error?.message || 'Unknown error'}
            </Text>

            {this.state.error?.stack && (
              <View style={styles.stackContainer}>
                <Text style={styles.stackLabel}>Stack trace:</Text>
                <Text style={styles.stackTrace} numberOfLines={5}>
                  {this.state.error.stack}
                </Text>
              </View>
            )}

            <TouchableOpacity
              style={styles.resetButton}
              onPress={this.handleReset}
            >
              <Text style={styles.resetButtonText}>Try Again</Text>
            </TouchableOpacity>

            <Text style={styles.debugHint}>
              Check Debug tab for full error details
            </Text>
          </View>
        </View>
      );
    }

    return this.props.children;
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: AppColors.background,
    padding: Spacing.lg,
  },
  errorCard: {
    backgroundColor: AppColors.surface,
    borderRadius: BorderRadius.lg,
    padding: Spacing.lg,
    maxWidth: 400,
    width: '100%',
    borderLeftWidth: 4,
    borderLeftColor: AppColors.error || '#E53935',
  },
  errorTitle: {
    fontSize: FontSizes.xl,
    fontWeight: '700',
    color: AppColors.error || '#E53935',
    marginBottom: Spacing.sm,
  },
  errorMessage: {
    fontSize: FontSizes.base,
    color: AppColors.textPrimary,
    marginBottom: Spacing.md,
    lineHeight: 22,
  },
  stackContainer: {
    backgroundColor: AppColors.background,
    borderRadius: BorderRadius.md,
    padding: Spacing.sm,
    marginBottom: Spacing.md,
  },
  stackLabel: {
    fontSize: FontSizes.xs,
    color: AppColors.textSecondary,
    fontWeight: '600',
    marginBottom: Spacing.xs,
  },
  stackTrace: {
    fontSize: FontSizes.xs,
    color: AppColors.textMuted,
    fontFamily: 'monospace',
    lineHeight: 16,
  },
  resetButton: {
    backgroundColor: AppColors.primary,
    borderRadius: BorderRadius.md,
    paddingVertical: Spacing.sm,
    paddingHorizontal: Spacing.md,
    alignItems: 'center',
    marginBottom: Spacing.sm,
  },
  resetButtonText: {
    color: AppColors.white,
    fontSize: FontSizes.base,
    fontWeight: '600',
  },
  debugHint: {
    fontSize: FontSizes.xs,
    color: AppColors.textMuted,
    textAlign: 'center',
    marginTop: Spacing.xs,
  },
});
