import * as Haptics from "expo-haptics";
import React from "react";
import {
  ActivityIndicator,
  Platform,
  Pressable,
  StyleSheet,
  Text,
  ViewStyle,
} from "react-native";

import { sansSemibold } from "@/constants/typography";
import { useColors } from "@/hooks/useColors";

interface PrimaryButtonProps {
  label: string;
  onPress?: () => void;
  variant?: "primary" | "secondary" | "ghost" | "destructive";
  disabled?: boolean;
  loading?: boolean;
  size?: "lg" | "md" | "sm";
  icon?: React.ReactNode;
  style?: ViewStyle;
  haptic?: boolean;
  testID?: string;
}

export function PrimaryButton({
  label,
  onPress,
  variant = "primary",
  disabled,
  loading,
  size = "md",
  icon,
  style,
  haptic = true,
  testID,
}: PrimaryButtonProps) {
  const colors = useColors();

  const bg =
    variant === "primary"
      ? colors.primary
      : variant === "secondary"
        ? colors.elevated
        : variant === "destructive"
          ? colors.destructive
          : "transparent";
  const fg =
    variant === "primary"
      ? colors.primaryForeground
      : variant === "destructive"
        ? colors.text
        : colors.text;
  const border =
    variant === "ghost" ? colors.borderStrong : "transparent";

  const heights = { lg: 56, md: 48, sm: 38 } as const;
  const radii = { lg: 18, md: 14, sm: 10 } as const;
  const fontSizes = { lg: 16, md: 15, sm: 13 } as const;

  return (
    <Pressable
      testID={testID}
      onPress={() => {
        if (disabled || loading) return;
        if (haptic && Platform.OS !== "web") {
          Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light).catch(
            () => {},
          );
        }
        onPress?.();
      }}
      disabled={disabled || loading}
      style={({ pressed }) => [
        styles.base,
        {
          height: heights[size],
          borderRadius: radii[size],
          backgroundColor: bg,
          borderColor: border,
          borderWidth: variant === "ghost" ? 1 : 0,
          opacity: disabled ? 0.45 : pressed ? 0.85 : 1,
          transform: [{ scale: pressed && !disabled ? 0.985 : 1 }],
        },
        style,
      ]}
    >
      {loading ? (
        <ActivityIndicator color={fg} />
      ) : (
        <>
          {icon}
          <Text
            style={{
              color: fg,
              fontFamily: sansSemibold,
              fontSize: fontSizes[size],
              letterSpacing: -0.2,
            }}
          >
            {label}
          </Text>
        </>
      )}
    </Pressable>
  );
}

const styles = StyleSheet.create({
  base: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    gap: 8,
    paddingHorizontal: 18,
  },
});
