<template>
  <div class="flex flex-col gap-8">
    <UCard class="brand-card border border-transparent backdrop-blur-sm">
      <template #header>
        <div class="flex flex-col gap-2">
          <h2 class="text-xl font-semibold text-[var(--brand-text)]">Constructor de consultas</h2>
          <p class="text-sm text-[var(--brand-text-muted)]">
            Arma solicitudes a los endpoints del backend y visualiza los resultados en modo lectura.
          </p>
        </div>
      </template>

      <form class="flex flex-col gap-6" @submit.prevent="executeRequest">
        <div class="grid gap-4 lg:grid-cols-4">
          <UFormField label="Tipo de consulta" name="type">
            <USelectMenu v-model="request.type" :items="requestTypeOptions" value-key="value" />
          </UFormField>

          <UFormField label="Ámbito" name="scope">
            <USelectMenu v-model="request.scope" :items="scopeOptions" value-key="value" />
          </UFormField>

          <UFormField v-if="requiresTable" label="Tabla" name="table">
            <USelectMenu
              v-model="request.table"
              :items="tableOptions"
              value-key="value"
              placeholder="Selecciona una tabla"
            />
          </UFormField>

          <UFormField v-if="showsLimit" label="Límite" name="limit">
            <UInput v-model.number="request.limit" type="number" min="1" max="500" />
          </UFormField>

          <UFormField v-if="requiresRecordId" label="ID del registro" name="recordId">
            <UInput v-model="request.recordId" placeholder="Introduce el ID exacto" />
          </UFormField>

          <UFormField v-if="showsIdFilter" label="Filtrar por ID" name="filterId">
            <UInput v-model="request.filterId" placeholder="Opcional" />
          </UFormField>

          <UFormField v-if="showsDateFilters" label="Fecha desde" name="createdFrom">
            <UInput v-model="request.createdFrom" type="date" />
          </UFormField>

          <UFormField v-if="showsDateFilters" label="Fecha hasta" name="createdTo">
            <UInput v-model="request.createdTo" type="date" />
          </UFormField>
        </div>

        <div v-if="showQueryJson" class="space-y-2">
          <UFormField label="Consulta avanzada (JSON)" name="queryJson">
            <UTextarea
              v-model="request.queryJson"
              :rows="5"
              placeholder='{ "filters": [{ "field": "estado", "operator": "eq", "value": "activo" }] }'
            />
          </UFormField>
          <p v-if="queryState.error" class="text-sm text-red-300">{{ queryState.error }}</p>
          <p v-else-if="queryState.encoded" class="text-xs text-[var(--brand-text-muted)]">
            Segmento codificado:
            <code class="rounded bg-[#2a2014] px-2 py-1 text-[var(--brand-accent)]">{{ queryState.encoded }}</code>
          </p>
          <p class="text-xs text-[var(--brand-text-muted)]">
            Se codifica automáticamente en base64-url para construir la ruta
            <code class="rounded bg-[#2a2014] px-2 py-1 text-[var(--brand-accent)]">
              /api/data/{{ request.table || ':tabla' }}/{{ queryState.encoded || ':query' }}
            </code>.
          </p>
        </div>

        <div class="flex flex-col gap-3 rounded-lg border border-[#3a2a16] bg-[#1c140c] px-4 py-3 shadow-inner shadow-black/30">
          <span class="text-xs font-semibold uppercase tracking-[0.28em] text-[var(--brand-text-muted)]">
            Solicitud generada
          </span>
          <code class="break-all text-sm text-[var(--brand-accent)]">GET {{ requestPreview }}</code>
        </div>

        <div class="flex justify-end gap-2">
          <UButton
            variant="soft"
            :ui="{ base: 'bg-transparent border border-[#3a2a16] text-[var(--brand-text-muted)] hover:bg-[#2a2014] hover:border-[#c08040]/60' }"
            @click="resetForm"
            :disabled="loading"
          >
            Limpiar
          </UButton>
          <UButton
            type="submit"
            :loading="loading"
            :ui="{ base: 'bg-[#c08040] text-[#1b1209] border border-[#d99a56] hover:bg-[#d99a56] hover:border-[#f0c07c]' }"
          >
            Ejecutar consulta
          </UButton>
        </div>
      </form>
    </UCard>

    <div v-if="errorMessage" class="rounded-lg border border-red-500/40 bg-red-500/18 p-4 text-sm text-red-200">
      {{ errorMessage }}
    </div>

    <section v-if="hasMetadataResponse" class="flex flex-col gap-5">
      <div v-if="metadataCollection.length" class="grid gap-5 md:grid-cols-2">
        <UCard v-for="meta in metadataCollection" :key="meta.table" class="brand-card border border-transparent">
          <template #header>
            <div class="flex items-center justify-between">
              <h2 class="text-lg font-semibold brand-section-title">Tabla {{ meta.table }}</h2>
              <span class="brand-badge inline-flex items-center gap-1 rounded-full px-3 py-1 text-xs font-semibold tracking-wide">
                {{ meta.rowCount }} registros
              </span>
            </div>
          </template>
          <dl class="grid grid-cols-2 gap-3 text-sm text-[var(--brand-text-muted)]">
            <div>
              <dt class="uppercase tracking-wide text-xs">Clave primaria</dt>
              <dd class="font-medium text-[var(--brand-text)]">{{ meta.primaryKey }}</dd>
            </div>
            <div>
              <dt class="uppercase tracking-wide text-xs">Tamaño aprox.</dt>
              <dd class="font-medium text-[var(--brand-text)]">{{ formatSize(meta.approxSizeBytes) }}</dd>
            </div>
            <div>
              <dt class="uppercase tracking-wide text-xs">Creación desde</dt>
              <dd class="font-medium text-[var(--brand-text)]">{{ formatDate(meta.createdAtRange?.from) }}</dd>
            </div>
            <div>
              <dt class="uppercase tracking-wide text-xs">Creación hasta</dt>
              <dd class="font-medium text-[var(--brand-text)]">{{ formatDate(meta.createdAtRange?.to) }}</dd>
            </div>
          </dl>
          <template #footer>
            <div class="brand-divider pt-3 text-xs text-[var(--brand-text-muted)]">
              Columnas detectadas: {{ meta.columns.join(', ') }}
            </div>
          </template>
        </UCard>
      </div>

      <div v-else-if="activeMetadata" class="grid gap-5 md:grid-cols-2">
        <UCard class="brand-card border border-transparent">
          <template #header>
            <div class="flex items-center justify-between">
              <h2 class="text-lg font-semibold brand-section-title">Resumen de {{ activeMetadata.table }}</h2>
              <span class="brand-badge inline-flex items-center gap-1 rounded-full px-3 py-1 text-xs font-semibold tracking-wide">
                {{ activeMetadata.rowCount }} registros
              </span>
            </div>
          </template>
          <dl class="grid grid-cols-2 gap-3 text-sm text-[var(--brand-text-muted)]">
            <div>
              <dt class="uppercase tracking-wide text-xs">Clave primaria</dt>
              <dd class="font-medium text-[var(--brand-text)]">{{ activeMetadata.primaryKey }}</dd>
            </div>
            <div>
              <dt class="uppercase tracking-wide text-xs">Última consulta</dt>
              <dd class="font-medium text-[var(--brand-text)]">{{ formatDate(activeMetadata.lastRefreshed) }}</dd>
            </div>
            <div>
              <dt class="uppercase tracking-wide text-xs">Tamaño aprox.</dt>
              <dd class="font-medium text-[var(--brand-text)]">{{ formatSize(activeMetadata.approxSizeBytes) }}</dd>
            </div>
            <div>
              <dt class="uppercase tracking-wide text-xs">Rango de creación</dt>
              <dd class="font-medium text-[var(--brand-text)]">
                {{ formatDate(activeMetadata.createdAtRange?.from) }} — {{ formatDate(activeMetadata.createdAtRange?.to) }}
              </dd>
            </div>
          </dl>
          <template #footer>
            <div class="brand-divider pt-3 text-xs text-[var(--brand-text-muted)]">
              Columnas detectadas: {{ activeMetadata.columns.join(', ') }}
            </div>
          </template>
        </UCard>

        <UCard v-if="activeMetadata.sampleRow" class="brand-card border border-transparent">
          <template #header>
            <h2 class="text-lg font-semibold brand-section-title">Registro de ejemplo</h2>
          </template>
          <pre class="overflow-auto rounded bg-[#22180f] p-4 text-sm text-[var(--brand-text-muted)]">
            {{ formatSample(activeMetadata.sampleRow) }}
          </pre>
        </UCard>
      </div>

      <UCard v-if="metadataRecord" class="brand-card border border-transparent">
        <template #header>
          <h2 class="text-lg font-semibold brand-section-title">Metadata del registro {{ metadataRecord.id }}</h2>
        </template>
        <pre class="overflow-auto rounded bg-[#22180f] p-4 text-sm text-[var(--brand-text-muted)]">
          {{ formatSample(metadataRecord.metadata) }}
        </pre>
      </UCard>
    </section>

    <UCard v-if="request.type === 'data' || hasDataResponse" class="brand-card border border-transparent">
      <template #header>
        <div class="flex flex-wrap items-center justify-between gap-3">
          <h2 class="text-lg font-semibold brand-section-title">Datos</h2>
          <div class="flex flex-wrap gap-2 text-xs text-[var(--brand-text-muted)]">
            <template v-if="dataStats">
              <span class="brand-pill inline-flex items-center gap-2 rounded-full px-3 py-1 text-xs">
                {{ dataStats.table }}: {{ dataStats.count }} registros (límite {{ dataStats.limit ?? 's/d' }})
              </span>
            </template>
            <template v-else-if="dataStatsCollection.length">
              <span
                v-for="item in dataStatsCollection"
                :key="item.table"
                class="brand-pill inline-flex items-center gap-2 rounded-full px-3 py-1 text-xs"
              >
                {{ item.table }}: {{ item.count }} registros (límite {{ item.limit ?? 's/d' }})
              </span>
            </template>
            <span v-else-if="tableData.length" class="brand-pill inline-flex items-center gap-2 rounded-full px-3 py-1 text-xs">
              {{ tableData.length }} registros visibles
            </span>
          </div>
        </div>
      </template>

      <div v-if="loading" class="flex items-center justify-center gap-3 py-10 text-[var(--brand-text-muted)]">
        <span class="inline-flex h-8 w-8 animate-spin rounded-full border-2 border-[#c08040] border-t-transparent align-middle" aria-hidden="true" />
        <span class="text-sm uppercase tracking-[0.3em]">Procesando…</span>
      </div>
      <div v-else-if="!hasDataResponse" class="py-10 text-center text-sm text-[var(--brand-text-muted)]">
        Ejecuta una consulta de datos para ver resultados aquí.
      </div>
      <div v-else-if="tableData.length === 0" class="py-10 text-center text-sm text-[var(--brand-text-muted)]">
        No se encontraron registros para los criterios seleccionados.
      </div>
      <div v-else class="overflow-auto">
        <table class="brand-table min-w-full divide-y divide-[#3a2a16]/60 text-sm">
          <thead>
            <tr>
              <th
                v-for="column in visibleColumns"
                :key="column"
                class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-[0.18em] text-[var(--brand-text-muted)]"
              >
                {{ column }}
              </th>
            </tr>
          </thead>
          <tbody class="brand-table divide-y divide-[#3a2a16]/40">
            <tr v-for="(row, index) in tableData" :key="index" class="transition-colors">
              <td v-for="column in visibleColumns" :key="column" class="px-4 py-2 text-sm text-[var(--brand-text-muted)]">
                {{ formatCell(row[column]) }}
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </UCard>

    <UCard v-if="rawResponse" class="brand-card border border-transparent">
      <template #header>
        <h2 class="text-lg font-semibold brand-section-title">Respuesta cruda (JSON)</h2>
      </template>
      <pre class="max-h-96 overflow-auto rounded bg-[#22180f] p-4 text-sm text-[var(--brand-text-muted)]">
        {{ formatSample(rawResponse) }}
      </pre>
    </UCard>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { useRequestFetch } from '#imports'

