<script setup lang="ts">
// A consumer `class` lands on the positioning wrapper (the root) like any normal
// component — so spacing/layout utilities (mb-2, me-2, …) work as expected. To
// style the inner rounded/clipped element (e.g. a custom background that must
// stay circular), use the `innerClass` prop — mirrors `triggerClass` on Dropdown.
defineOptions({ name: 'BglAvatar' })
import type { IconType, ThemeType } from '@bagelink/vue'
import { initials, Icon } from '@bagelink/vue'
import { computed } from 'vue'
import Image from './Image.vue'

const props = withDefaults(defineProps<{
	fallback?: string
	src?: string
	name?: string
	icon?: IconType
	alt?: string
	size?: number
	/** Rounded-square instead of a circle. `true` = themed radius, or pass a px radius. */
	square?: boolean | number
	/** Theme color → tinted background + matching icon/text color (e.g. an icon chip). */
	color?: ThemeType
	/** Presence/status dot in the corner. `true` = green "online", or a ThemeType
	    (e.g. 'gray' offline, 'orange' away, 'red' busy). */
	status?: boolean | ThemeType
	/** Accessible label / tooltip for the status dot. */
	statusTitle?: string
	/** Class applied to the inner rounded/clipped avatar element (vs. the wrapper). */
	innerClass?: string
}>(), { size: 50 })

const statusColor = computed(() => (props.status === true ? 'green' : props.status || null))
// Dot scales with the avatar but stays within sane bounds.
const dotSize = computed(() => Math.max(7, Math.min(14, Math.round(props.size * 0.28))))

const radius = computed(() => {
	if (!props.square) { return '1000px' } // circle (default)
	if (props.square === true) { return 'var(--bgl-btn-border-radius)' }
	return `${props.square}px`
})

// When a theme color is given, tint the background and color the icon/initials.
// Mix straight from the live --bgl-<color> so it always matches the foreground —
// notably for `primary`, whose pre-baked --bgl-primary-tint token can resolve to a
// different (default) hue when an app overrides --bgl-primary in a nested scope.
const themed = computed(() => props.color
	? { background: `color-mix(in srgb, var(--bgl-${props.color}) 14%, transparent)`, color: `var(--bgl-${props.color})`, border: 'none' }
	: {})
</script>

<template>
	<div class="avatar-wrap" :style="{ width: `${size}px`, height: `${size}px` }">
		<div
			class="overflow-hidden txt-center p-0 avatar flex justify-content-center align-items-center"
			:class="innerClass"
			:style="{ width: `${size}px`, height: `${size}px`, borderRadius: radius, ...themed }"
		>
			<Image v-if="src" :src="src" :alt="alt || name" />
			<Icon v-else-if="icon" :icon="icon" :size="size / 40" />
			<p v-else :style="{ 'line-height': `${size}px`, 'font-size': `calc(1.5rem * ${size} / 50)` }">
				{{ (fallback || initials(name || '')).toUpperCase() }}
			</p>
		</div>
		<span
			v-if="statusColor" class="avatar-status" :title="statusTitle"
			:style="{ width: `${dotSize}px`, height: `${dotSize}px`, background: `var(--bgl-${statusColor})` }"
		/>
	</div>
</template>

<style scoped>

.avatar-wrap {
position: relative;
flex-shrink: 0;
display: inline-flex;
}

.avatar {
background-color: var(--bgl-gray-tint);
border: 0.5px solid var(--bgl-border-color);
flex-shrink: 0;
}

/* Presence dot — sits over the bottom-trailing corner, ringed by the surface
   color so it reads cleanly on any background. */
.avatar-status {
position: absolute;
inset-block-end: 0;
inset-inline-end: 0;
border-radius: 50%;
box-shadow: 0 0 0 2px var(--bgl-box-bg, #fff);
}

.avatar p {
font-size: 1.5rem;
line-height: 50px;
margin: 0;
font-weight: 200;
}

.avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}

</style>
