<script setup lang="ts">
/**
 * RadialBars — concentric progress rings (the "activity rings" look). Each item
 * is a value 0–max rendered as a ring; great for multi-KPI completion tiles.
 *
 *   <RadialBars :data="[{label:'Sales',value:82},{label:'Leads',value:64},{label:'Churn',value:23}]" />
 *   <RadialBars :data="rings" :max="100" :legend="false" />
 */
import { computed, ref } from 'vue'
import { alpha, resolveColor } from './core/palette'
import { useChartAnim } from './core/useChartAnim'
import type { ThemeType } from '../../types'

interface Ring { label: string; value: number; color?: ThemeType | string; max?: number }

const props = withDefaults(defineProps<{
	data: Ring[]
	/** Shared max when a ring doesn't set its own. */
	max?: number
	size?: number
	/** Ring thickness in px. */
	thickness?: number
	/** Gap between rings in px. */
	gap?: number
	legend?: boolean
	/** Show the value of each ring in the legend. Default %. */
	suffix?: string
	animated?: boolean
}>(), {
	max: 100,
	size: 180,
	thickness: 14,
	gap: 6,
	legend: true,
	suffix: '%',
	animated: true,
})

const el = ref<HTMLElement>()
const { progress } = useChartAnim({ el, enabled: props.animated, duration: 900 })

const cx = computed(() => props.size / 2)

function ringPath(r: number): string {
	const c = cx.value
	// Full-circle path (two arcs) starting at 12 o'clock.
	return `M ${c} ${c - r} A ${r} ${r} 0 1 1 ${c - 0.001} ${c - r} Z`
}

interface Arc { path: string; color: string; label: string; display: string; circ: number; filled: number }
const arcs = computed<Arc[]>(() =>
	props.data.map((d, i) => {
		const r = cx.value - props.thickness / 2 - i * (props.thickness + props.gap)
		const max = d.max ?? props.max
		const frac = Math.min(1, Math.max(0, d.value / (max || 1)))
		const circ = 2 * Math.PI * r
		return {
			path: ringPath(r),
			color: resolveColor(d.color, i),
			label: d.label,
			display: `${d.value}${props.suffix}`,
			circ,
			filled: circ * frac * progress.value,
		}
	}),
)
</script>

<template>
	<div
		ref="el" class="bgl-radial inline-flex gap-1"
		:class="legend ? 'row' : 'column'"
	>
		<svg :width="size" :height="size" :viewBox="`0 0 ${size} ${size}`" class="bgl-radial__svg flex-shrink-0">
			<g v-for="(a, i) in arcs" :key="i">
				<path :d="a.path" :stroke="alpha(a.color, 14)" :stroke-width="thickness" fill="none" stroke-linecap="round" />
				<path
					:d="a.path" :stroke="a.color" :stroke-width="thickness" fill="none" stroke-linecap="round"
					:stroke-dasharray="`${a.filled} ${a.circ}`"
					:transform="`rotate(-90 ${cx} ${cx})`"
				/>
			</g>
		</svg>

		<ul v-if="legend" class="bgl-radial__legend grid gap-05 m-0 min-w-0">
			<li v-for="(a, i) in arcs" :key="i" class="flex align-items-center gap-05 txt13">
				<span class="bgl-radial__dot flex-shrink-0" :style="{ background: a.color }" />
				<span>{{ a.label }}</span>
				<span class="bgl-radial__val semibold tabular-nums ms-auto">{{ a.display }}</span>
			</li>
		</ul>
	</div>
</template>

<style scoped>
.bgl-radial__svg path { transition: stroke-dasharray 0.3s ease; }
.bgl-radial__legend { list-style: none; padding: 0; }
.bgl-radial__dot { width: 10px; height: 10px; border-radius: 3px; }
</style>
