/**
 * CustomBottomSheet — replaces ALL system Alert/Modal patterns.
 *
 * Built on @gorhom/bottom-sheet with MD3 styling, drag-handle,
 * scrim overlay, and smooth reanimated transitions.
 *
 * Usage:
 *   <CustomBottomSheet ref={sheetRef} snapPoints={['50%']}>
 *     <BottomSheetContent />
 *   </CustomBottomSheet>
 *
 * Imperative API:
 *   sheetRef.current?.present()   – open
 *   sheetRef.current?.dismiss()   – close
 */

import React, {
  forwardRef,
  useCallback,
  useImperativeHandle,
  useMemo,
  useRef,
} from 'react';
import {
  View,
  Text,
  StyleSheet,
  TouchableOpacity,
  Pressable,
} from 'react-native';
import BottomSheet, {
  BottomSheetBackdrop,
  BottomSheetScrollView,
  BottomSheetView,
  type BottomSheetBackdropProps,
} from '@gorhom/bottom-sheet';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import {useTheme} from '../theme';
import type {MD3Theme} from '../theme';

const hapticOptions = {enableVibrateFallback: true, ignoreAndroidSystemSettings: false};
export const triggerHaptic = (type: 'impactLight' | 'impactMedium' | 'selection' | 'notificationSuccess' = 'impactLight') =>
  ReactNativeHapticFeedback.trigger(type, hapticOptions);

// ─── Public Handle ───────────────────────────────────────────────────

export interface CustomBottomSheetHandle {
  present: () => void;
  dismiss: () => void;
}

// ─── Props ───────────────────────────────────────────────────────────

export interface CustomBottomSheetProps {
  /** Title displayed in the sheet header */
  title?: string;
  /** Snap-point percentages or absolute values */
  snapPoints?: (string | number)[];
  /** Callback when the sheet is fully closed */
  onDismiss?: () => void;
  /** Whether to wrap children in a ScrollView (default: true) */
  scrollable?: boolean;
  /** Header left action (e.g. Cancel) */
  headerLeft?: {label: string; onPress: () => void};
  /** Header right action (e.g. Save) */
  headerRight?: {label: string; onPress: () => void; color?: string};
  /** Content */
  children: React.ReactNode;
  /** Enable dynamic sizing instead of snapPoints */
  enableDynamicSizing?: boolean;
}

// ─── Component ───────────────────────────────────────────────────────

const CustomBottomSheetInner = forwardRef<CustomBottomSheetHandle, CustomBottomSheetProps>(
  (
    {
      title,
      snapPoints: snapPointsProp,
      onDismiss,
      scrollable = true,
      headerLeft,
      headerRight,
      children,
      enableDynamicSizing = false,
    },
    ref,
  ) => {
    const theme = useTheme();
    const s = makeStyles(theme);
    const sheetRef = useRef<BottomSheet>(null);
    const snapPoints = useMemo(() => snapPointsProp ?? ['60%'], [snapPointsProp]);

    // Imperative handle
    useImperativeHandle(ref, () => ({
      present: () => {
        triggerHaptic('impactMedium');
        sheetRef.current?.snapToIndex(0);
      },
      dismiss: () => {
        triggerHaptic('impactLight');
        sheetRef.current?.close();
      },
    }));

    // Backdrop with scrim
    const renderBackdrop = useCallback(
      (props: BottomSheetBackdropProps) => (
        <BottomSheetBackdrop
          {...props}
          disappearsOnIndex={-1}
          appearsOnIndex={0}
          opacity={0.4}
          pressBehavior="close"
        />
      ),
      [],
    );

    // Handle indicator
    const renderHandle = useCallback(
      () => (
        <View style={s.handleContainer}>
          <View style={s.handle} />
        </View>
      ),
      [s],
    );

    const Wrapper = scrollable ? BottomSheetScrollView : BottomSheetView;

    return (
      <BottomSheet
        ref={sheetRef}
        index={-1}
        snapPoints={enableDynamicSizing ? undefined : snapPoints}
        enableDynamicSizing={enableDynamicSizing}
        enablePanDownToClose
        onClose={onDismiss}
        backdropComponent={renderBackdrop}
        handleComponent={renderHandle}
        backgroundStyle={s.background}
        style={s.container}
        keyboardBehavior="interactive"
        keyboardBlurBehavior="restore"
        android_keyboardInputMode="adjustResize">
        {/* Sheet Header */}
        {(title || headerLeft || headerRight) && (
          <View style={s.header}>
            {headerLeft ? (
              <TouchableOpacity onPress={headerLeft.onPress} hitSlop={8}>
                <Text style={s.headerLeftText}>{headerLeft.label}</Text>
              </TouchableOpacity>
            ) : (
              <View style={s.headerPlaceholder} />
            )}
            {title ? <Text style={s.headerTitle}>{title}</Text> : <View />}
            {headerRight ? (
              <TouchableOpacity onPress={headerRight.onPress} hitSlop={8}>
                <Text
                  style={[
                    s.headerRightText,
                    headerRight.color ? {color: headerRight.color} : undefined,
                  ]}>
                  {headerRight.label}
                </Text>
              </TouchableOpacity>
            ) : (
              <View style={s.headerPlaceholder} />
            )}
          </View>
        )}

        {/* Sheet Body */}
        <Wrapper
          style={s.body}
          contentContainerStyle={s.bodyContent}
          showsVerticalScrollIndicator={false}>
          {children}
        </Wrapper>
      </BottomSheet>
    );
  },
);