definePageMeta({
  layout: 'dashboard',
  title: 'Explorador de datos'
})

type RequestType = 'data' | 'metadata'
type MetadataScope = 'all' | 'table' | 'record'
type DataScope = 'all' | 'table' | 'record' | 'query'
type RequestScope = MetadataScope | DataScope

interface Option<T extends string> {
  label: string
  value: T
}

const requestTypeOptions: Option<RequestType>[] = [
  { label: 'Datos', value: 'data' },
  { label: 'Metadatos', value: 'metadata' }
]

const metadataScopeOptions: Option<MetadataScope>[] = [
  { label: 'Todas las tablas', value: 'all' },
  { label: 'Por tabla', value: 'table' },
  { label: 'Registro específico', value: 'record' }
]

const dataScopeOptions: Option<DataScope>[] = [
  { label: 'Todas las tablas', value: 'all' },
  { label: 'Por tabla', value: 'table' },
  { label: 'Registro específico', value: 'record' },
  { label: 'Consulta avanzada', value: 'query' }
]

const DEFAULT_METADATA_SCOPE: MetadataScope = 'all'
const DEFAULT_DATA_SCOPE: DataScope = 'table'

const requestFetch = useRequestFetch()

const request = reactive<{
  type: RequestType
  scope: RequestScope
  table: string
  recordId: string
  filterId: string
  createdFrom: string
  createdTo: string
  limit: number
  queryJson: string
}>(
  {
    type: 'data',
    scope: DEFAULT_DATA_SCOPE,
    table: '',
    recordId: '',
    filterId: '',
    createdFrom: '',
    createdTo: '',
    limit: 100,
    queryJson: ''
  }
)

