<script setup lang="ts">
/**
 * StatCard — a KPI tile: label, big value, delta chip, and an optional trend
 * sparkline. Composes Card + Sparkline; all formatting is locale-aware.
 *
 *   <StatCard label="Revenue" :value="48200" currency="USD" :change="12.4" :trend="[…]" />
 *   <StatCard label="Active users" :value="1280" :change="-3.1" icon="group" color="purple" />
 */
import { computed } from 'vue'
import Card from '../Card.vue'
import Icon from '../Icon/Icon.vue'
import Sparkline from './Sparkline.vue'
import type { RawPoint } from './core/data'
import { formatValue } from './core/format'
import { resolveColor } from './core/palette'
import type { ThemeType } from '../../types'

const props = withDefaults(defineProps<{
	label: string
	value: number | string
	icon?: string
	color?: ThemeType | string
	/** Percentage change; sign drives the up/down chip color. */
	change?: number
	/** Invert chip colors when down is good (e.g. churn, cost). */
	invertChange?: boolean
	/** Sparkline data for a trend line. */
	trend?: RawPoint[]
	currency?: string
	prefix?: string
	suffix?: string
	subtitle?: string
	loading?: boolean
	/** Outlined card (transparent bg + border), like `<Card outline>`. */
	outline?: boolean
	/** Hairline framed card, like `<Card frame>`. */
	frame?: boolean
}>(), {
	color: 'primary',
})

const accent = computed(() => resolveColor(props.color))
const formatted = computed(() =>
	typeof props.value === 'number'
		? formatValue(props.value, { currency: props.currency, prefix: props.prefix, suffix: props.suffix })
		: `${props.prefix ?? ''}${props.value}${props.suffix ?? ''}`,
)
const hasChange = computed(() => props.change !== undefined && props.change !== 0)
const up = computed(() => (props.change ?? 0) > 0)
const good = computed(() => (props.invertChange ? !up.value : up.value))
</script>

<template>
	<Card thin :outline="outline" :frame="frame" class="bgl-stat flex column gap-1">
		<div class="flex space-between w-100p align-items-start gap-05">
			<div class="flex gap-05 align-items-center min-w-0">
				<span v-if="icon" class="bgl-stat__icon grid place-items-center flex-shrink-0" :style="{ color: accent, background: `color-mix(in srgb, ${accent} 12%, transparent)` }">
					<Icon :name="icon" :size="1.1" />
				</span>
				<div class="min-w-0">
					<p class="txt13 opacity-6 m-0 ellipsis-1">{{ label }}</p>
					<p v-if="subtitle" class="txt12 color-gray m-0 ellipsis-1">{{ subtitle }}</p>
				</div>
			</div>
			<span v-if="hasChange" class="bgl-stat__delta inline-flex align-items-center flex-shrink-0 semibold" :class="good ? 'bgl-stat__delta--up' : 'bgl-stat__delta--down'">
				<Icon :name="up ? 'trending_up' : 'trending_down'" :size="0.9" />
				{{ Math.abs(change!).toFixed(1) }}%
			</span>
		</div>

		<div class="flex space-between w-100p align-items-end gap-1">
			<span class="txt28 m_txt24 semibold line-height-1 tabular-nums" :class="{ 'opacity-4': loading }">{{ loading ? '…' : formatted }}</span>
			<Sparkline v-if="trend?.length" :data="trend" :color="color" area class="flex-shrink-0 opacity-9" :width="96" :height="32" />
		</div>
	</Card>
</template>

<style scoped>
.bgl-stat__icon { width: 34px; height: 34px; border-radius: 9px; }
/* Delta chip: layout via utilities; pill shape + sizing stay here. */
.bgl-stat__delta { gap: 0.15rem; font-size: 0.78rem; padding: 0.1rem 0.4rem; border-radius: 999px; }
.bgl-stat__delta--up { color: var(--bgl-green); background: color-mix(in srgb, var(--bgl-green) 12%, transparent); }
.bgl-stat__delta--down { color: var(--bgl-red); background: color-mix(in srgb, var(--bgl-red) 12%, transparent); }
</style>