CustomBottomSheetInner.displayName = 'CustomBottomSheet';

export const CustomBottomSheet = CustomBottomSheetInner;

// ─── Styles ──────────────────────────────────────────────────────────

function makeStyles(theme: MD3Theme) {
  const {colors, typography, shape, spacing} = theme;
  return StyleSheet.create({
    container: {
      zIndex: 999,
    },
    background: {
      backgroundColor: colors.surfaceContainerLow,
      borderTopLeftRadius: shape.extraLarge,
      borderTopRightRadius: shape.extraLarge,
    },
    handleContainer: {
      alignItems: 'center',
      paddingTop: spacing.sm,
      paddingBottom: spacing.xs,
    },
    handle: {
      width: 32,
      height: 4,
      borderRadius: 2,
      backgroundColor: colors.onSurfaceVariant,
      opacity: 0.4,
    },
    header: {
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'space-between',
      paddingHorizontal: spacing.xl,
      paddingTop: spacing.sm,
      paddingBottom: spacing.md,
      borderBottomWidth: 1,
      borderBottomColor: colors.outlineVariant,
    },
    headerTitle: {
      ...typography.titleMedium,
      color: colors.onSurface,
      fontWeight: '600',
    },
    headerLeftText: {
      ...typography.labelLarge,
      color: colors.onSurfaceVariant,
    },
    headerRightText: {
      ...typography.labelLarge,
      color: colors.primary,
      fontWeight: '600',
    },
    headerPlaceholder: {
      width: 48,
    },
    body: {
      flex: 1,
    },
    bodyContent: {
      paddingHorizontal: spacing.xl,
      paddingTop: spacing.lg,
      paddingBottom: spacing.xxxl + 20,
    },
  });
}

// ─── Convenience Sub-Components ──────────────────────────────────────

/**
 * MD3-styled text input for use inside bottom sheets.
 */
export interface BottomSheetInputProps {
  label: string;
  value: string;
  onChangeText: (text: string) => void;
  placeholder?: string;
  keyboardType?: 'default' | 'decimal-pad' | 'number-pad' | 'email-address';
  error?: string;
  multiline?: boolean;
  prefix?: string;
  autoFocus?: boolean;
}

import {TextInput} from 'react-native';

