<template>
  <main class="container mx-auto px-6 py-10 space-y-8">
    <header class="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
      <div>
        <h1 class="text-3xl font-semibold text-base-content">Catalogue des produits</h1>
        <p class="text-sm text-base-content/70">
          Retrouvez l'ensemble des produits du catalogue, leurs informations fournisseurs et leurs catégories.
        </p>
      </div>
      <div class="flex flex-wrap gap-2">
        <NuxtLink to="/product/create" class="btn btn-primary btn-sm md:btn-md">
          Ajouter un produit
        </NuxtLink>
        <NuxtLink to="/product-category" class="btn btn-outline btn-sm md:btn-md">
          Gérer les catégories
        </NuxtLink>
      </div>
    </header>

    <section class="card border border-base-200 bg-base-100 shadow-sm">
      <div class="card-body space-y-4">
        <div class="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
          <div class="flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center">
            <label class="w-full sm:w-72">
              <span class="text-xs font-semibold uppercase tracking-wide text-base-content/70">Recherche</span>
              <input
                v-model="searchTerm"
                type="text"
                class="input input-bordered input-sm w-full mt-1"
                placeholder="Nom ou référence…"
              />
            </label>
            <div class="flex items-center gap-2">
              <label class="text-xs font-semibold uppercase tracking-wide text-base-content/70" for="product-sort">Trier par</label>
              <select
                id="product-sort"
                v-model="sortField"
                class="select select-bordered select-sm"
              >
                <option value="name">Nom</option>
                <option value="createdAt">Date de création</option>
              </select>
            </div>
            <div class="flex items-center gap-2">
              <label class="text-xs font-semibold uppercase tracking-wide text-base-content/70" for="product-dir">Ordre</label>
              <select
                id="product-dir"
                v-model="sortDirection"
                class="select select-bordered select-sm"
              >
                <option value="asc">Ascendant</option>
                <option value="desc">Descendant</option>
              </select>
            </div>
          </div>
          <p class="text-xs text-base-content/60 lg:text-right">
            {{ filteredCount }} / {{ totalCount }} résultat{{ filteredCount > 1 ? 's' : '' }}
          </p>
        </div>

        <div v-if="loading" class="flex justify-center py-10">
          <span class="loading loading-spinner" aria-hidden="true" />
        </div>

        <div
          v-else-if="errorMessage"
          class="alert alert-error"
        >
          <div class="flex flex-col gap-1">
            <span class="font-semibold">Impossible de charger les produits</span>
            <span class="text-sm">{{ errorMessage }}</span>
          </div>
          <button type="button" class="btn btn-ghost btn-sm ml-auto" @click="reload">
            Réessayer
          </button>
        </div>

        <p v-else-if="!hasLoaded" class="text-sm text-base-content/70">
          Chargement du catalogue…
        </p>

        <p v-else-if="!normalizedProducts.length" class="text-sm text-base-content/70">
          Aucun produit n'a encore été enregistré.
        </p>

        <p v-else-if="filteredProducts.length === 0" class="text-sm text-base-content/70">
          Aucun produit ne correspond à votre recherche.
        </p>

        <div v-else class="overflow-x-auto">
          <table class="table table-sm md:table-md">
            <thead>
              <tr>
                <th class="w-16">Aperçu</th>
                <th>Nom</th>
                <th>Référence</th>
                <th>Type de produit</th>
                <th>Fournisseurs</th>
                <th class="text-right">Prix indicatif</th>
                <th class="w-32 text-right">Actions</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="row in productRows" :key="row.product.id">
                <td class="align-middle">
                  <DocumentThumbnail
                    :document="resolvePrimaryDocument(row.product)"
                    :alt="resolvePreviewAlt(row.product)"
                  />
                </td>
                <td class="font-medium">{{ row.product.name }}</td>
                <td>{{ row.product.reference || '—' }}</td>
                <td>
                  <NuxtLink
                    v-if="row.product.typeProduct?.id"
                    :to="`/product-category/${row.product.typeProduct.id}/edit`"
                    class="link link-hover link-primary"
                  >
                    {{ row.product.typeProduct.name }}
                  </NuxtLink>
                  <span v-else>{{ row.product.typeProduct?.name || '—' }}</span>
                </td>
                <td>
                  <div
                    v-if="row.suppliers.visible.length"
                    class="flex max-w-[14rem] flex-wrap items-center gap-1 text-sm"
                    :title="row.suppliers.tooltip"
                  >
                    <span
                      v-for="supplier in row.suppliers.visible"
                      :key="supplier"
                      class="badge badge-ghost badge-sm whitespace-nowrap"
                    >
                      {{ supplier }}
                    </span>
                    <span
                      v-if="row.suppliers.overflow"
                      class="badge badge-outline badge-sm"
                    >
                      +{{ row.suppliers.overflow }}
                    </span>
                  </div>
                  <span v-else class="text-sm text-base-content/50">—</span>
                </td>
                <td class="text-right">
                  {{ formatPrice(row.product.supplierPrice) }}
                </td>
                <td class="text-right space-x-2">
                  <NuxtLink
                    :to="`/product/${row.product.id}/edit`"
                    class="btn btn-ghost btn-xs"
                  >
                    Modifier
                  </NuxtLink>
                  <button
                    type="button"
                    class="btn btn-ghost btn-xs text-error"
                    @click="confirmDelete(row.product)"
                  >
                    Supprimer
                  </button>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </section>
  </main>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useHead } from '#imports'