const loading = ref(false)
const errorMessage = ref<string | null>(null)
const rawResponse = ref<unknown>(null)

const availableMetadata = ref<any[]>([])
const metadataCollection = ref<any[]>([])
const metadataRecord = ref<any | null>(null)
const activeMetadata = ref<any | null>(null)

const tableData = ref<Record<string, unknown>[]>([])
const dataStats = ref<{ table: string; count: number; limit?: number | null } | null>(null)
const dataStatsCollection = ref<{ table: string; count: number; limit?: number | null }[]>([])

const hasDataResponse = ref(false)
const hasMetadataResponse = ref(false)

const scopeOptions = computed(() => (request.type === 'metadata' ? metadataScopeOptions : dataScopeOptions))

const requiresTable = computed(() => request.scope !== 'all')
const requiresRecordId = computed(() => request.scope === 'record')

const showsLimit = computed(
  () => request.type === 'data' && (request.scope === 'all' || request.scope === 'table' || request.scope === 'query')
)

const showsDateFilters = computed(() => request.type === 'data' && request.scope === 'table')
const showsIdFilter = computed(() => request.type === 'data' && request.scope === 'table')
const showQueryJson = computed(() => request.type === 'data' && request.scope === 'query')

const tableOptions = computed(() =>
  availableMetadata.value.map((meta) => ({
    label: `${meta.table} (${meta.rowCount ?? '—'})`,
    value: meta.table
  }))
)

