import { useEffect, useReducer } from "react"
import {
    UserSignedExtensionName,
    UserSignedExtensions,
} from "../../../types/UserSignedExtension"

import {
    Select,
    SelectValue,
    SelectTrigger,
    SelectLabel,
    SelectContent,
    SelectGroup,
    SelectItem,
} from "../../../components/ui/select"
import { Input } from "../../../components/ui/input"

const reducer = (
    state: Partial<UserSignedExtensions>,
    [name, value]: [
        UserSignedExtensionName,
        UserSignedExtensions[UserSignedExtensionName],
    ],
) => ({
    ...state,
    [name]: value,
})

type Props = {
    userSignedExtensionNames: string[]
    onChange(userSignedExtensions: Partial<UserSignedExtensions>): void
}
export const UserSignedExtensionInputs = ({
    userSignedExtensionNames,
    onChange,
}: Props) => {
    const [state, dispatch] = useReducer(
        reducer,
        {} as Partial<UserSignedExtensions>,
    )
    useEffect(() => onChange(state), [state])

    return (
        <div>
            {userSignedExtensionNames.map((type) => {
                switch (type) {
                    case "CheckMortality": {
                        return (
                            <MortalityInput
                                key={type}
                                defaultValue={state["CheckMortality"]}
                                onChange={(v) => dispatch(["CheckMortality", v])}
                            />
                        )
                    }
                    case "ChargeTransactionPayment": {
                        return (
                            <TipInput
                                key={type}
                                defaultValue={state["ChargeTransactionPayment"]}
                                onChange={(v) => dispatch(["ChargeTransactionPayment", v])}
                            />
                        )
                    }
                    default: {
                        return null
                    }
                }
            })}
        </div>
    )
}

type TipInputProps = {
    onChange(value: UserSignedExtensions["ChargeTransactionPayment"]): void
    defaultValue?: number
}
const TipInput = ({ onChange, defaultValue = 0 }: TipInputProps) => {
    // @ts-expect-error TODO: improve bigint types
    useEffect(() => onChange(defaultValue), [])
    return (
        <div className="flex flex-col gap-2">
            <div className="text-xs font-semibold mt-4">Tip Amount</div>
            <Input
                onChange={e => onChange(+e.target.value)}
                aria-label="Request Origin"
                type="number"
                className="pr-10 text-muted-foreground"
                value={Number(defaultValue)}
            />
        </div>
    )
}

// TODO: the max mortality value could be computed from the metadata
const VALID_MORTALITIES = Array(8)
    .fill(0)
    .map((_, i) => "" + Math.pow(2, i + 2))

type MortalityInputProps = {
    onChange(value: UserSignedExtensions["CheckMortality"]): void
    defaultValue?: UserSignedExtensions["CheckMortality"]
}
const MortalityInput = ({
    onChange,
    defaultValue = { mortal: true, period: 64 },
}: MortalityInputProps) => {
    useEffect(() => onChange(defaultValue), [])
    return (
        <div className="flex flex-col gap-2">
            <div className="text-xs font-semibold mt-4">Transaction Mortality</div>
            <Select onValueChange={(value) => onChange({ mortal: true, period: +value })}>
                <SelectTrigger className="w-full" data-testid="scheme-select">
                    <SelectValue placeholder="Blocks in Queue" />
                </SelectTrigger>
                <SelectContent>
                    <SelectGroup>
                        <SelectLabel>Blocks in Queue</SelectLabel>
                        {VALID_MORTALITIES.map((m) => (
                            <SelectItem key={m} data-testid={m} value={m}>{m}</SelectItem>
                        ))}
                    </SelectGroup>
                </SelectContent>
            </Select>
        </div>
    )
}
