<template>
  <button
    v-if="preview && src"
    type="button"
    class="vm-avatar"
    :style="boxStyle"
    :title="title"
    @click="open = true"
  >
    <img v-if="src" class="vm-avatar__img" :src="src" alt="" />
    <span v-else class="vm-avatar__fallback">{{ fallbackText }}</span>
  </button>
  <span v-else class="vm-avatar" :style="boxStyle">
    <img v-if="src" class="vm-avatar__img" :src="src" alt="" />
    <span v-else class="vm-avatar__fallback">{{ fallbackText }}</span>
  </span>

  <vm-preview-viewer
    v-if="preview && src"
    v-model:open="open"
    embedded
    :src="src"
    :name="displayName"
  />
</template>

<script setup lang="ts">
import { crudLabel } from '../style'
import { computed, ref } from 'vue'
import VmPreviewViewer from './vm-preview-viewer.vue'

defineOptions({ name: 'vm-avatar' })

const props = withDefaults(
  defineProps<{
    modelValue?: string | null
    name?: string
    /** 表格列从 scope 取昵称 */
    nameProp?: string
    scope?: Record<string, unknown>
    size?: number
    preview?: boolean
  }>(),
  {
    size: 32,
    preview: false,
  },
)

const open = ref(false)
const src = computed(() => (props.modelValue ? String(props.modelValue) : ''))

const displayName = computed(() => {
  if (props.name) return props.name
  if (props.nameProp && props.scope) {
    return String(props.scope[props.nameProp] || '?')
  }
  return '?'
})

const fallbackText = computed(() => displayName.value.slice(0, 1).toUpperCase())

const title = computed(() => displayName.value || crudLabel('avatar'))
const boxStyle = computed(() => ({
  width: `${props.size}px`,
  height: `${props.size}px`,
}))
</script>

<style lang="scss" scoped>
.vm-avatar {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: color-mix(in srgb, var(--brand) 12%, var(--card));
  vertical-align: middle;
  cursor: default;

  &:is(button) {
    cursor: pointer;

    &:hover {
      box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand) 24%, transparent);
    }
  }
}

.vm-avatar__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.vm-avatar__fallback {
  font-size: 12px;
  font-weight: 700;
  color: var(--brand);
}
</style>