const visibleColumns = computed(() => (tableData.value[0] ? Object.keys(tableData.value[0]) : []))

const queryState = computed(() => {
  if (!showQueryJson.value) {
    return { encoded: '', error: null as string | null }
  }

  const trimmed = request.queryJson.trim()

  if (!trimmed) {
    return { encoded: '', error: null as string | null }
  }

  try {
    const parsed = JSON.parse(trimmed)
    const normalized = JSON.stringify(parsed)
    return { encoded: encodeBase64Url(normalized), error: null as string | null }
  } catch (error) {
    return { encoded: '', error: 'El JSON proporcionado no es válido.' }
  }
})

const requestPreview = computed(() => {
  const base = request.type === 'metadata' ? '/api/metadata' : '/api/data'
  let path = base
  const params = new URLSearchParams()
  const limit = sanitizeLimit(request.limit)

  if (request.type === 'metadata') {
    if (request.scope === 'table') {
      path += `/${request.table || ':tabla'}`
    } else if (request.scope === 'record') {
      path += `/${request.table || ':tabla'}/${request.recordId || ':id'}`
    }
  } else {
    if (request.scope === 'all') {
      params.set('limit', String(limit))
    } else if (request.scope === 'table') {
      path += `/${request.table || ':tabla'}`
      params.set('limit', String(limit))
      if (request.filterId) params.set('id', request.filterId.trim())
      if (request.createdFrom) params.set('created_from', request.createdFrom)
      if (request.createdTo) params.set('created_to', request.createdTo)
    } else if (request.scope === 'record') {
      path += `/${request.table || ':tabla'}/${request.recordId || ':id'}`
    } else if (request.scope === 'query') {
      const segment = queryState.value.encoded || ':query-base64'
      path += `/${request.table || ':tabla'}/${segment}`
      params.set('limit', String(limit))
    }
  }

  const queryString = params.toString()
  return queryString ? `${path}?${queryString}` : path
})

onMounted(async () => {
  await loadAvailableMetadata()
})

watch(
  () => request.type,
  (type) => {
    request.scope = type === 'metadata' ? DEFAULT_METADATA_SCOPE : DEFAULT_DATA_SCOPE
    request.recordId = ''
    request.filterId = ''
    request.createdFrom = ''
    request.createdTo = ''
    request.queryJson = ''
    clearResults()

    if (requiresTable.value && !request.table && availableMetadata.value.length > 0) {
      request.table = availableMetadata.value[0].table
    }
  }
)

