import * as React from "react"
import {useMergeRefs} from "react-merge-refs"
import {TextInput} from "react-native"
import Animated, {
    type SharedValue,
    useAnimatedStyle,
    useDerivedValue,
} from "react-native-reanimated"

import {
    useBottomSheetToolboxInternalContext,
    useKeyboardHeightSharedValue,
} from "@attio/react-native-bottom-sheet-toolbox"

import type {BottomSheetToolBoxTextInputBaseProps} from "../../types"
import {
    type UseMinOverlayHeightSharedValueArgs,
    useMinOverlayHeightSharedValue,
} from "./use-min-overlay-height-shared-value"

const AnimatedTextInput = Animated.createAnimatedComponent(TextInput)

export interface OverlayTextInputProps
    extends Omit<UseMinOverlayHeightSharedValueArgs, "fallbackLines">,
        BottomSheetToolBoxTextInputBaseProps {
    minTextInputHeightSharedValue: SharedValue<number | null>
    ref?: React.ForwardedRef<TextInput>
}

export function OverlayTextInput({
    bottomInsetSharedValue,
    topInsetSharedValue,
    minTextInputHeightSharedValue,
    textInputStyle,
    autoFocus = false,
    multiline = false,
    ref,
    value,
    ...textInputProps
}: OverlayTextInputProps) {
    const textInputRef = React.useRef<TextInput>(null)

    const onContentSizeChange = useMinOverlayHeightSharedValue({
        minTextInputHeightSharedValue,
        topInsetSharedValue,
        bottomInsetSharedValue,
        textInputStyle,
        fallbackLines: multiline ? 3 : 1,
    })

    const {currentPositionSharedValue} = useBottomSheetToolboxInternalContext()
    const keyboardHeightSharedValue = useKeyboardHeightSharedValue()
    const overlayTextInputHeightSharedValue = useDerivedValue(() => {
        const topInset = topInsetSharedValue.get()
        const minTextInputHeight = minTextInputHeightSharedValue.get()

        if (topInset === null || minTextInputHeight === null) {
            return null
        }

        const unclampedHeight =
            currentPositionSharedValue.get() -
            keyboardHeightSharedValue.get() -
            topInset -
            bottomInsetSharedValue.get()

        const height = Math.max(minTextInputHeight, unclampedHeight)

        return height
    }, [
        bottomInsetSharedValue,
        currentPositionSharedValue,
        keyboardHeightSharedValue,
        minTextInputHeightSharedValue,
        topInsetSharedValue,
    ])

    const style = useAnimatedStyle(() => {
        const height = overlayTextInputHeightSharedValue.get()
        const bottomInset = bottomInsetSharedValue.get()

        return {
            height: height,
            marginBottom: bottomInset,
        }
    }, [bottomInsetSharedValue])

    const mergedRef = useMergeRefs([ref, textInputRef])

    return (
        <AnimatedTextInput
            ref={mergedRef}
            {...textInputProps}
            value={value}
            multiline={multiline}
            onContentSizeChange={onContentSizeChange}
            textAlignVertical="top"
            autoFocus={autoFocus}
            style={[style, textInputStyle]}
        />
    )
}