export const BottomSheetInput: React.FC<BottomSheetInputProps> = ({
  label,
  value,
  onChangeText,
  placeholder,
  keyboardType = 'default',
  error,
  multiline = false,
  prefix,
  autoFocus = false,
}) => {
  const theme = useTheme();
  const {colors, typography, shape, spacing} = theme;
  const [focused, setFocused] = React.useState(false);

  const borderColor = error
    ? colors.error
    : focused
      ? colors.primary
      : colors.outline;

  return (
    <View style={{marginBottom: spacing.lg}}>
      <Text
        style={{
          ...typography.bodySmall,
          color: error ? colors.error : focused ? colors.primary : colors.onSurfaceVariant,
          marginBottom: spacing.xs,
        }}>
        {label}
      </Text>
      <View
        style={{
          flexDirection: 'row',
          alignItems: 'center',
          borderWidth: focused ? 2 : 1,
          borderColor,
          borderRadius: shape.small,
          backgroundColor: colors.surfaceContainerLowest,
          paddingHorizontal: spacing.md,
          minHeight: multiline ? 80 : 48,
        }}>
        {prefix && (
          <Text
            style={{
              ...typography.bodyLarge,
              color: colors.onSurfaceVariant,
              marginRight: spacing.xs,
            }}>
            {prefix}
          </Text>
        )}
        <TextInput
          style={{
            flex: 1,
            ...typography.bodyLarge,
            color: colors.onSurface,
            paddingVertical: spacing.sm,
            textAlignVertical: multiline ? 'top' : 'center',
          }}
          value={value}
          onChangeText={onChangeText}
          placeholder={placeholder}
          placeholderTextColor={colors.onSurfaceVariant + '80'}
          keyboardType={keyboardType}
          multiline={multiline}
          autoFocus={autoFocus}
          onFocus={() => setFocused(true)}
          onBlur={() => setFocused(false)}
        />
      </View>
      {error && (
        <Text
          style={{
            ...typography.bodySmall,
            color: colors.error,
            marginTop: spacing.xs,
          }}>
          {error}
        </Text>
      )}
    </View>
  );
};

/**
 * MD3 chip selector row for use inside bottom sheets.
 */
export interface BottomSheetChipSelectorProps<T extends string> {
  label?: string;
  options: {value: T; label: string; icon?: string}[];
  selected: T;
  onSelect: (value: T) => void;
}

import Icon from 'react-native-vector-icons/MaterialCommunityIcons';

export function BottomSheetChipSelector<T extends string>({
  label,
  options,
  selected,
  onSelect,
}: BottomSheetChipSelectorProps<T>) {
  const theme = useTheme();
  const {colors, typography, shape, spacing} = theme;

  return (
    <View style={{marginBottom: spacing.lg}}>
      {label && (
        <Text
          style={{
            ...typography.bodySmall,
            color: colors.onSurfaceVariant,
            marginBottom: spacing.sm,
          }}>
          {label}
        </Text>
      )}
      <View style={{flexDirection: 'row', flexWrap: 'wrap', gap: spacing.sm}}>
        {options.map(opt => {
          const isSelected = opt.value === selected;
          return (
            <Pressable
              key={opt.value}
              onPress={() => {
                triggerHaptic('selection');
                onSelect(opt.value);
              }}
              style={{
                flexDirection: 'row',
                alignItems: 'center',
                paddingHorizontal: spacing.md,
                paddingVertical: spacing.sm,
                borderRadius: shape.small,
                borderWidth: 1,
                borderColor: isSelected ? colors.primary : colors.outlineVariant,
                backgroundColor: isSelected
                  ? colors.primaryContainer
                  : colors.surfaceContainerLowest,
              }}>
              {opt.icon && (
                <Icon
                  name={opt.icon}
                  size={16}
                  color={isSelected ? colors.primary : colors.onSurfaceVariant}
                  style={{marginRight: spacing.xs}}
                />
              )}
              <Text
                style={{
                  ...typography.labelMedium,
                  color: isSelected ? colors.onPrimaryContainer : colors.onSurfaceVariant,
                }}>
                {opt.label}
              </Text>
            </Pressable>
          );
        })}
      </View>
    </View>
  );
}