watch(
  () => request.scope,
  () => {
    if (!requiresTable.value) {
      request.table = ''
    } else if (!request.table && availableMetadata.value.length > 0) {
      request.table = availableMetadata.value[0].table
    }

    if (!requiresRecordId.value) {
      request.recordId = ''
    }

    if (!showsIdFilter.value) {
      request.filterId = ''
    }

    if (!showsDateFilters.value) {
      request.createdFrom = ''
      request.createdTo = ''
    }
  }
)

async function loadAvailableMetadata() {
  try {
    const metadata = await requestFetch('/api/metadata')
    if (Array.isArray(metadata)) {
      availableMetadata.value = metadata
      useState('availableMetadataSummary', () => metadata).value = metadata
      useState('dashboardLastUpdated', () => new Date().toISOString()).value = new Date().toISOString()
      if (!request.table && requiresTable.value && metadata.length > 0) {
        request.table = metadata[0].table
      }
    }
  } catch (error) {
    errorMessage.value = extractErrorMessage(error)
  }
}

function sanitizeLimit(value: number) {
  if (!Number.isFinite(value)) {
    return 100
  }
  return Math.max(1, Math.min(500, Math.trunc(value)))
}

function encodeBase64Url(value: string) {
  if (typeof globalThis !== 'undefined' && typeof globalThis.btoa === 'function') {
    const encoded = globalThis.btoa(
      encodeURIComponent(value).replace(/%([0-9A-F]{2})/g, (_, hex) => String.fromCharCode(Number.parseInt(hex, 16)))
    )

    return encoded.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '')
  }

  return Buffer.from(value, 'utf-8').toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '')
}

function clearResults() {
  metadataCollection.value = []
  metadataRecord.value = null
  activeMetadata.value = null
  tableData.value = []
  dataStats.value = null
  dataStatsCollection.value = []
  rawResponse.value = null
  hasDataResponse.value = false
  hasMetadataResponse.value = false
}

function resetForm() {
  request.scope = request.type === 'metadata' ? DEFAULT_METADATA_SCOPE : DEFAULT_DATA_SCOPE
  request.table = availableMetadata.value[0]?.table ?? ''
  request.recordId = ''
  request.filterId = ''
  request.createdFrom = ''
  request.createdTo = ''
  request.limit = 100
  request.queryJson = ''
  clearResults()
}

function buildExecutableRequest() {
  const base = request.type === 'metadata' ? '/api/metadata' : '/api/data'
  let path = base
  const query: Record<string, string> = {}

  if (request.type === 'metadata') {
    if (request.scope === 'all') {
      return { url: path, query, error: null as string | null }
    }

    if (!request.table) {
      return { url: '', query, error: 'Selecciona una tabla antes de ejecutar la consulta.' }
    }

    path += `/${request.table}`

    if (request.scope === 'record') {
      if (!request.recordId.trim()) {
        return { url: '', query, error: 'Introduce el ID del registro que deseas consultar.' }
      }

      path += `/${request.recordId.trim()}`
    }

    return { url: path, query, error: null }
  }

  if (request.scope === 'all') {
    query.limit = String(sanitizeLimit(request.limit))
    return { url: path, query, error: null }
  }

  if (!request.table) {
    return { url: '', query, error: 'Selecciona una tabla antes de ejecutar la consulta.' }
  }

  if (request.scope === 'table') {
    path += `/${request.table}`
    query.limit = String(sanitizeLimit(request.limit))
    if (request.filterId) {
      query.id = request.filterId.trim()
    }
    if (request.createdFrom) {
      query.created_from = request.createdFrom
    }
    if (request.createdTo) {
      query.created_to = request.createdTo
    }
    return { url: path, query, error: null }
  }

  if (request.scope === 'record') {
    if (!request.recordId.trim()) {
      return { url: '', query, error: 'Introduce el ID del registro que deseas consultar.' }
    }

    path += `/${request.table}/${request.recordId.trim()}`
    return { url: path, query, error: null }
  }

  if (!request.queryJson.trim()) {
    return { url: '', query, error: 'Introduce un JSON para la consulta avanzada.' }
  }

  if (queryState.value.error) {
    return { url: '', query, error: queryState.value.error }
  }

  path += `/${request.table}/${queryState.value.encoded}`
  query.limit = String(sanitizeLimit(request.limit))

  return { url: path, query, error: null }
}

