<template>
  <span v-if="floating" class="table-loading-anchor" aria-hidden="true"></span>
  <Teleport to="body" :disabled="!floating">
    <div
      class="table-loading"
      :class="[variant, tone, { 'screen-floating': floating, 'modal-floating': floating && blocking }]"
      role="status"
      :aria-label="ariaLabel"
      aria-live="polite"
    >
      <div class="table-loading-card">
        <span class="table-loading-spinner" aria-hidden="true"></span>
        <div class="table-loading-copy">
          <strong v-if="title">{{ title }}</strong>
          <p v-if="message">{{ message }}</p>
        </div>
      </div>
    </div>
  </Teleport>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  variant: {
    type: String,
    default: 'panel',
    validator: (value) => ['panel', 'detail', 'overlay', 'drawer', 'banner'].includes(value)
  },
  tone: {
    type: String,
    default: 'theme',
    validator: (value) => ['theme', 'sky', 'success'].includes(value)
  },
  title: { type: String, default: '' },
  message: { type: String, default: '' },
  icon: { type: String, default: 'mdi mdi-loading' },
  motion: {
    type: String,
    default: 'loop',
    validator: (value) => ['loop', 'entry'].includes(value)
  },
  floating: { type: Boolean, default: false },
  blocking: { type: Boolean, default: false },
  showSkeleton: { type: Boolean, default: true },
  skeletonRows: { type: Number, default: 5 }
})

const ariaLabel = computed(() => [props.title, props.message].filter(Boolean).join(', ') || 'Loading')
</script>

<style scoped>
.table-loading {
  width: 100%;
  color: #64748b;
}

.table-loading-card {
  width: min(420px, 100%);
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 14px;
  padding: 16px 18px;
  border: 1px solid rgba(148, 163, 184, 0.24);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.94);
  box-shadow:
    0 14px 34px rgba(15, 23, 42, 0.08),
    0 1px 0 rgba(255, 255, 255, 0.9) inset;
}

.table-loading-spinner {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border: 3px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.16);
  border-top-color: var(--theme-primary-active, #255b7d);
  border-radius: 999px;
  animation: table-loading-spin 820ms linear infinite;
}

.table-loading-copy {
  min-width: 0;
  display: grid;
  gap: 4px;
  text-align: left;
}

.table-loading-copy strong {
  color: #0f172a;
  font-size: 15px;
  line-height: 1.35;
  font-weight: 850;
}

.table-loading-copy p {
  margin: 0;
  color: #64748b;
  font-size: 13px;
  line-height: 1.55;
}

.table-loading-anchor {
  display: block;
  width: 0;
  height: 0;
  overflow: hidden;
}

.table-loading.screen-floating {
  position: fixed;
  inset: 0;
  z-index: 430;
  width: 100vw;
  height: 100dvh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgba(248, 250, 252, 0.10);
  pointer-events: none;
}

.table-loading.screen-floating.modal-floating {
  z-index: 560;
  background: rgba(15, 23, 42, 0.18);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  pointer-events: auto;
}

.table-loading.panel {
  min-height: 220px;
  display: grid;
  place-items: center;
  padding: 28px 24px;
}

.table-loading.panel.screen-floating {
  min-height: 100dvh;
  padding: 24px;
}

.table-loading.detail {
  min-height: 180px;
  display: grid;
  align-items: center;
  justify-items: center;
  padding: 22px 24px;
}

.table-loading.overlay,
.table-loading.drawer {
  display: grid;
  place-items: center;
  gap: 12px;
  text-align: center;
}

.table-loading.overlay {
  min-height: 0;
}

.table-loading.drawer {
  min-height: 160px;
}

.table-loading.banner {
  display: grid;
  place-items: center;
  min-height: 0;
  padding: 0;
  color: #255b7d;
}

.table-loading.banner .table-loading-card {
  width: 100%;
  padding: 10px 12px;
  border-radius: 8px;
  box-shadow: none;
}

.table-loading.banner .table-loading-spinner {
  width: 20px;
  height: 20px;
  border-width: 2px;
}

@keyframes table-loading-spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .table-loading-spinner {
    animation: none;
  }
}
</style>
