import React, { useEffect, useMemo, memo } from 'react';
import { Button, XStack } from 'tamagui';
import CustomText from '@/components/common/CustomText.jsx';
import Animated, { useSharedValue, useAnimatedStyle, withTiming } from 'react-native-reanimated';

// UI组件
import LoadingSpinner from '@/components/ui/LoadingSpinner';

// 引入屏幕适配
import { wp, sp } from '@/utils/ui/screenUtils';

/**
 * CustomButton 自定义按钮
 * - 统一“禁用态、按压半透明、loading 滑入动画”的交互与样式
 * - 支持将 Tamagui Button 的其余属性透传（...rest），用于覆盖默认主题/尺寸等
 *
 * @param {Object} props
 * @param {boolean} [props.loading=false] 是否处于加载中；用于驱动loading与滑入动画
 * @param {boolean} [props.disabled=false] 是否禁用；与 loading 解耦，仅表示不可点击
 * @param {boolean} [props.disabledWhileLoading=true] 是否在 loading 时自动禁用（effectiveDisabled 会合并此逻辑）
 * @param {function} [props.onPress] 点击事件处理函数，直接透传给 Button（建议调用方使用 useCallback 稳定引用）
 * @param {Object} [props.style] 外层 Button 的样式；会与禁用态背景样式合并
 * @param {Object} [props.textStyle] 文本样式；children 未提供时作用于 btnText
 * @param {React.ReactNode} [props.children] 自定义按钮内容；若提供则优先于 btnText 渲染
 * @param {string} [props.btnText] 简单场景的按钮文案；当未提供 children 时生效
 * @param {number} [props.spinnerSize=wp(16)] loading尺寸；用于动画目标宽度与 LoadingSpinner.size
 * @param {string} [props.spinnerColor="#FFFFFF"] loading颜色
 * @param {number} [props.animationDuration=180] loading滑入/滑出动画时长（ms）
 * @param {number} [props.gapWhileLoading=wp(6)] loading 显示时，图标与文字之间的间距
 * @param {Object} [props.pressStyle] 按下态样式；不传时采用默认半透明紫；可通过 {...rest} 进一步覆盖
 */
const CustomButton = ({
    // 是否处于加载中（驱动动画与loading）
    loading = false,
    // 是否禁用（仅表达不可点击，与 loading 解耦）
    disabled = false,
    // loading 时是否自动禁用（默认自动禁用）
    disabledWhileLoading = true,
    // 点击事件（建议调用方用 useCallback 保持稳定）
    onPress,
    // Button 外层样式（会与禁用态的背景色样式合并）
    style,
    // 文本样式（children 未提供时作用于 btnText）
    textStyle,
    // 自定义内容（优先渲染），为空时退回到 btnText
    children,
    // 简单文案（无 children 时生效）
    btnText,
    // loading尺寸（亦作为动画目标宽度）
    spinnerSize = wp(16),
    // loading颜色
    spinnerColor = '#FFFFFF',
    // 动画时长（ms）
    animationDuration = 180,
    // loading 时的左右间距
    gapWhileLoading = wp(6),
    // 按下态样式（不传时使用默认半透明紫）
    pressStyle: pressStyleProp,
    // 其余 Tamagui Button 属性透传，支持覆盖默认设置
    ...rest
}) => {
    // 计算最终禁用态：disabled 或（loading 且禁用策略开启）
    const effectiveDisabled = disabled || (loading && disabledWhileLoading);

    // loading滑入动画（基于 loading，而非 disabled）
    const spinnerWidth = useSharedValue(0);
    const spinnerTargetWidth = spinnerSize;
    useEffect(() => {
        spinnerWidth.value = withTiming(loading ? spinnerTargetWidth : 0, { duration: animationDuration });
    }, [loading, spinnerTargetWidth, animationDuration, spinnerWidth]);

    // loading容器的宽度动画样式
    const spinnerAnimStyle = useAnimatedStyle(() => ({
        width: spinnerWidth.value,
        overflow: 'hidden',
        alignItems: 'center',
    }));

    // 按下态样式：外部传入优先，否则使用默认半透明紫
    const computedPressStyle = useMemo(() => (
        pressStyleProp ?? {
            backgroundColor: 'rgba(222, 66, 140, 0.5)',
            borderWidth: 0,
            borderColor: 'transparent'
        }
    ), [pressStyleProp]);

    // Button 样式：禁用态背景色合并 + 外部样式
    const buttonStyle = useMemo(() => ([
        effectiveDisabled && {
            backgroundColor: 'rgba(222, 66, 140, 0.5)',
            borderWidth: 0,
            borderColor: 'transparent'
        },
        style,
    ]), [effectiveDisabled, style]);

    // 文本样式：映射可能由 {...rest} 传入的字体相关属性，使其作用于自定义 Text
    const computedTextStyle = useMemo(() => ([
        // 从透传的 Button 属性映射到文本样式
        rest.fontSize != null || rest.fontWeight != null || rest.lineHeight != null
            ? {
                fontSize: rest.fontSize,
                fontWeight: rest.fontWeight,
                lineHeight: rest.lineHeight,
            }
            : null,
        textStyle,
    ].filter(Boolean)), [rest.fontSize, rest.fontWeight, rest.lineHeight, textStyle]);

    // loading 时与文字的间距（无需动画即可达到自然过渡）
    const gap = loading ? gapWhileLoading : 0;

    return (
        <Button
            theme="lightPrimaryWhite"
            fontSize={sp(14)}
            fontFamily="SemiBold"
            lineHeight={wp(20)}
            borderRadius={wp(4)}
            // 按下态样式：外部传入优先，其次为默认
            pressStyle={computedPressStyle}
            // 最终禁用态：disabled || (loading && disabledWhileLoading)
            disabled={effectiveDisabled}
            // 点击事件直接透传（交由 disabled 阻止触发）
            onPress={onPress}
            // Button 样式（禁用态背景 + 外部样式）
            style={buttonStyle}
            // 其余 Tamagui Button 属性透传，允许覆盖上面的默认设置
            {...rest}
        >
            <XStack
                alignItems="center"
                justifyContent="center"
                // loading 时为图标与文字留出间距
                gap={gap}
            >
                {/* loading容器：通过宽度动画实现“滑入/滑出”效果 */}
                <Animated.View style={spinnerAnimStyle}>
                    {/* 自定义loading */}
                    <LoadingSpinner size={spinnerSize} color={spinnerColor} animating={loading} />
                </Animated.View>
                {/* 内容优先级：children > btnText */}
                {children ? (
                    children
                ) : (
                    <CustomText style={computedTextStyle}>{btnText}</CustomText>
                )}
            </XStack>
        </Button>
    );
};

export default memo(CustomButton);