async function executeRequest() {
  const requestConfig = buildExecutableRequest()

  if (requestConfig.error) {
    errorMessage.value = requestConfig.error
    return
  }

  loading.value = true
  errorMessage.value = null

  try {
    const response = await requestFetch(requestConfig.url, {
      query: requestConfig.query
    })

    processResponse(response)
    rawResponse.value = response
  } catch (error) {
    clearResults()
    errorMessage.value = extractErrorMessage(error)
  } finally {
    loading.value = false
  }
}

function processResponse(response: unknown) {
  metadataCollection.value = []
  metadataRecord.value = null
  activeMetadata.value = null
  tableData.value = []
  dataStats.value = null
  dataStatsCollection.value = []

  if (request.type === 'metadata') {
    hasMetadataResponse.value = true

    if (Array.isArray(response)) {
      metadataCollection.value = response
      availableMetadata.value = response
      useState('availableMetadataSummary', () => response).value = response
      useState('dashboardLastUpdated', () => new Date().toISOString()).value = new Date().toISOString()
    } else if (request.scope === 'record' && response && typeof response === 'object') {
      metadataRecord.value = response
    } else {
      activeMetadata.value = response

      if (response && typeof response === 'object' && 'table' in response) {
        const index = availableMetadata.value.findIndex((item) => item.table === (response as any).table)
        if (index >= 0) {
          availableMetadata.value[index] = response
        }
      }
    }

    return
  }

  hasDataResponse.value = true

  if (request.scope === 'all' && Array.isArray(response)) {
    const datasets = response as Array<{
      table: string
      count?: number | null
      limit?: number | null
      records?: Record<string, unknown>[]
    }>

    dataStatsCollection.value = datasets.map((item) => ({
      table: item.table,
      count: item.count ?? item.records?.length ?? 0,
      limit: item.limit ?? null
    }))

    tableData.value = datasets.flatMap((item) => {
      const rows = Array.isArray(item.records) ? item.records : []
      return rows.map((row) => ({ __tabla: item.table, ...row }))
    })

    return
  }

  if (request.scope === 'record') {
    tableData.value = response ? [response as Record<string, unknown>] : []
    dataStats.value = {
      table: request.table,
      count: tableData.value.length,
      limit: null
    }

    return
  }

  if (response && typeof response === 'object' && 'records' in response) {
    const dataset = response as {
      table: string
      count?: number | null
      limit?: number | null
      records?: Record<string, unknown>[]
    }

    const rows = Array.isArray(dataset.records) ? dataset.records : []
    tableData.value = rows
    dataStats.value = {
      table: dataset.table,
      count: dataset.count ?? rows.length,
      limit: dataset.limit ?? null
    }

    return
  }

  tableData.value = Array.isArray(response) ? (response as Record<string, unknown>[]) : []
}

function extractErrorMessage(error: unknown) {
  if (error && typeof error === 'object' && 'statusMessage' in error) {
    return String((error as { statusMessage: string }).statusMessage)
  }

  if (error instanceof Error) {
    return error.message
  }

  return 'Ocurrió un error inesperado al consultar los datos.'
}

function formatSize(bytes: number | null | undefined) {
  if (!bytes) {
    return 'No disponible'
  }

  if (bytes < 1024) {
    return `${bytes} B`
  }

  const units = ['KB', 'MB', 'GB']
  let size = bytes / 1024
  let unitIndex = 0

  while (size >= 1024 && unitIndex < units.length - 1) {
    size /= 1024
    unitIndex += 1
  }

  return `${size.toFixed(1)} ${units[unitIndex]}`
}

function formatDate(value: string | null | undefined) {
  if (!value) {
    return '—'
  }

  const date = new Date(value)

  if (Number.isNaN(date.getTime())) {
    return value
  }

  return date.toLocaleString()
}

function formatCell(value: unknown) {
  if (value === null || value === undefined) {
    return '—'
  }

  if (value instanceof Date) {
    return value.toISOString()
  }

  if (typeof value === 'object') {
    try {
      return JSON.stringify(value)
    } catch (error) {
      return '[objeto]'
    }
  }

  return String(value)
}

function formatSample(value: unknown) {
  try {
    return JSON.stringify(value, null, 2)
  } catch (error) {
    return String(value)
  }
}
</script>
