<script setup lang="ts">
defineOptions({ name: 'BglAlert' })
import type { IconType } from '@bagelink/vue'
import { Icon } from '@bagelink/vue'
import { computed, ref, useSlots } from 'vue'
import Btn from './Btn.vue'

type AlertType = 'info' | 'success' | 'warning' | 'error'

interface Props {
	message?: string
	/** Bold heading above the message / default slot. */
	title?: string
	thin?: boolean
	/** Border + transparent background (drops the tinted fill). */
	outline?: boolean
	/** Neutral surface card: standard box background + a subtle neutral
	    (non-accent) border. Only the icon/title keep the accent color — use
	    when a full tinted fill reads as too loud. */
	frame?: boolean
	dismissable?: boolean
	type?: AlertType
	/** Boolean shorthands: <Alert error>...</Alert> */
	info?: boolean
	success?: boolean
	warning?: boolean
	error?: boolean
	icon?: IconType | 'none'
}

const props = defineProps<Props>()
const slots = useSlots()

const computedType = computed<AlertType>(() => {
	if (props.type) { return props.type }
	if (props.error) { return 'error' }
	if (props.warning) { return 'warning' }
	if (props.success) { return 'success' }
	return 'info'
})

const isDismissed = ref(false)

const typeIcon: Record<AlertType, IconType> = {
	info: 'info',
	success: 'check_circle',
	warning: 'warning',
	error: 'error',
}
</script>

<template>
	<div v-if="!isDismissed" class="alert" :class="[computedType, { thin, outline, frame }]" :dismissable="dismissable">
		<Icon v-if="icon !== 'none'" class="alert_icon" :icon="icon || typeIcon[computedType]" :size="1.7" />
		<div class="alert_content">
			<p v-if="title" class="alert_title m-0">{{ title }}</p>
			<slot>
				<p class="m-0 light">
					{{ message }}
				</p>
			</slot>
		</div>
		<div v-if="slots.actions" class="alert_actions">
			<slot name="actions" />
		</div>
		<Btn flat thin class="alert_close" icon="close" @click="isDismissed = true" />
	</div>
</template>

<style scoped>
.alert {
  --alert-outline: var(--bgl-primary);
  --alert-bg: var(--bgl-primary-light);
  padding: var(--bgl-btn-padding);
  border-radius: var(--bgl-card-border-radius);
  background: var(--alert-bg);
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  position: relative;
}

.alert.info {
  --alert-outline: var(--bgl-primary);
  --alert-bg: var(--bgl-primary-light);
}

.alert.success {
  --alert-outline: var(--bgl-green);
  --alert-bg: var(--bgl-green-light);
}

.alert.warning {
  --alert-outline: var(--bgl-yellow);
  --alert-bg: var(--bgl-yellow-light);
}

.alert.error {
  --alert-outline: var(--bgl-red);
  --alert-bg: var(--bgl-red-light);
  color: var(--bgl-red);
}

.alert .alert_icon {
  color: var(--alert-outline);
}

.alert_content {
  flex: 1;
  min-width: 0;
}

.alert_title {
  font-weight: 600;
}

.alert_actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
  align-self: center;
}

.alert.thin {
  padding: 1rem;
}

.alert.outline {
  outline: 1px solid var(--alert-outline);
  background: unset;
}

/* frame: neutral surface card — box bg + subtle border tinted by the accent;
   accent stays on the icon/title only (use when a full tinted fill is too loud). */
.alert.frame {
  background: var(--bgl-box-bg);
  border: 1px solid color-mix(in srgb, var(--alert-outline) 35%, var(--bgl-border-color));
  color: inherit;
}

.alert_icon {
  line-height: 1;
}

.alert_close {
  display: none;
  position: absolute;
  inset-inline-end: 1.5rem;
}

.alert[dismissable="true"] .alert_close {
  display: block;
}

.alert[dismissable="true"] p {
  width: calc(100% - 5rem);
}
</style>