import { useProducts } from '~/composables/useProducts'
import { useProductTypes } from '~/composables/useProductTypes'
import { useToast } from '~/composables/useToast'
import { usePersistedSort } from '~/composables/usePersistedSort'
import DocumentThumbnail from '~/components/DocumentThumbnail.vue'
import { isImageDocument, isPdfDocument } from '~/utils/documentPreview'

useHead(() => ({
  title: 'Catalogue des produits',
}))

const {
  products,
  total,
  loading,
  loaded,
  error,
  loadProducts,
  deleteProduct,
} = useProducts()
const { productTypes, loadProductTypes } = useProductTypes()
const toast = useToast()

const searchTerm = ref('')
const { sortField, sortDirection } = usePersistedSort<'name' | 'createdAt', 'asc' | 'desc'>(
  'product-catalog',
  { field: 'name', direction: 'asc' },
)

// Enrichir les produits avec les types de produits complets
const normalizedProducts = computed(() => {
  return (Array.isArray(products.value) ? products.value : []).map((product) => {
    const typeProduct = productTypes.value.find(t => t.id === product.typeProductId)
    return {
      ...product,
      typeProduct: typeProduct || product.typeProduct || null
    }
  })
})
const hasLoaded = computed(() => loaded.value)
const errorMessage = computed(() => (typeof error.value === 'string' && error.value.length ? error.value : null))

const filteredProducts = computed(() => {
  const term = searchTerm.value.trim().toLowerCase()
  const items = normalizedProducts.value.slice()

  const filtered = term
    ? items.filter((product) => {
        const name = (product?.name || '').toLowerCase()
        const reference = (product?.reference || '').toLowerCase()
        const typeName = (product?.typeProduct?.name || '').toLowerCase()
        return (
          name.includes(term) ||
          reference.includes(term) ||
          typeName.includes(term)
        )
      })
    : items

  const direction = sortDirection.value === 'asc' ? 1 : -1

  return filtered.sort((a, b) => {
    if (sortField.value === 'name') {
      return (
        (a?.name || '').localeCompare(b?.name || '', 'fr', { sensitivity: 'base' })
      ) * direction
    }

    const dateA = a?.createdAt ? new Date(a.createdAt).getTime() : 0
    const dateB = b?.createdAt ? new Date(b.createdAt).getTime() : 0
    return (dateA - dateB) * direction
  })
})

const filteredCount = computed(() => filteredProducts.value.length)
const totalCount = computed(() => {
  const reported = Number(total.value)
  if (!Number.isFinite(reported) || reported < 0) {
    return normalizedProducts.value.length
  }
  return reported
})

const priceFormatter = new Intl.NumberFormat('fr-FR', {
  style: 'currency',
  currency: 'EUR',
  currencyDisplay: 'narrowSymbol',
})

