<script setup lang="ts">
import type { BlockData } from '@vigilkids/section-core'

import { safeUrl } from '@vigilkids/section-core'
import { computed } from 'vue'

import { useInlineEdit } from '../../../composables/useInlineEdit'
import {
  buildArticleImageInlineStyle,
  normalizeArticleImageDimension,
} from '../../../utils/article-image'

const props = defineProps<{
  blockOrder: string[]
  blocks: Record<string, BlockData>
  editorMode?: boolean
  settings: Record<string, unknown>
}>()

const emit = defineEmits<{
  (e: 'update:setting', key: string, value: unknown): void
  (e: 'update:block-setting', blockId: string, key: string, value: unknown): void
  (e: 'inline-edit-start', key: string): void
  (e: 'inline-edit-end'): void
  (e: 'undo-redo', action: 'redo' | 'undo'): void
}>()

const s = computed(() => props.settings)

const allowedAlignments = ['left', 'center', 'right'] as const
const allowedSizeModes = ['standard', 'wide', 'full', 'custom'] as const
const allowedFits = ['contain', 'cover'] as const
const allowedCornerRadii = ['none', 'sm', 'md', 'lg', 'xl'] as const

function normalizeOption<T extends string>(value: unknown, allowed: readonly T[], fallback: T): T {
  const normalized = typeof value === 'string' ? value : ''
  return (allowed as readonly string[]).includes(normalized) ? (normalized as T) : fallback
}

const alignment = computed(() => normalizeOption(s.value.alignment, allowedAlignments, 'center'))
const sizeMode = computed(() => normalizeOption(s.value.size_mode, allowedSizeModes, 'standard'))
const fit = computed(() => normalizeOption(s.value.fit, allowedFits, 'contain'))
const cornerRadius = computed(() =>
  normalizeOption(s.value.corner_radius, allowedCornerRadii, 'lg'),
)
const src = computed(() => (typeof s.value.src === 'string' ? String(s.value.src).trim() : ''))
const alt = computed(() => (typeof s.value.alt === 'string' ? String(s.value.alt) : ''))
const caption = computed(() =>
  typeof s.value.caption === 'string' ? String(s.value.caption).trim() : '',
)
const customWidth = computed(() =>
  sizeMode.value === 'custom' ? normalizeArticleImageDimension(s.value.custom_width) : undefined,
)
const customHeight = computed(() =>
  sizeMode.value === 'custom' ? normalizeArticleImageDimension(s.value.custom_height) : undefined,
)
const figureClass = computed(() => [
  'article-image',
  `article-image--align-${alignment.value}`,
  `article-image--size-${sizeMode.value}`,
  `article-image--fit-${fit.value}`,
  `article-image--radius-${cornerRadius.value}`,
])
const imageAttrs = computed(() => ({
  width: customWidth.value,
  height: customHeight.value,
}))
const imageStyle = computed(() =>
  sizeMode.value === 'custom'
    ? buildArticleImageInlineStyle(customWidth.value, customHeight.value)
    : {},
)

const { editableAttrs } = useInlineEdit({
  editorMode: () => !!props.editorMode,
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
  onEditStart: (key) => emit('inline-edit-start', key),
  onEditEnd: () => emit('inline-edit-end'),
  onUndoRedo: (action) => emit('undo-redo', action),
})
</script>

<template>
  <figure :class="figureClass">
    <img
      v-if="src"
      :alt="alt"
      :src="safeUrl(src)"
      :style="imageStyle"
      class="article-image__img"
      loading="lazy"
      v-bind="imageAttrs"
    />
    <figcaption v-if="caption" class="article-image__caption" v-bind="editableAttrs('caption')">
      {{ caption }}
    </figcaption>
  </figure>
</template>
