<template>
  <v-dialog v-model="dialog" max-width="800" scrollable>
    <v-card class="tw:overflow-hidden">
      <v-card-title class="tw:flex tw:items-center tw:justify-between tw:gap-2">
        <span class="tw:text-lg tw:font-semibold">{{ title }}</span>
        <v-btn icon="mdi-close" size="small" variant="text" @click="close" />
      </v-card-title>

      <v-divider />

      <v-card-text class="tw:py-4">
        <v-alert :type="type" variant="tonal" class="tw:mb-4">
          <div class="tw:text-base tw:font-medium tw:mb-2">
            {{ message }}
          </div>
          <div class="tw:text-sm">
            {{ $t("core.itemsCount") }}:
            <strong>{{ itemCount }}</strong>
          </div>
        </v-alert>

        <div v-if="showItems && renderedItems.length > 0">
          <div class="tw:text-xs tw:uppercase tw:font-semibold tw:opacity-60 tw:mb-2">
            {{ $t("core.selectedItems") }}
          </div>

          <v-list density="compact" class="tw:border tw:rounded-md tw:py-0">
            <v-list-item
              v-for="item in renderedItems"
              :key="item.key"
              class="tw:py-2"
            >
              <template #title>
                <span class="tw:text-sm tw:font-medium">{{ item.title }}</span>
              </template>

              <template #subtitle>
                <pre
                  v-if="item.kind === 'pre'"
                  class="tw:mt-1 tw:text-xs tw:font-mono tw:p-2 tw:max-h-44 tw:overflow-auto tw:rounded tw:bg-black/5 dark:tw:bg-white/5 tw:whitespace-pre-wrap tw:break-all"
                >{{ item.text }}</pre>
                <div v-else class="tw:mt-1 tw:text-sm tw:opacity-80 tw:break-all">
                  {{ item.text }}
                </div>
              </template>
            </v-list-item>
          </v-list>
        </div>
      </v-card-text>

      <v-divider />

      <v-card-actions class="tw:px-4 tw:py-3">
        <v-spacer />
        <v-btn variant="text" @click="close">
          {{ cancelText || $t("core.close") }}
        </v-btn>
        <v-btn
          v-if="showConfirm"
          :color="type === 'warning' ? 'warning' : type === 'error' ? 'error' : 'primary'"
          variant="flat"
          @click="confirm"
        >
          {{ confirmText }}
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<script setup lang="ts">
import { computed } from "vue"
import { useI18n } from "vue-i18n"

interface Props {
  modelValue: boolean
  items: any[]
  title: string
  message: string
  type?: "info" | "success" | "warning" | "error"
  showItems?: boolean
  showConfirm?: boolean
  displayAttribute: string
  confirmText?: string
  cancelText?: string
}

const props = withDefaults(defineProps<Props>(), {
  type: "info",
  showItems: true,
  showConfirm: false,
})

const emit = defineEmits<{
  "update:modelValue": [value: boolean]
  confirm: []
}>()
const { t } = useI18n()

const dialog = computed({
  get: () => props.modelValue,
  set: (value) => emit("update:modelValue", value),
})

const itemCount = computed(() => props.items.length)

const close = () => {
  dialog.value = false
}

type SummaryRenderKind = "text" | "pre"

interface SummaryRenderItem {
  key: string
  title: string
  kind: SummaryRenderKind
  text: string
}

interface SummaryFormatter {
  kind: SummaryRenderKind
  canHandle: (value: unknown) => boolean
  format: (value: unknown) => string
}

const formatAsText = (value: unknown): string => {
  if (value === null || value === undefined) return "-"
  return String(value)
}

const objectJsonFormatter: SummaryFormatter = {
  kind: "pre",
  canHandle: (value) =>
    value !== null && typeof value === "object" && !Array.isArray(value),
  format: (value) => JSON.stringify(value, null, 2),
}

const arrayJsonFormatter: SummaryFormatter = {
  kind: "pre",
  canHandle: (value) => Array.isArray(value),
  format: (value) => JSON.stringify(value, null, 2),
}

const primitiveFormatter: SummaryFormatter = {
  kind: "text",
  canHandle: () => true,
  format: (value) => formatAsText(value),
}

// TODO(summary-formatters): Add XML formatter when import/export surfaces XML payloads.
// TODO(summary-formatters): Add CSV formatter with row/column-aware preview rendering.
// TODO(summary-formatters): Add image formatter for URL/blob metadata and thumbnail previews.
const summaryFormatters: SummaryFormatter[] = [
  objectJsonFormatter,
  arrayJsonFormatter,
  primitiveFormatter,
]

const resolveFormatter = (value: unknown): SummaryFormatter => {
  return (
    summaryFormatters.find((formatter) => formatter.canHandle(value)) ??
    primitiveFormatter
  )
}

const formatDisplayTitle = (item: unknown, index: number): string => {
  if (!item || typeof item !== "object" || Array.isArray(item)) {
    return `${t("core.selectedItems")} #${index + 1}`
  }

  const record = item as Record<string, unknown>
  const attributeValue = record[props.displayAttribute]
  if (attributeValue !== undefined && attributeValue !== null) {
    return formatAsText(attributeValue)
  }
  if (record._id !== undefined && record._id !== null) {
    return formatAsText(record._id)
  }
  return `${t("core.selectedItems")} #${index + 1}`
}

const getDisplayPayload = (item: unknown): unknown => {
  if (!item || typeof item !== "object" || Array.isArray(item)) {
    return item
  }

  const record = item as Record<string, unknown>
  const payload = { ...record }
  delete payload[props.displayAttribute]
  return payload
}

const renderedItems = computed<SummaryRenderItem[]>(() =>
  props.items.map((item, index) => {
    const payload = getDisplayPayload(item)
    const formatter = resolveFormatter(payload)

    return {
      key: `${index}-${formatDisplayTitle(item, index)}`,
      title: formatDisplayTitle(item, index),
      kind: formatter.kind,
      text: formatter.format(payload),
    }
  }),
)

const confirm = () => {
  emit("confirm")
  close()
}
</script>