const formatPrice = (value: any) => {
  if (value === null || value === undefined || value === '') {
    return '—'
  }
  const number = Number(value)
  if (Number.isNaN(number)) {
    return '—'
  }
  return priceFormatter.format(number)
}

const MAX_VISIBLE_SUPPLIERS = 3

const resolveProductSuppliers = (product: Record<string, any>) => {
  const names: string[] = []
  const seen = new Set<string>()

  const pushName = (maybeName: unknown) => {
    if (typeof maybeName !== 'string') {
      return
    }
    const normalized = maybeName.trim().replace(/\s+/g, ' ')
    if (!normalized.length) {
      return
    }
    const key = normalized.toLowerCase()
    if (seen.has(key)) {
      return
    }
    seen.add(key)
    names.push(normalized)
  }

  const collectConstructeurs = (value: unknown): void => {
    if (!value) {
      return
    }
    if (Array.isArray(value)) {
      value.forEach(collectConstructeurs)
      return
    }
    if (typeof value === 'string') {
      pushName(value)
      return
    }
    if (typeof value === 'object') {
      const record = value as Record<string, any>
      pushName(record?.name ?? record?.label ?? record?.companyName ?? record?.company ?? null)
      if (record?.constructeur) {
        collectConstructeurs(record.constructeur)
      }
      if (Array.isArray(record?.constructeurs)) {
        collectConstructeurs(record.constructeurs)
      }
    }
  }

  const collectFromLabel = (value: unknown): void => {
    if (typeof value !== 'string') {
      return
    }
    value
      .split(/[,;\\/•·|]+/)
      .map((part) => part.trim())
      .filter(Boolean)
      .forEach(pushName)
  }

  collectConstructeurs(product?.constructeurs)
  collectConstructeurs(product?.constructeur)

  collectFromLabel(product?.constructeursLabel)
  collectFromLabel(product?.supplierLabel)
  collectFromLabel(product?.suppliers)

  return names
}

const buildSuppliersDisplay = (product: Record<string, any>) => {
  const suppliers = resolveProductSuppliers(product)
  const visible = suppliers.slice(0, MAX_VISIBLE_SUPPLIERS)
  const overflow = Math.max(suppliers.length - visible.length, 0)
  return {
    suppliers,
    visible,
    overflow,
    tooltip: suppliers.length ? suppliers.join(', ') : '',
  }
}

const productRows = computed(() =>
  filteredProducts.value.map((product) => ({
    product,
    suppliers: buildSuppliersDisplay(product),
  })),
)

const resolvePrimaryDocument = (product: Record<string, any>) => {
  const documents = Array.isArray(product?.documents) ? product.documents : []
  if (!documents.length) {
    return null
  }
  const normalized = documents.filter((doc) => doc && typeof doc === 'object')
  const withPath = normalized.filter((doc) => doc?.path)
  if (!withPath.length) {
    return normalized[0] ?? null
  }
  const images = withPath.filter((doc) => isImageDocument(doc))
  if (images.length) {
    return images[0]
  }
  const pdf = withPath.find((doc) => isPdfDocument(doc))
  if (pdf) {
    return pdf
  }
  return withPath[0]
}

const resolvePreviewAlt = (product: Record<string, any>) => {
  const parts = [product?.name, product?.reference].filter(Boolean)
  if (parts.length) {
    return `Aperçu du document de ${parts.join(' – ')}`
  }
  return 'Aperçu du document'
}

const reload = async () => {
  await loadProducts({ force: true })
}

const { confirm } = useConfirm()

const confirmDelete = async (product: Record<string, any>) => {
  const confirmed = await confirm({
    message: `Voulez-vous vraiment supprimer le produit "${product.name}" ?\n\nCette action est irréversible.`,
  })
  if (!confirmed) {
    return
  }

  const result = await deleteProduct(product.id)
  if (result.success) {
    toast.showSuccess(`Produit "${product.name}" supprimé`)
  }
}

onMounted(async () => {
  await Promise.all([
    loadProducts(),
    loadProductTypes()
  ])
})
</script>
