/**
 * Button 按钮组件
 * 支持多种变体、尺寸、加载状态和图标
 */

import React, { useMemo } from 'react';
import {
  TouchableOpacity,
  ActivityIndicator,
  StyleSheet,
  View,
  ViewStyle,
  TextStyle,
} from 'react-native';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { borderRadius, spacing, fontSizes, useAppColors, type AppColors } from '../../theme';
import Text from './Text';

type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'text' | 'danger';
type ButtonSize = 'sm' | 'md' | 'lg';
type IconPosition = 'left' | 'right';

interface ButtonProps {
  title: string;
  onPress: () => void;
  variant?: ButtonVariant;
  size?: ButtonSize;
  disabled?: boolean;
  loading?: boolean;
  icon?: string;
  iconPosition?: IconPosition;
  fullWidth?: boolean;
  style?: ViewStyle;
}

function createButtonStyles(colors: AppColors) {
  return StyleSheet.create({
    base: {
      justifyContent: 'center',
      alignItems: 'center',
      borderRadius: borderRadius.md,
    },
    content: {
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'center',
    },
    size_sm: {
      paddingVertical: spacing.sm,
      paddingHorizontal: spacing.md,
      minHeight: 32,
    },
    size_md: {
      paddingVertical: spacing.md,
      paddingHorizontal: spacing.lg,
      minHeight: 40,
    },
    size_lg: {
      paddingVertical: spacing.lg,
      paddingHorizontal: spacing.xl,
      minHeight: 48,
    },
    primary: {
      backgroundColor: colors.primary.main,
    },
    secondary: {
      backgroundColor: colors.secondary.main,
    },
    outline: {
      backgroundColor: 'transparent',
      borderWidth: 1,
      borderColor: colors.primary.main,
    },
    text: {
      backgroundColor: 'transparent',
      shadowColor: 'transparent',
      elevation: 0,
    },
    danger: {
      backgroundColor: colors.error.main,
    },
    disabled: {
      backgroundColor: colors.background.disabled,
      borderColor: colors.background.disabled,
    },
    fullWidth: {
      width: '100%',
    },
    textBase: {
      fontWeight: '600',
    },
    textSize_sm: {
      fontSize: fontSizes.sm,
    },
    textSize_md: {
      fontSize: fontSizes.md,
    },
    textSize_lg: {
      fontSize: fontSizes.lg,
    },
    iconLeft: {
      marginRight: spacing.sm,
    },
    iconRight: {
      marginLeft: spacing.sm,
    },
  });
}

const Button: React.FC<ButtonProps> = ({
  title,
  onPress,
  variant = 'primary',
  size = 'md',
  disabled = false,
  loading = false,
  icon,
  iconPosition = 'left',
  fullWidth = false,
  style,
}) => {
  const colors = useAppColors();
  const styles = useMemo(() => createButtonStyles(colors), [colors]);

  const getButtonStyle = (): ViewStyle[] => {
    const baseStyle: ViewStyle[] = [styles.base, styles[`size_${size}`]];

    switch (variant) {
      case 'primary':
        baseStyle.push(styles.primary);
        break;
      case 'secondary':
        baseStyle.push(styles.secondary);
        break;
      case 'outline':
        baseStyle.push(styles.outline);
        break;
      case 'text':
        baseStyle.push(styles.text);
        break;
      case 'danger':
        baseStyle.push(styles.danger);
        break;
    }

    if (disabled || loading) {
      baseStyle.push(styles.disabled);
    }

    if (fullWidth) {
      baseStyle.push(styles.fullWidth);
    }

    return baseStyle;
  };

  const getTextStyle = (): TextStyle => {
    const baseStyle: TextStyle = {
      ...styles.textBase,
      ...styles[`textSize_${size}`],
    };

    switch (variant) {
      case 'primary':
      case 'danger':
        baseStyle.color = colors.text.inverse;
        break;
      case 'secondary':
        baseStyle.color = colors.text.inverse;
        break;
      case 'outline':
      case 'text':
        baseStyle.color = colors.primary.main;
        break;
    }

    if (disabled || loading) {
      baseStyle.color = colors.text.disabled;
    }

    return baseStyle;
  };

  const getIconSize = (): number => {
    switch (size) {
      case 'sm':
        return 16;
      case 'md':
        return 20;
      case 'lg':
        return 24;
    }
  };

  const getIconColor = (): string => {
    if (disabled || loading) {
      return colors.text.disabled;
    }
    switch (variant) {
      case 'primary':
      case 'danger':
        return colors.text.inverse;
      case 'secondary':
        return colors.text.inverse;
      case 'outline':
      case 'text':
        return colors.primary.main;
    }
  };

  const isDisabled = disabled || loading;

  return (
    <TouchableOpacity
      style={[getButtonStyle(), style]}
      onPress={onPress}
      disabled={isDisabled}
      activeOpacity={0.9}
    >
      {loading ? (
        <ActivityIndicator
          size="small"
          color={
            variant === 'outline' || variant === 'text' ? colors.primary.main : colors.text.inverse
          }
        />
      ) : (
        <View style={styles.content}>
          {icon && iconPosition === 'left' && (
            <MaterialCommunityIcons
              name={icon as any}
              size={getIconSize()}
              color={getIconColor()}
              style={styles.iconLeft}
            />
          )}
          <Text style={getTextStyle()}>{title}</Text>
          {icon && iconPosition === 'right' && (
            <MaterialCommunityIcons
              name={icon as any}
              size={getIconSize()}
              color={getIconColor()}
              style={styles.iconRight}
            />
          )}
        </View>
      )}
    </TouchableOpacity>
  );
};

export default Button;
