<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
          v-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>

        <DataTable
          v-else
          :columns="columns"
          :rows="productRows"
          :loading="loadingProducts"
          :sort="table.sort.value"
          :pagination="paginationState"
          :column-filters="table.columnFilters.value"
          :show-per-page="true"
          empty-message="Aucun produit n'a encore été enregistré."
          no-results-message="Aucun produit ne correspond à votre recherche."
          @sort="table.handleSort"
          @update:current-page="table.handlePageChange"
          @update:per-page="table.handlePerPageChange"
          @update:column-filters="table.handleColumnFiltersChange"
        >
          <template #toolbar>
            <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="table.searchTerm.value"
                type="text"
                class="input input-bordered input-sm w-full mt-1"
                placeholder="Nom ou référence…"
                @input="table.debouncedSearch"
              />
            </label>
          </template>

          <template #cell-preview="{ row }">
            <DocumentThumbnail
              :document="resolvePrimaryDocument(row.product)"
              :alt="resolvePreviewAlt(row.product)"
            />
          </template>

          <template #cell-name="{ row }">
            <span class="font-medium">{{ row.product.name }}</span>
          </template>

          <template #cell-reference="{ row }">
            {{ row.product.reference || '—' }}
          </template>

          <template #cell-typeProduct="{ row }">
            <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>
          </template>

          <template #cell-suppliers="{ row }">
            <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>
          </template>

          <template #cell-price="{ row }">
            {{ formatPrice(row.product.supplierPrice) }}
          </template>

          <template #cell-actions="{ row }">
            <div class="flex justify-end gap-2">
              <NuxtLink
                :to="`/product/${row.product.id}/edit`"
                class="btn btn-ghost btn-xs"
              >
                Modifier
              </NuxtLink>
              <button
                v-if="canEdit"
                type="button"
                class="btn btn-ghost btn-xs text-error"
                @click="confirmDelete(row.product)"
              >
                Supprimer
              </button>
            </div>
          </template>
        </DataTable>
      </div>
    </section>
  </main>
</template>

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

const { canEdit } = usePermissions()

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

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

const table = useDataTable(
  { fetchData: fetchProducts },
  { defaultSort: 'name', defaultDirection: 'asc', defaultPerPage: 20, persistToUrl: true },
)

const loadingProducts = computed(() => loading.value)
const errorMessage = computed(() => (typeof error.value === 'string' && error.value.length ? error.value : null))

const columns = [
  { key: 'preview', label: 'Aperçu', width: 'w-16' },
  { key: 'name', label: 'Nom', sortable: true },
  { key: 'reference', label: 'Référence' },
  { key: 'typeProduct', label: 'Type de produit', filterable: true, filterPlaceholder: 'Filtrer…' },
  { key: 'suppliers', label: 'Fournisseurs' },
  { key: 'price', label: 'Prix indicatif', sortable: true, sortKey: 'supplierPrice', align: 'right' as const },
  { key: 'actions', label: 'Actions', align: 'right' as const, width: 'w-32' },
]

const productsOnPage = computed(() => productRows.value.length)
const paginationState = table.pagination(total, productsOnPage)

// Enrich products with full type data
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 productRows = computed(() =>
  normalizedProducts.value.map(product => ({
    id: product.id,
    product,
    suppliers: buildSuppliersDisplay(product),
  })),
)

async function fetchProducts() {
  await loadProducts({
    search: table.searchTerm.value,
    page: table.currentPage.value,
    itemsPerPage: table.itemsPerPage.value,
    orderBy: table.sortField.value,
    orderDir: table.sortDirection.value as 'asc' | 'desc',
    typeName: table.columnFilters.value.typeProduct || undefined,
    force: true,
  })
}

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)
  return Number.isNaN(number) ? '—' : 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 resolvePrimaryDocument = (product: Record<string, any>) => {
  const documents = Array.isArray(product?.documents) ? product.documents : []
  if (!documents.length) return null
  const normalized = documents.filter((doc: any) => doc && typeof doc === 'object')
  const withPath = normalized.filter((doc: any) => doc?.fileUrl || doc?.path)
  if (!withPath.length) return normalized[0] ?? null
  const images = withPath.filter((doc: any) => isImageDocument(doc))
  if (images.length) return images[0]
  const pdf = withPath.find((doc: any) => isPdfDocument(doc))
  if (pdf) return pdf
  return withPath[0]
}

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

const reload = () => fetchProducts()

const { confirm } = useConfirm()

const resolveDeleteImpact = (product: Record<string, any>) => {
  const impacts: string[] = []
  const machineLinks = Array.isArray(product?.machineLinks) ? product.machineLinks.length : product?.machineLinksCount ?? 0
  const documents = Array.isArray(product?.documents) ? product.documents.length : product?.documentsCount ?? 0
  const customFields = Array.isArray(product?.customFieldValues) ? product.customFieldValues.length : product?.customFieldValuesCount ?? 0
  if (machineLinks > 0) impacts.push(`${machineLinks} liaison${machineLinks > 1 ? 's' : ''} machine`)
  if (documents > 0) impacts.push(`${documents} document${documents > 1 ? 's' : ''}`)
  if (customFields > 0) impacts.push(`${customFields} valeur${customFields > 1 ? 's' : ''} de champs personnalisés`)
  return impacts
}

const confirmDelete = async (product: Record<string, any>) => {
  const productName = product?.name || 'ce produit'
  const impacts = resolveDeleteImpact(product)
  const lines = [`Voulez-vous vraiment supprimer « ${productName} » ?`]
  if (impacts.length) {
    lines.push(`Cela supprimera également :\n• ${impacts.join('\n• ')}`)
  }
  lines.push('Cette action est irréversible.')
  const confirmed = await confirm({ title: 'Supprimer le produit', message: lines.join('\n\n'), dangerous: true })
  if (!confirmed) return
  const result = await deleteProduct(product.id)
  if (result.success) {
    toast.showSuccess(`Produit "${productName}" supprimé`)
  }
}

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