<script lang="ts">
import type { TypographyControl } from '$shared/lib';
import { Button } from '$shared/shadcn/ui/button';
import * as ButtonGroup from '$shared/shadcn/ui/button-group';
import { Input } from '$shared/shadcn/ui/input';
import * as Popover from '$shared/shadcn/ui/popover';
import { Slider } from '$shared/shadcn/ui/slider';
import MinusIcon from '@lucide/svelte/icons/minus';
import PlusIcon from '@lucide/svelte/icons/plus';
import type { ChangeEventHandler } from 'svelte/elements';

interface ComboControlProps {
    /**
     * Text for increase button aria-label
     */
    increaseLabel?: string;
    /**
     * Text for decrease button aria-label
     */
    decreaseLabel?: string;
    /**
     * Text for control button aria-label
     */
    controlLabel?: string;
    /**
     * Control instance
     */
    control: TypographyControl;
}

const {
    control,
    decreaseLabel,
    increaseLabel,
    controlLabel,
}: ComboControlProps = $props();

// Local state for the slider to prevent infinite loops
// svelte-ignore state_referenced_locally - $state captures initial value, $effect syncs updates
let sliderValue = $state(Number(control.value));

// Sync sliderValue when external value changes
$effect(() => {
    sliderValue = Number(control.value);
});

const handleInputChange: ChangeEventHandler<HTMLInputElement> = event => {
    const parsedValue = parseFloat(event.currentTarget.value);
    if (!isNaN(parsedValue)) {
        control.value = parsedValue;
    }
};

/**
 * Handle slider value change.
 * The Slider component passes the value as a number directly.
 */
const handleSliderChange = (newValue: number) => {
    control.value = newValue;
};
</script>

<ButtonGroup.Root>
    <Button
        variant="outline"
        size="icon"
        aria-label={decreaseLabel}
        onclick={control.decrease}
        disabled={control.isAtMin}
    >
        <MinusIcon />
    </Button>
    <Popover.Root>
        <Popover.Trigger>
            {#snippet child({ props })}
                <Button
                    {...props}
                    variant="outline"
                    size="icon"
                    aria-label={controlLabel}
                >
                    {control.value}
                </Button>
            {/snippet}
        </Popover.Trigger>
        <Popover.Content class="w-auto p-4">
            <div class="flex flex-col items-center gap-3">
                <Slider
                    min={control.min}
                    max={control.max}
                    step={control.step}
                    value={sliderValue}
                    onValueChange={handleSliderChange}
                    type="single"
                    orientation="vertical"
                    class="h-48"
                />
                <Input
                    value={control.value}
                    onchange={handleInputChange}
                    min={control.min}
                    max={control.max}
                    class="w-16 text-center"
                />
            </div>
        </Popover.Content>
    </Popover.Root>
    <Button
        variant="outline"
        size="icon"
        aria-label={increaseLabel}
        onclick={control.increase}
        disabled={control.isAtMax}
    >
        <PlusIcon />
    </Button>
</ButtonGroup.Root>
