<script lang="ts">
	import Icon from "@iconify/svelte";
	import { getButtonStyle, parseColorText, getSegmentStyle } from "./utils";
	import { themeColors } from "$lib/stores/theme";
	import type { RadioLine } from "./types";
	import "$lib/assets/css/tui-radio.css";

	interface Props {
		line: RadioLine;
		inline?: boolean;
		value?: string;
		onchange?: (value: string) => void;
	}

	let {
		line,
		inline = false,
		value = $bindable(""),
		onchange,
	}: Props = $props();

	const labelSegments = $derived(
		line.content ? parseColorText(line.content, $themeColors.colorMap) : [],
	);
	const options = $derived(line.radioOptions || []);
	const isDisabled = $derived(line.inputDisabled || false);
	const isHorizontal = $derived(line.radioHorizontal || false);

	function handleSelect(optionValue: string) {
		if (isDisabled) return;
		value = optionValue;
		onchange?.(value);
	}

	function handleKeydown(e: KeyboardEvent, optionValue: string) {
		if (e.key === " " || e.key === "Enter") {
			e.preventDefault();
			handleSelect(optionValue);
		}
	}

	function getRadioSymbol(selected: boolean): string {
		return selected ? "(●)" : "( )";
	}
</script>

<div
	class="tui-radio-group"
	class:inline
	class:disabled={isDisabled}
	style="--radio-color: {getButtonStyle(line.style)}"
	role="radiogroup"
>
	{#if line.content}
		<div class="radio-label">
			{#if line.icon}
				<Icon icon={line.icon} width="14" class="label-icon" />
			{/if}
			{#each labelSegments as segment}
				{#if segment.icon}
					<Icon icon={segment.icon} width="14" class="inline-icon" />
				{:else if getSegmentStyle(segment)}
					<span style={getSegmentStyle(segment)}>{segment.text}</span>
				{:else}
					{segment.text}
				{/if}
			{/each}
		</div>
	{/if}

	<div class="radio-options" class:horizontal={isHorizontal}>
		{#each options as option}
			{@const isSelected = value === option.value}
			{@const optionSegments = parseColorText(
				option.label,
				$themeColors.colorMap,
			)}
			<div
				class="radio-option"
				class:selected={isSelected}
				class:option-disabled={option.disabled}
				role="radio"
				aria-checked={isSelected}
				aria-disabled={isDisabled || option.disabled}
				tabindex={isDisabled || option.disabled ? -1 : 0}
				onclick={() => !option.disabled && handleSelect(option.value)}
				onkeydown={(e) =>
					!option.disabled && handleKeydown(e, option.value)}
			>
				<span class="radio-symbol">
					{getRadioSymbol(isSelected)}
				</span>
				{#if option.icon}
					<Icon icon={option.icon} width="14" class="option-icon" />
				{/if}
				<span class="option-label">
					{#each optionSegments as segment}
						{#if segment.icon}
							<Icon
								icon={segment.icon}
								width="14"
								class="inline-icon"
							/>
						{:else if getSegmentStyle(segment)}
							<span style={getSegmentStyle(segment)}
								>{segment.text}</span
							>
						{:else}
							{segment.text}
						{/if}
					{/each}
				</span>
			</div>
		{/each}
	</div>
</div>

<style>
	.tui-radio-group {
		margin: 0.5rem 0;
		font-size: 0.9rem;
	}

	.tui-radio-group.inline {
		display: inline-flex;
		flex-direction: column;
		margin: 0 0.75rem 0 0;
	}

	.tui-radio-group.disabled {
		opacity: 0.5;
	}

	.radio-label {
		display: flex;
		align-items: center;
		gap: 0.35rem;
		margin-bottom: 0.5rem;
		color: var(--terminal-muted);
		font-size: 0.85rem;
	}

	:global(.label-icon) {
		color: var(--radio-color);
	}

	.radio-options {
		display: flex;
		flex-direction: column;
		gap: 0.25rem;
	}

	.radio-options.horizontal {
		flex-direction: row;
		flex-wrap: wrap;
		gap: 0.75rem;
	}

	.radio-option {
		display: flex;
		align-items: center;
		gap: 0.5rem;
		padding: 0.35rem 0.5rem;
		cursor: pointer;
		border-radius: 4px;
		transition: all 0.15s ease;
		user-select: none;
	}

	.radio-option:hover:not(.option-disabled) {
		background: color-mix(in srgb, var(--radio-color) 10%, transparent);
	}

	.radio-option:focus-visible {
		outline: 1px solid var(--radio-color);
		outline-offset: 2px;
	}

	.radio-option.option-disabled {
		opacity: 0.5;
		cursor: not-allowed;
	}

	.radio-symbol {
		font-family: inherit;
		font-weight: bold;
		color: var(--terminal-muted);
		transition: color 0.15s ease;
	}

	.radio-option.selected .radio-symbol {
		color: var(--radio-color);
	}

	:global(.option-icon) {
		color: var(--radio-color);
	}

	.option-label {
		color: var(--terminal-text);
	}

	.radio-option.option-disabled .option-label {
		color: var(--terminal-muted);
	}
</style>
