<template>
  <main class="container mx-auto px-6 py-8">
    <!-- Loading State -->
    <div v-if="loading" class="flex justify-center items-center py-12">
      <span class="loading loading-spinner loading-lg"></span>
    </div>

    <!-- Machine Details -->
    <div v-else-if="machine" ref="printAreaRef" class="space-y-8">
      <DocumentPreviewModal
        :document="previewDocument"
        :visible="previewVisible"
        @close="closePreview"
      />

      <!-- Header with actions -->
      <div class="flex flex-col gap-4 md:flex-row md:items-start md:justify-between">
        <div class="flex flex-col gap-2">
          <h1 class="text-3xl font-bold">
            {{ machineViewTitle }}
          </h1>
          <div class="btn-group w-full max-w-xs print:hidden" data-print-hide>
            <button
              type="button"
              class="btn btn-sm"
              :class="isDetailsView ? 'btn-primary' : 'btn-outline'"
              @click="changeMachineView('details')"
            >
              Vue machine
            </button>
            <button
              type="button"
              class="btn btn-sm"
              :class="isSkeletonView ? 'btn-primary' : 'btn-outline'"
              :disabled="!machineHasSkeletonRequirements"
              @click="changeMachineView('skeleton')"
            >
              Squelette
            </button>
          </div>
        </div>
        <div class="flex items-center gap-2 print:hidden" data-print-hide>
          <button
            @click="toggleEditMode"
            class="btn btn-primary"
            :class="{ 'btn-outline': isEditMode }"
          >
            <IconLucideSquarePen
              v-if="!isEditMode"
              class="w-5 h-5 mr-2"
              aria-hidden="true"
            />
            <IconLucideEye
              v-else
              class="w-5 h-5 mr-2"
              aria-hidden="true"
            />
            {{ isEditMode ? 'Voir détails' : 'Modifier' }}
          </button>
          <button
            v-if="isDetailsView && !isEditMode"
            @click="openPrintModal"
            type="button"
            class="btn btn-outline btn-secondary"
          >
            <IconLucidePrinter class="w-5 h-5 mr-2" aria-hidden="true" />
            Imprimer
          </button>
        </div>
      </div>

      <template v-if="isDetailsView">
      <!-- Debug info -->
      <div v-if="debug" class="bg-yellow-100 p-4 rounded-lg">
        <p>Debug: Machine trouvée - {{ machine.name }}</p>
        <p>Components count: {{ components.length }}</p>
        <p>Pieces count: {{ pieces.length }}</p>
      </div>
      
      <!-- Hero -->
      <PageHero
        :title="machine.name"
        :subtitle="machine.description || machine.typeMachine?.description"
        min-height="min-h-[20vh]"
        max-width="max-w-md"
        rounded
      >
        <div class="flex justify-center gap-4">
          <div v-if="machine.typeMachine?.category" class="badge badge-outline">
            {{ machine.typeMachine?.category }}
          </div>
          <div v-if="machine.site?.name" class="badge badge-outline">
            {{ machine.site?.name }}
          </div>
          <div v-if="machine.reference" class="badge badge-outline">
            {{ machine.reference }}
          </div>
        </div>
      </PageHero>

      <!-- Machine Info Card -->
      <div class="card bg-base-100 shadow-lg">
        <div class="card-body">
          <h2 class="card-title">Informations de la machine</h2>
          <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div class="form-control">
              <label class="label">
                <span class="label-text">Nom</span>
              </label>
              <input 
                v-if="isEditMode"
                :id="getMachineFieldId('name')"
                v-model="machineName" 
                type="text" 
                class="input input-bordered"
                @blur="updateMachineInfo"
              />
              <div v-else class="input input-bordered bg-base-200">
                {{ machineName }}
              </div>
            </div>
            <div v-if="isEditMode || machineReference" class="form-control">
              <label class="label">
                <span class="label-text">Référence</span>
              </label>
              <input 
                v-if="isEditMode"
                :id="getMachineFieldId('reference')"
                v-model="machineReference" 
                type="text" 
                class="input input-bordered"
                @blur="updateMachineInfo"
              />
              <div v-else class="input input-bordered bg-base-200">
                {{ machineReference }}
              </div>
            </div>
            <div v-if="isEditMode || hasMachineConstructeur" class="form-control">
              <label class="label">
                <span class="label-text">Fournisseur</span>
              </label>
              <ConstructeurSelect
                v-if="isEditMode"
                class="w-full"
                :key="machine.value?.id"
                :model-value="machineConstructeurIds"
                :initial-options="machineConstructeursDisplay"
                placeholder="Rechercher un ou plusieurs fournisseurs..."
                @update:modelValue="handleMachineConstructeurChange"
              />
              <div v-else class="input input-bordered bg-base-200">
                <div v-if="machineConstructeursDisplay.length" class="space-y-1">
                  <div
                    v-for="constructeur in machineConstructeursDisplay"
                    :key="constructeur.id"
                    class="flex flex-col"
                  >
                    <span class="font-medium">{{ constructeur.name }}</span>
                    <span
                      v-if="formatConstructeurContactSummary(constructeur)"
                      class="text-xs text-gray-500"
                    >
                      {{ formatConstructeurContactSummary(constructeur) }}
                    </span>
                  </div>
                </div>
                <span v-else class="font-medium">Non défini</span>
              </div>
            </div>
          </div>

          <!-- Champs personnalisés -->
          <div v-if="visibleMachineCustomFields.length" class="mt-6 pt-4 border-t border-gray-200">
            <h4 class="font-semibold text-gray-700 mb-3">Champs personnalisés de la machine</h4>
            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
              <div
                v-for="field in visibleMachineCustomFields"
                :key="field.customFieldValueId || field.id || field.name"
                class="form-control"
              >
                <label class="label">
                  <span class="label-text text-sm">{{ field.name }}</span>
                  <span v-if="field.required" class="label-text-alt text-error">*</span>
                </label>

                <template v-if="isEditMode">
                  <input
                    v-if="field.type === 'text'"
                    :value="field.value ?? ''"
                    type="text"
                    class="input input-bordered input-sm"
                    :required="field.required"
                    @input="setMachineCustomFieldValue(field, $event.target.value)"
                    @blur="updateMachineCustomField(field)"
                  />
                  <input
                    v-else-if="field.type === 'number'"
                    :value="field.value ?? ''"
                    type="number"
                    class="input input-bordered input-sm"
                    :required="field.required"
                    @input="setMachineCustomFieldValue(field, $event.target.value)"
                    @blur="updateMachineCustomField(field)"
                  />
                  <select
                    v-else-if="field.type === 'select'"
                    :value="field.value ?? ''"
                    class="select select-bordered select-sm"
                    :required="field.required"
                    @change="setMachineCustomFieldValue(field, $event.target.value)"
                    @blur="updateMachineCustomField(field)"
                  >
                    <option value="">Sélectionner...</option>
                    <option
                      v-for="option in field.options"
                      :key="option"
                      :value="option"
                    >
                      {{ option }}
                    </option>
                  </select>
                  <div v-else-if="field.type === 'boolean'" class="flex items-center gap-2">
                    <input
                      :value="field.value ?? ''"
                      type="checkbox"
                      class="checkbox checkbox-sm"
                      :checked="String(field.value).toLowerCase() === 'true'"
                      @change="setMachineCustomFieldValue(field, $event.target.checked ? 'true' : 'false')"
                      @blur="updateMachineCustomField(field)"
                    />
                    <span class="text-sm">{{ String(field.value).toLowerCase() === 'true' ? 'Oui' : 'Non' }}</span>
                  </div>
                  <input
                    v-else-if="field.type === 'date'"
                    :value="field.value ?? ''"
                    type="date"
                    class="input input-bordered input-sm"
                    :required="field.required"
                    @input="setMachineCustomFieldValue(field, $event.target.value)"
                    @blur="updateMachineCustomField(field)"
                  />
                  <div v-else class="text-xs text-error">
                    Type de champ non pris en charge
                  </div>
                </template>
                <template v-else>
                  <div class="input input-bordered input-sm bg-base-200">
                    {{ formatCustomFieldValue(field) }}
                  </div>
                </template>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- Documents -->
      <div class="card bg-base-100 shadow-lg mt-6">
        <div class="card-body space-y-4">
          <div class="flex items-center justify-between">
            <div>
              <h2 class="card-title">Documents de la machine</h2>
              <p class="text-xs text-gray-500">Ajoutez ou consultez les documents liés à cette machine.</p>
            </div>
            <span v-if="isEditMode && machineDocumentFiles.length" class="badge badge-outline">
              {{ machineDocumentFiles.length }} fichier{{ machineDocumentFiles.length > 1 ? 's' : '' }} sélectionné{{ machineDocumentFiles.length > 1 ? 's' : '' }}
            </span>
          </div>

          <DocumentUpload
            v-if="isEditMode"
            v-model="machineDocumentFiles"
            title="Déposer des fichiers pour la machine"
            subtitle="Formats acceptés : PDF, images, documents..."
            @files-added="handleMachineFilesAdded"
          />

          <div v-if="machineDocumentsList.length" class="space-y-2">
            <div
              v-for="document in machineDocumentsList"
              :key="document.id"
              class="flex items-center justify-between rounded border border-base-200 bg-base-100 px-3 py-2"
            >
              <div class="flex items-center gap-3 text-sm">
                <div
                  class="flex-shrink-0 overflow-hidden rounded-md border border-base-200 bg-base-200/70 flex items-center justify-center"
                  :class="documentThumbnailClass(document)"
                >
                  <img
                    v-if="isImageDocument(document) && document.path"
                    :src="document.path"
                    class="h-full w-full object-cover"
                    :alt="`Aperçu de ${document.name}`"
                  >
                  <iframe
                    v-else-if="shouldInlinePdf(document)"
                    :src="documentPreviewSrc(document)"
                    class="h-full w-full border-0 bg-white"
                    title="Aperçu PDF"
                  />
                  <component
                    v-else
                    :is="documentIcon(document).component"
                    class="h-6 w-6"
                    :class="documentIcon(document).colorClass"
                    aria-hidden="true"
                  />
                </div>
                <div>
                  <div class="font-medium">{{ document.name }}</div>
                  <div class="text-xs text-gray-500">
                    {{ document.mimeType || 'Inconnu' }} • {{ formatSize(document.size) }}
                  </div>
                </div>
              </div>
              <div class="flex items-center gap-2">
                <button
                  type="button"
                  class="btn btn-ghost btn-xs"
                  :disabled="!canPreviewDocument(document)"
                  :title="canPreviewDocument(document) ? 'Consulter le document' : 'Aucun aperçu disponible pour ce type'"
                  @click="openPreview(document)"
                >
                  Consulter
                </button>
                <button type="button" class="btn btn-ghost btn-xs" @click="downloadDocument(document)">
                  Télécharger
                </button>
                <button
                  v-if="isEditMode"
                  type="button"
                  class="btn btn-error btn-xs"
                  :disabled="machineDocumentsUploading"
                  @click="removeMachineDocument(document.id)"
                >
                  Supprimer
                </button>
              </div>
            </div>
          </div>
          <p v-else class="text-xs text-gray-500">Aucun document lié à cette machine.</p>
        </div>
      </div>

      <!-- Produits associés -->
      <div class="card bg-base-100 shadow-lg">
        <div class="card-body space-y-4">
          <div class="flex items-center justify-between">
            <div>
              <h2 class="card-title">Produits associés</h2>
              <p class="text-xs text-gray-500">
                Produits sélectionnés directement pour cette machine selon le squelette.
              </p>
            </div>
            <span class="badge badge-outline" v-if="machineDirectProducts.length">
              {{ machineDirectProducts.length }} produit{{ machineDirectProducts.length > 1 ? 's' : '' }}
            </span>
          </div>

          <div v-if="machineDirectProducts.length" class="space-y-3">
            <div
              v-for="product in machineDirectProducts"
              :key="product.id || product.name"
              class="rounded border border-base-200 bg-base-200/60 p-3 text-sm space-y-1"
            >
              <div class="flex items-center justify-between flex-wrap gap-2">
                <p class="font-semibold text-base-content">
                  {{ product.name }}
                </p>
                <span class="badge badge-ghost badge-sm">
                  {{ product.groupLabel }}
                </span>
              </div>
              <p v-if="product.reference" class="text-xs text-base-content/70">
                <span class="font-medium">Référence :</span>
                <span class="ml-1">{{ product.reference }}</span>
              </p>
              <p v-if="product.supplierLabel" class="text-xs text-base-content/70">
                <span class="font-medium">Fournisseurs :</span>
                <span class="ml-1">{{ product.supplierLabel }}</span>
              </p>
              <p v-if="product.priceLabel" class="text-xs text-base-content/70">
                <span class="font-medium">Prix indicatif :</span>
                <span class="ml-1">{{ product.priceLabel }}</span>
              </p>
            </div>
          </div>
          <p v-else class="text-xs text-gray-500">
            Aucun produit n'a été associé directement à cette machine.
          </p>
        </div>
      </div>

      <!-- Components Section -->
      <div class="card bg-base-100 shadow-lg">
        <div class="card-body">
          <div class="flex justify-between items-center mb-4">
            <h2 class="card-title">Composants</h2>
            <button 
              type="button"
              class="btn btn-ghost btn-sm gap-2"
              @click="toggleAllComponents"
              :title="componentsCollapsed ? 'Déplier tous les composants' : 'Replier tous les composants'"
            >
              <IconLucideChevronRight
                class="w-5 h-5 transition-transform"
                :class="componentsCollapsed ? 'rotate-0' : 'rotate-90'"
                aria-hidden="true"
              />
              <span class="text-sm">
                {{ componentsCollapsed ? 'Tout déplier' : 'Tout replier' }}
              </span>
            </button>
          </div>

          <ComponentHierarchy
            :components="components"
            :is-edit-mode="isEditMode"
            :collapse-all="componentsCollapsed"
            :toggle-token="collapseToggleToken"
            @update="updateComponent"
            @edit-piece="updatePieceFromComponent"
            @custom-field-update="updatePieceCustomField"
          />
        </div>
      </div>

      <!-- Machine Pieces Section -->
      <div class="card bg-base-100 shadow-lg">
        <div class="card-body">
          <div class="flex justify-between items-center mb-4">
            <h2 class="card-title">Pièces de la machine</h2>
          </div>

          <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
            <PieceItem
              v-for="piece in machinePieces"
              :key="piece.id"
              :piece="piece"
              :is-edit-mode="isEditMode"
              @update="updatePieceInfo"
              @edit="editPiece"
              @custom-field-update="updatePieceCustomField"
            />
          </div>
        </div>
      </div>
    </template>

    <template v-else>
      <div
        v-if="componentRequirementGroups.length || pieceRequirementGroups.length || productRequirementGroups.length"
        class="card bg-base-100 shadow-lg"
      >
        <div class="card-body space-y-6">
          <div>
            <h2 class="card-title">Structure sélectionnée</h2>
            <p class="text-sm text-gray-500">
              Synthèse des familles définies dans le type et des modèles utilisés pour cette machine.
            </p>
          </div>

          <div v-if="componentRequirementGroups.length" class="space-y-4">
            <h3 class="text-sm font-semibold text-gray-700">Composants</h3>
            <div
              v-for="group in componentRequirementGroups"
              :key="group.requirement.id"
              class="rounded-lg border border-base-200 p-4"
            >
              <div class="flex flex-wrap items-center justify-between gap-2 mb-3">
                <div>
                  <h4 class="font-medium text-sm">
                    {{ group.requirement.label || group.requirement.typeComposant?.name || 'Famille de composants' }}
                  </h4>
                  <p class="text-xs text-gray-500">
                    Type : {{ group.requirement.typeComposant?.name || 'Non défini' }} · Min {{ group.requirement.minCount ?? (group.requirement.required ? 1 : 0) }} · Max {{ group.requirement.maxCount ?? '∞' }}
                  </p>
                </div>
                <span class="badge badge-outline badge-sm">{{ group.components.length }} composant(s)</span>
              </div>

              <div v-if="group.components.length" class="space-y-2">
                <div
                  v-for="component in group.components"
                  :key="component.id"
                  class="flex flex-wrap items-center gap-2 text-sm"
                >
                  <span class="font-medium">{{ component.name }}</span>
                  <span v-if="component.parentComposantId" class="text-xs text-gray-500">
                    (Sous-composant)
                  </span>
                  <div
                    v-if="summarizeCustomFields(component.customFields || []).length"
                    class="w-full flex flex-wrap gap-2 text-xs text-gray-600"
                  >
                    <span
                      v-for="field in summarizeCustomFields(component.customFields || [])"
                      :key="field.key"
                      class="badge badge-ghost badge-sm whitespace-pre-wrap"
                    >
                      <span class="font-medium">{{ field.label }} :</span>
                      <span class="ml-1">{{ field.value }}</span>
                    </span>
                  </div>
                  <div
                    v-if="component.__productDisplay"
                    class="w-full text-xs text-gray-600 space-y-1"
                  >
                    <div>
                      <span class="font-medium">Produit :</span>
                      <span>{{ component.__productDisplay.name }}</span>
                    </div>
                    <div v-if="component.__productDisplay.category">
                      <span class="font-medium">Catégorie :</span>
                      <span>{{ component.__productDisplay.category }}</span>
                    </div>
                    <div v-if="component.__productDisplay.reference">
                      <span class="font-medium">Référence :</span>
                      <span>{{ component.__productDisplay.reference }}</span>
                    </div>
                    <div v-if="component.__productDisplay.suppliers">
                      <span class="font-medium">Fournisseurs :</span>
                      <span>{{ component.__productDisplay.suppliers }}</span>
                    </div>
                    <div v-if="component.__productDisplay.price">
                      <span class="font-medium">Prix indicatif :</span>
                      <span>{{ component.__productDisplay.price }}</span>
                    </div>
                  </div>
                </div>
              </div>
              <p v-else class="text-xs text-gray-500">Aucun composant rattaché à ce groupe.</p>
            </div>
          </div>

          <div v-if="pieceRequirementGroups.length" class="space-y-4">
            <h3 class="text-sm font-semibold text-gray-700">Pièces principales</h3>
            <div
              v-for="group in pieceRequirementGroups"
              :key="group.requirement.id"
              class="rounded-lg border border-base-200 p-4"
            >
              <div class="flex flex-wrap items-center justify-between gap-2 mb-3">
                <div>
                  <h4 class="font-medium text-sm">
                    {{ group.requirement.label || group.requirement.typePiece?.name || 'Groupe de pièces' }}
                  </h4>
                  <p class="text-xs text-gray-500">
                    Type : {{ group.requirement.typePiece?.name || 'Non défini' }} · Min {{ group.requirement.minCount ?? (group.requirement.required ? 1 : 0) }} · Max {{ group.requirement.maxCount ?? '∞' }}
                  </p>
                </div>
                <span class="badge badge-outline badge-sm">{{ group.pieces.length }} pièce(s)</span>
              </div>

              <div v-if="group.pieces.length" class="space-y-2">
                <div
                  v-for="piece in group.pieces"
                  :key="piece.id"
                  class="flex flex-wrap items-center gap-2 text-sm"
                >
                  <span class="font-medium">{{ piece.name }}</span>
                  <span v-if="piece.parentComponentName" class="text-xs text-gray-500">
                    (Rattachée à {{ piece.parentComponentName }})
                  </span>
                  <div
                    v-if="summarizeCustomFields(piece.customFields || []).length"
                    class="w-full flex flex-wrap gap-2 text-xs text-gray-600"
                  >
                    <span
                      v-for="field in summarizeCustomFields(piece.customFields || [])"
                      :key="field.key"
                      class="badge badge-ghost badge-sm whitespace-pre-wrap"
                    >
                      <span class="font-medium">{{ field.label }} :</span>
                      <span class="ml-1">{{ field.value }}</span>
                    </span>
                  </div>
                  <div
                    v-if="piece.__productDisplay"
                    class="w-full text-xs text-gray-600 space-y-1"
                  >
                    <div>
                      <span class="font-medium">Produit :</span>
                      <span>{{ piece.__productDisplay.name }}</span>
                    </div>
                    <div v-if="piece.__productDisplay.category">
                      <span class="font-medium">Catégorie :</span>
                      <span>{{ piece.__productDisplay.category }}</span>
                    </div>
                    <div v-if="piece.__productDisplay.reference">
                      <span class="font-medium">Référence :</span>
                      <span>{{ piece.__productDisplay.reference }}</span>
                    </div>
                    <div v-if="piece.__productDisplay.suppliers">
                      <span class="font-medium">Fournisseurs :</span>
                      <span>{{ piece.__productDisplay.suppliers }}</span>
                    </div>
                    <div v-if="piece.__productDisplay.price">
                      <span class="font-medium">Prix indicatif :</span>
                      <span>{{ piece.__productDisplay.price }}</span>
                    </div>
                  </div>
                </div>
              </div>
              <p v-else class="text-xs text-gray-500">Aucune pièce rattachée à ce groupe.</p>
            </div>
          </div>

          <div v-if="productRequirementGroups.length" class="space-y-4">
            <h3 class="text-sm font-semibold text-gray-700">Produits requis</h3>
            <div
              v-for="group in productRequirementGroups"
              :key="group.requirement.id"
              class="rounded-lg border border-base-200 p-4"
            >
              <div class="flex flex-wrap items-center justify-between gap-2 mb-3">
                <div>
                  <h4 class="font-medium text-sm">
                    {{ group.requirement.label || group.requirement.typeProduct?.name || 'Groupe de produits' }}
                  </h4>
                  <p class="text-xs text-gray-500">
                    Catégorie : {{ group.requirement.typeProduct?.name || 'Non définie' }} · Min {{ group.requirement.minCount ?? (group.requirement.required ? 1 : 0) }} · Max {{ group.requirement.maxCount ?? '∞' }}
                  </p>
                </div>
                <div class="flex flex-wrap items-center gap-2">
                  <span class="badge badge-outline badge-sm">Total {{ group.totalCount }}</span>
                  <span class="badge badge-ghost badge-sm">Direct {{ group.directProducts.length }}</span>
                </div>
              </div>

              <div class="text-xs text-gray-500 mb-3">
                Via composants : {{ group.componentCount }} • Via pièces : {{ group.pieceCount }}
              </div>

              <div v-if="group.directProducts.length" class="space-y-2">
                <div
                  v-for="product in group.directProducts"
                  :key="product.id || product.name"
                  class="rounded border border-base-200 bg-base-200/60 p-3 text-sm"
                >
                  <div class="font-medium">
                    {{ product.name }}
                  </div>
                  <div v-if="product.reference" class="text-xs text-gray-500">
                    Référence : {{ product.reference }}
                  </div>
                  <div v-if="product.supplierLabel" class="text-xs text-gray-500">
                    Fournisseurs : {{ product.supplierLabel }}
                  </div>
                  <div v-if="product.priceLabel" class="text-xs text-gray-500">
                    Prix indicatif : {{ product.priceLabel }}
                  </div>
                </div>
              </div>
              <p v-else class="text-xs text-gray-500">
                Aucune sélection directe. Couverture assurée via composants ou pièces associés.
              </p>
            </div>
          </div>
        </div>
      </div>
    </template>
  </div>

    <!-- Error State -->
    <div v-else class="text-center py-12">
      <div class="max-w-md mx-auto">
        <IconLucideAlertTriangle class="w-16 h-16 mx-auto text-gray-400 mb-4" aria-hidden="true" />
        <h3 class="text-lg font-medium text-gray-900 mb-2">Machine non trouvée</h3>
        <p class="text-gray-500 mb-4">La machine avec l'ID "{{ machineId }}" n'existe pas ou a été supprimée.</p>
        <NuxtLink to="/machines" class="btn btn-primary">
          Retour aux machines
        </NuxtLink>
      </div>
    </div>
  </main>

  <MachinePrintSelectionModal
    :open="printModalOpen"
    :selection="printSelection"
    :components="components"
    :pieces="machinePieces"
    @close="closePrintModal"
    @confirm="handlePrintConfirm"
    @select-all="setAllPrintSelection(true)"
    @deselect-all="setAllPrintSelection(false)"
  />

</template>

<script setup>
import { ref, reactive, onMounted, computed, watch } from 'vue'
import { useRoute } from 'vue-router'
import { useMachines } from '~/composables/useMachines'
import { useComposants } from '~/composables/useComposants'
import { usePieces } from '~/composables/usePieces'
import { useComponentTypes } from '~/composables/useComponentTypes'
import { usePieceTypes } from '~/composables/usePieceTypes'
import { useCustomFields } from '~/composables/useCustomFields'
import { useApi } from '~/composables/useApi'
import { useToast } from '~/composables/useToast'
import { useDocuments } from '~/composables/useDocuments'
import { getFileIcon } from '~/utils/fileIcons'
import { sanitizeDefinitionOverrides, normalizeStructureForEditor } from '~/shared/modelUtils'
import {
  resolveConstructeurs,
  uniqueConstructeurIds,
  formatConstructeurContact as formatConstructeurContactSummary,
} from '~/shared/constructeurUtils'
import {
  coerceValueForType,
  formatCustomFieldValue,
  shouldDisplayCustomField,
  normalizeCustomFieldDefinitionEntry,
  normalizeExistingCustomFieldDefinitions,
  normalizeCustomFieldValueEntry,
  mergeCustomFieldValuesWithDefinitions,
  dedupeCustomFieldEntries,
  summarizeCustomFields,
} from '~/shared/utils/customFieldUtils'
import {
  resolveIdentifier,
  resolveProductReference as _resolveProductReference,
  getProductDisplay as _getProductDisplay,
  getProductSuppliersLabel,
  getProductPriceLabel,
  extractParentLinkIdentifiers,
} from '~/shared/utils/productDisplayUtils'
import {
  buildMachineHierarchyFromLinks,
  resolveLinkArray,
  mergePieceLists,
  mergeComponentTrees,
} from '~/composables/useMachineHierarchy'
import { useMachinePrint } from '~/composables/useMachinePrint'
import { canPreviewDocument, isImageDocument, isPdfDocument } from '~/utils/documentPreview'
import ComponentHierarchy from '~/components/ComponentHierarchy.vue'
import DocumentUpload from '~/components/DocumentUpload.vue'
import ConstructeurSelect from '~/components/ConstructeurSelect.vue'
import { useConstructeurs } from '~/composables/useConstructeurs'
import { useProducts } from '~/composables/useProducts'
import DocumentPreviewModal from '~/components/DocumentPreviewModal.vue'
import PageHero from '~/components/PageHero.vue'
import MachinePrintSelectionModal from '~/components/MachinePrintSelectionModal.vue'
import IconLucideAlertTriangle from '~icons/lucide/alert-triangle'
import IconLucideSquarePen from '~icons/lucide/square-pen'
import IconLucideEye from '~icons/lucide/eye'
import IconLucideChevronRight from '~icons/lucide/chevron-right'
import IconLucidePrinter from '~icons/lucide/printer'
import IconLucidePlus from '~icons/lucide/plus'
import IconLucideX from '~icons/lucide/x'

const route = useRoute()
const machineId = route.params.id

// Vérifier que l'ID est valide
if (!machineId) {
  console.error('ID de machine manquant')
}

// Composables
const {
  updateMachine: updateMachineApi,
  reconfigureSkeleton: reconfigureMachineSkeleton,
} = useMachines()
const {
  updateComposant: updateComposantApi
} = useComposants()
const {
  updatePiece: updatePieceApi
} = usePieces()
const { componentTypes, loadComponentTypes } = useComponentTypes()
const { pieceTypes, loadPieceTypes } = usePieceTypes()
const { products, loadProducts } = useProducts()

const { upsertCustomFieldValue, updateCustomFieldValue: updateCustomFieldValueApi } = useCustomFields()
const { get } = useApi()
const {
  uploadDocuments,
  deleteDocument,
  loadDocumentsByMachine,
  loadDocumentsByComponent,
  loadDocumentsByPiece
} = useDocuments()
const toast = useToast()

// Data
const loading = ref(true)
const machine = ref(null)
const components = ref([])
const pieces = ref([])
const machineComponentLinks = ref([])
const machinePieceLinks = ref([])
const machineProductLinks = ref([])
const printAreaRef = ref(null)

const { constructeurs, loadConstructeurs } = useConstructeurs()

// Champs de la machine
const machineName = ref('')
const machineReference = ref('')
const machineConstructeurIds = ref([])
const machineConstructeurId = computed({
  get: () => machineConstructeurIds.value[0] || null,
  set: (value) => {
    machineConstructeurIds.value = value ? [value] : []
  },
})
const machineConstructeursDisplay = computed(() => {
  const ids = uniqueConstructeurIds(
    machineConstructeurIds.value,
    machine.value?.constructeurIds,
    machine.value?.constructeurs,
    machine.value?.constructeur,
  )
  return resolveConstructeurs(
    ids,
    Array.isArray(machine.value?.constructeurs) ? machine.value?.constructeurs : [],
    machine.value?.constructeur ? [machine.value.constructeur] : [],
    constructeurs.value,
  )
})
const machineConstructeurContact = computed(() =>
  machineConstructeursDisplay.value
    .map((constructeur) => formatConstructeurContactSummary(constructeur))
    .filter(Boolean)
    .join(' • '),
)
const hasMachineConstructeur = computed(
  () => machineConstructeursDisplay.value.length > 0,
)

const machineDocumentFiles = ref([])
const machineDocumentsUploading = ref(false)
const machineDocumentsLoaded = ref(false)
const machineCustomFields = ref([])
const previewDocument = ref(null)
const previewVisible = ref(false)

const {
  printModalOpen,
  printSelection,
  ensurePrintSelectionEntries: _ensurePrintEntries,
  setAllPrintSelection: _setAllPrint,
  openPrintModal: _openPrintModal,
  closePrintModal,
  handlePrintConfirm: _handlePrintConfirm,
} = useMachinePrint()

const activeMachineView = ref('details')
const isDetailsView = computed(() => activeMachineView.value === 'details')
const isSkeletonView = computed(() => activeMachineView.value === 'skeleton')

const skeletonEditor = reactive({
  open: false,
  loading: false,
  submitting: false,
})

const componentRequirementSelections = reactive({})
const pieceRequirementSelections = reactive({})
const productRequirementSelections = reactive({})

const machineType = computed(() => machine.value?.typeMachine || null)
const componentRequirements = computed(() => machineType.value?.componentRequirements || [])
const pieceRequirements = computed(() => machineType.value?.pieceRequirements || [])
const productRequirements = computed(() => machineType.value?.productRequirements || [])
const machineHasSkeletonRequirements = computed(() =>
  componentRequirements.value.length > 0 ||
  pieceRequirements.value.length > 0 ||
  productRequirements.value.length > 0
)

const componentTypeOptions = computed(() => componentTypes.value || [])
const pieceTypeOptions = computed(() => pieceTypes.value || [])

const componentTypeLabelMap = computed(() => {
  const map = new Map()
  componentTypeOptions.value.forEach((type) => {
    if (type?.id) {
      map.set(type.id, type.name || '')
    }
  })
  componentRequirements.value.forEach((requirement) => {
    const type = requirement.typeComposant
    if (type?.id) {
      map.set(type.id, type.name || '')
    }
  })
  return map
})

const pieceTypeLabelMap = computed(() => {
  const map = new Map()
  pieceTypeOptions.value.forEach((type) => {
    if (type?.id) {
      map.set(type.id, type.name || '')
    }
  })
  pieceRequirements.value.forEach((requirement) => {
    const type = requirement.typePiece
    if (type?.id) {
      map.set(type.id, type.name || '')
    }
  })
  return map
})

const productInventory = computed(() => products.value || [])

const productById = computed(() => {
  const map = new Map()
  productInventory.value.forEach((product) => {
    if (product?.id) {
      map.set(product.id, product)
    }
  })
  return map
})

const findProductById = (productId) => {
  if (!productId) {
    return null
  }
  return productById.value.get(productId) || null
}

// Local wrappers that bind closures for imported functions
const resolveProductReference = (source) => _resolveProductReference(source, findProductById)
const getProductDisplay = (source) => _getProductDisplay(source, findProductById)
// getProductSuppliersLabel → imported from productDisplayUtils
// getProductPriceLabel → imported from productDisplayUtils

const getProductOptionsForRequirement = (requirement) => {
  const requirementTypeId =
    requirement?.typeProductId ||
    requirement?.typeProduct?.id ||
    null

  return productInventory.value.filter((product) => {
    if (!product?.id) {
      return false
    }
    if (!requirementTypeId) {
      return true
    }
    const productTypeId =
      product.typeProductId ||
      product.typeProduct?.id ||
      null
    return productTypeId === requirementTypeId
  })
}

const resolveProductRequirementTypeLabel = (requirement, entry) => {
  const typeId =
    entry?.typeProductId ||
    requirement?.typeProductId ||
    requirement?.typeProduct?.id ||
    null

  if (typeId) {
    const typeMatch = productRequirements.value.find(
      (req) => req.typeProductId === typeId || req.typeProduct?.id === typeId,
    )
    if (typeMatch?.typeProduct?.name) {
      return typeMatch.typeProduct.name
    }
  }
  return requirement?.typeProduct?.name || 'Catégorie non définie'
}

const isPlainObject = (value) => Object.prototype.toString.call(value) === '[object Object]'

// resolveIdentifier → imported from productDisplayUtils

// extractParentLinkIdentifiers → imported from productDisplayUtils

const resolveComponentRequirementTypeLabel = (requirement, entry) => {
  const typeId = entry?.typeComposantId || requirement?.typeComposantId || null
  if (!typeId) {
    return requirement?.typeComposant?.name || 'Type non défini'
  }
  return componentTypeLabelMap.value.get(typeId) || requirement?.typeComposant?.name || 'Type non défini'
}

const resolvePieceRequirementTypeLabel = (requirement, entry) => {
  const typeId = entry?.typePieceId || requirement?.typePieceId || null
  if (!typeId) {
    return requirement?.typePiece?.name || 'Type non défini'
  }
  return pieceTypeLabelMap.value.get(typeId) || requirement?.typePiece?.name || 'Type non défini'
}

const getComponentRequirementEntries = (requirementId) => {
  return componentRequirementSelections[requirementId] || []
}

const getPieceRequirementEntries = (requirementId) => {
  return pieceRequirementSelections[requirementId] || []
}

const getProductRequirementEntries = (requirementId) => {
  return productRequirementSelections[requirementId] || []
}

const createComponentSelectionEntry = (requirement, source = null) => {
  const link = source?.machineComponentLink || null

  const entry = {
    linkId: resolveIdentifier(link?.id, source?.machineComponentLinkId, source?.linkId),
    composantId: resolveIdentifier(source?.composantId, source?.componentId, source?.id),
    parentLinkId: resolveIdentifier(
      link?.parentLinkId,
      link?.parentComponentLinkId,
      source?.parentComponentLinkId,
      source?.parentLinkId,
    ),
    parentRequirementId: resolveIdentifier(
      link?.parentRequirementId,
      source?.parentRequirementId,
      requirement?.parentRequirementId,
    ),
    parentMachineComponentRequirementId: resolveIdentifier(
      link?.parentMachineComponentRequirementId,
      source?.parentMachineComponentRequirementId,
      requirement?.parentMachineComponentRequirementId,
    ),
    parentMachinePieceRequirementId: resolveIdentifier(
      link?.parentMachinePieceRequirementId,
      source?.parentMachinePieceRequirementId,
      requirement?.parentMachinePieceRequirementId,
    ),
    parentComponentId: resolveIdentifier(link?.parentComponentId, source?.parentComponentId),
    parentPieceId: resolveIdentifier(link?.parentPieceId, source?.parentPieceId),
    typeComposantId:
      source?.typeMachineComponentRequirement?.typeComposantId
      || source?.typeComposantId
      || source?.typeComposant?.id
      || requirement?.typeComposantId
      || null,
    definition: {
      name:
        source?.name
        || source?.nom
        || requirement?.typeComposant?.name
        || '',
      reference: source?.reference || '',
      constructeurIds: [],
      constructeurId: null,
      prix:
        source?.prix
        ?? source?.price
        ?? null,
    },
  }

  const definitionConstructeurIds = uniqueConstructeurIds(
    link?.overrides?.constructeurIds,
    link?.overrides?.constructeurId,
    source?.constructeurIds,
    source?.constructeurId,
    source?.constructeur,
  )
  entry.definition.constructeurIds = definitionConstructeurIds
  entry.definition.constructeurId = definitionConstructeurIds[0] || null

  if (link?.overrides && isPlainObject(link.overrides)) {
    entry.definition = {
      ...entry.definition,
      ...link.overrides,
    }
  }

  const finalizedConstructeurIds = uniqueConstructeurIds(
    entry.definition.constructeurIds,
    entry.definition.constructeurId,
    entry.definition.constructeur,
  )
  entry.definition.constructeurIds = finalizedConstructeurIds
  entry.definition.constructeurId = finalizedConstructeurIds[0] || null

  return entry
}

const createPieceSelectionEntry = (requirement, source = null) => {
  const link = source?.machinePieceLink || null

  const entry = {
    linkId: resolveIdentifier(link?.id, source?.machinePieceLinkId, source?.linkId),
    pieceId: resolveIdentifier(source?.pieceId, source?.id),
    parentLinkId: resolveIdentifier(link?.parentLinkId, source?.parentLinkId),
    parentComponentLinkId: resolveIdentifier(
      link?.parentComponentLinkId,
      source?.parentComponentLinkId,
      source?.machineComponentLinkId,
    ),
    parentRequirementId: resolveIdentifier(
      link?.parentRequirementId,
      source?.parentRequirementId,
      requirement?.parentRequirementId,
    ),
    parentMachineComponentRequirementId: resolveIdentifier(
      link?.parentMachineComponentRequirementId,
      source?.parentMachineComponentRequirementId,
      requirement?.parentMachineComponentRequirementId,
    ),
    parentMachinePieceRequirementId: resolveIdentifier(
      link?.parentMachinePieceRequirementId,
      source?.parentMachinePieceRequirementId,
      requirement?.parentMachinePieceRequirementId,
    ),
    parentComponentId: resolveIdentifier(link?.parentComponentId, source?.parentComponentId, source?.composantId),
    parentPieceId: resolveIdentifier(link?.parentPieceId, source?.parentPieceId),
    composantId: resolveIdentifier(source?.composantId, link?.composantId, link?.componentId),
    typePieceId:
      source?.typeMachinePieceRequirement?.typePieceId
      || source?.typePieceId
      || source?.typePiece?.id
      || requirement?.typePieceId
      || null,
    definition: {
      name:
        source?.name
        || source?.nom
        || requirement?.typePiece?.name
        || '',
      reference: source?.reference || '',
      constructeurIds: [],
      constructeurId: null,
      prix:
        source?.prix
        ?? source?.price
        ?? null,
    },
  }

  const definitionConstructeurIds = uniqueConstructeurIds(
    link?.overrides?.constructeurIds,
    link?.overrides?.constructeurId,
    source?.constructeurIds,
    source?.constructeurId,
    source?.constructeur,
  )
  entry.definition.constructeurIds = definitionConstructeurIds
  entry.definition.constructeurId = definitionConstructeurIds[0] || null

  if (link?.overrides && isPlainObject(link.overrides)) {
    entry.definition = {
      ...entry.definition,
      ...link.overrides,
    }
  }

  const finalizedConstructeurIds = uniqueConstructeurIds(
    entry.definition.constructeurIds,
    entry.definition.constructeurId,
    entry.definition.constructeur,
  )
  entry.definition.constructeurIds = finalizedConstructeurIds
  entry.definition.constructeurId = finalizedConstructeurIds[0] || null

  return entry
}

const createProductSelectionEntry = (requirement, source = null) => {
  const link = source?.machineProductLink || source || null

  return {
    linkId: resolveIdentifier(
      link?.id,
      source?.machineProductLinkId,
      source?.linkId,
    ),
    productId: resolveIdentifier(source?.productId, link?.productId),
    parentLinkId: resolveIdentifier(link?.parentLinkId, source?.parentLinkId),
    parentComponentLinkId: resolveIdentifier(
      link?.parentComponentLinkId,
      source?.parentComponentLinkId,
    ),
    parentPieceLinkId: resolveIdentifier(
      link?.parentPieceLinkId,
      source?.parentPieceLinkId,
    ),
    parentRequirementId: resolveIdentifier(
      link?.parentRequirementId,
      source?.parentRequirementId,
      requirement?.parentRequirementId,
    ),
    parentComponentRequirementId: resolveIdentifier(
      link?.parentComponentRequirementId,
      source?.parentComponentRequirementId,
      requirement?.parentComponentRequirementId,
    ),
    parentPieceRequirementId: resolveIdentifier(
      link?.parentPieceRequirementId,
      source?.parentPieceRequirementId,
      requirement?.parentPieceRequirementId,
    ),
    parentMachineComponentRequirementId: resolveIdentifier(
      link?.parentMachineComponentRequirementId,
      source?.parentMachineComponentRequirementId,
      requirement?.parentMachineComponentRequirementId,
    ),
    parentMachinePieceRequirementId: resolveIdentifier(
      link?.parentMachinePieceRequirementId,
      source?.parentMachinePieceRequirementId,
      requirement?.parentMachinePieceRequirementId,
    ),
    typeProductId: resolveIdentifier(
      link?.typeProductId,
      source?.typeProductId,
      requirement?.typeProductId,
      requirement?.typeProduct?.id,
    ),
  }
}

const resetSkeletonRequirementSelections = () => {
  Object.keys(componentRequirementSelections).forEach((key) => {
    delete componentRequirementSelections[key]
  })
  Object.keys(pieceRequirementSelections).forEach((key) => {
    delete pieceRequirementSelections[key]
  })
  Object.keys(productRequirementSelections).forEach((key) => {
    delete productRequirementSelections[key]
  })
}

const addComponentSelectionEntry = (requirement) => {
  const entries = getComponentRequirementEntries(requirement.id)
  const max = requirement.maxCount ?? null
  if (max !== null && entries.length >= max) {
    toast.showError(
      `Vous ne pouvez pas ajouter plus de ${max} composant(s) pour ${requirement.label || requirement.typeComposant?.name || 'ce groupe'}`
    )
    return
  }
  componentRequirementSelections[requirement.id] = [
    ...entries,
    createComponentSelectionEntry(requirement),
  ]
}

const removeComponentSelectionEntry = (requirementId, index) => {
  const entries = getComponentRequirementEntries(requirementId)
  componentRequirementSelections[requirementId] = entries.filter((_, i) => i !== index)
}

const setComponentRequirementType = (requirementId, index, value) => {
  const entries = getComponentRequirementEntries(requirementId)
  const entry = entries[index]
  if (!entry) return
  entry.typeComposantId = value || null
}

const setComponentRequirementConstructeur = (requirementId, index, value) => {
  const entries = getComponentRequirementEntries(requirementId)
  const entry = entries[index]
  if (!entry) return
  const ids = uniqueConstructeurIds(value)
  entry.definition.constructeurIds = ids
  entry.definition.constructeurId = ids[0] || null
}

const addPieceSelectionEntry = (requirement) => {
  const entries = getPieceRequirementEntries(requirement.id)
  const max = requirement.maxCount ?? null
  if (max !== null && entries.length >= max) {
    toast.showError(
      `Vous ne pouvez pas ajouter plus de ${max} pièce(s) pour ${requirement.label || requirement.typePiece?.name || 'ce groupe'}`
    )
    return
  }
  pieceRequirementSelections[requirement.id] = [...entries, createPieceSelectionEntry(requirement)]
}

const removePieceSelectionEntry = (requirementId, index) => {
  const entries = getPieceRequirementEntries(requirementId)
  pieceRequirementSelections[requirementId] = entries.filter((_, i) => i !== index)
}

const setPieceRequirementType = (requirementId, index, value) => {
  const entries = getPieceRequirementEntries(requirementId)
  const entry = entries[index]
  if (!entry) return
  entry.typePieceId = value || null
}

const setPieceRequirementConstructeur = (requirementId, index, value) => {
  const entries = getPieceRequirementEntries(requirementId)
  const entry = entries[index]
  if (!entry) return
  const ids = uniqueConstructeurIds(value)
  entry.definition.constructeurIds = ids
  entry.definition.constructeurId = ids[0] || null
}

const addProductSelectionEntry = (requirement) => {
  const entries = getProductRequirementEntries(requirement.id)
  const max = requirement.maxCount ?? null
  if (max !== null && entries.length >= max) {
    toast.showError(
      `Vous ne pouvez pas ajouter plus de ${max} produit(s) pour ${requirement.label || requirement.typeProduct?.name || 'ce groupe'}`,
    )
    return
  }
  productRequirementSelections[requirement.id] = [
    ...entries,
    createProductSelectionEntry(requirement),
  ]
}

const removeProductSelectionEntry = (requirementId, index) => {
  const entries = getProductRequirementEntries(requirementId)
  productRequirementSelections[requirementId] = entries.filter((_, i) => i !== index)
}

const setProductRequirementProduct = (requirementId, index, productId) => {
  const entries = getProductRequirementEntries(requirementId)
  const entry = entries[index]
  if (!entry) return

  const normalizedProductId = productId || null
  entry.productId = normalizedProductId

  if (normalizedProductId) {
    const product = findProductById(normalizedProductId)
    entry.typeProductId =
      product?.typeProductId ||
      product?.typeProduct?.id ||
      entry.typeProductId ||
      null
  }
}

const setProductRequirementType = (requirementId, index, value) => {
  const entries = getProductRequirementEntries(requirementId)
  const entry = entries[index]
  if (!entry) return
  entry.typeProductId = value || entry.typeProductId || null
}

const collectPiecesForSkeleton = () => {
  const aggregated = []
  machinePieces.value.forEach((piece) => {
    aggregated.push(piece)
  })
  flattenedComponents.value.forEach((component) => {
    ;(component.pieces || []).forEach((piece) => {
      aggregated.push(piece)
    })
  })
  return aggregated
}

const initializeSkeletonRequirementSelections = async () => {
  skeletonEditor.loading = true
  try {
    resetSkeletonRequirementSelections()
    const type = machineType.value
    if (!type) {
      return
    }

    try {
      await loadProducts()
    } catch (error) {
      console.error('Erreur lors du chargement des produits pour le squelette:', error)
    }

    ;(type.componentRequirements || []).forEach((requirement) => {
      const existingComponents = flattenedComponents.value.filter(
        (component) => component.typeMachineComponentRequirementId === requirement.id,
      )
      const entries = existingComponents.map((component) =>
        createComponentSelectionEntry(requirement, component),
      )

      const min = requirement.minCount ?? (requirement.required ? 1 : 0)
      while (entries.length < min) {
        entries.push(createComponentSelectionEntry(requirement))
      }

      if (entries.length) {
        componentRequirementSelections[requirement.id] = entries
      }
    })

    const allPieces = collectPiecesForSkeleton()
    ;(type.pieceRequirements || []).forEach((requirement) => {
      const existingPieces = allPieces.filter(
        (piece) => piece.typeMachinePieceRequirementId === requirement.id,
      )
      const entries = existingPieces.map((piece) =>
        createPieceSelectionEntry(requirement, piece),
      )

      const min = requirement.minCount ?? (requirement.required ? 1 : 0)
      while (entries.length < min) {
        entries.push(createPieceSelectionEntry(requirement))
      }

      if (entries.length) {
        pieceRequirementSelections[requirement.id] = entries
      }
    })

    const existingProductLinks = Array.isArray(machineProductLinks.value)
      ? machineProductLinks.value
      : Array.isArray(machine.value?.productLinks)
        ? machine.value.productLinks
        : []

    ;(type.productRequirements || []).forEach((requirement) => {
      const matches = existingProductLinks.filter((link) => {
        const requirementId = resolveIdentifier(
          link?.typeMachineProductRequirementId,
          link?.requirementId,
        )
        return requirementId === requirement.id
      })

      const entries = matches.map((link) => createProductSelectionEntry(requirement, link))

      const min = requirement.minCount ?? (requirement.required ? 1 : 0)
      while (entries.length < min) {
        entries.push(createProductSelectionEntry(requirement))
      }

      if (entries.length) {
        productRequirementSelections[requirement.id] = entries
      }
    })
  } finally {
    skeletonEditor.loading = false
  }
}

const openSkeletonEditor = async () => {
  if (skeletonEditor.open) {
    return
  }
  skeletonEditor.open = true
  await initializeSkeletonRequirementSelections()
}

const closeSkeletonEditor = () => {
  if (!skeletonEditor.open) {
    return
  }
  if (skeletonEditor.submitting) {
    return
  }
  skeletonEditor.open = false
  skeletonEditor.loading = false
  skeletonEditor.submitting = false
  resetSkeletonRequirementSelections()
}

const changeMachineView = async (view) => {
  if (view === activeMachineView.value) {
    return
  }

  if (view === 'skeleton') {
    if (!machineHasSkeletonRequirements.value) {
      toast.showInfo('Aucun squelette configuré pour cette machine.')
      return
    }

    activeMachineView.value = 'skeleton'

    if (!skeletonEditor.open) {
      try {
        await openSkeletonEditor()
      } catch (error) {
        console.error('Impossible d\'ouvrir l\'éditeur de squelette:', error)
        toast.showError('Impossible de charger les éléments du squelette.')
        activeMachineView.value = 'details'
      }
    }
    return
  }

  closeSkeletonEditor()
  activeMachineView.value = 'details'
}

const computeSkeletonProductUsage = (type) => {
  const usage = new Map()

  const increment = (typeProductId) => {
    if (!typeProductId) {
      return
    }
    usage.set(typeProductId, (usage.get(typeProductId) ?? 0) + 1)
  }

  for (const requirement of type.componentRequirements || []) {
    const entries = getComponentRequirementEntries(requirement.id)
    entries.forEach((entry) => {
      if (!entry?.composantId) {
        return
      }
      const component = findComponentById(components.value, entry.composantId)
      const typeProductId =
        component?.product?.typeProductId ||
        component?.product?.typeProduct?.id ||
        null
      increment(typeProductId)
    })
  }

  for (const requirement of type.pieceRequirements || []) {
    const entries = getPieceRequirementEntries(requirement.id)
    entries.forEach((entry) => {
      if (!entry?.pieceId) {
        return
      }
      const piece = findPieceById(entry.pieceId)
      const typeProductId =
        piece?.product?.typeProductId ||
        piece?.product?.typeProduct?.id ||
        null
      increment(typeProductId)
    })
  }

  for (const requirement of type.productRequirements || []) {
    const entries = getProductRequirementEntries(requirement.id)
    entries.forEach((entry) => {
      if (!entry?.productId) {
        return
      }
      const product = findProductById(entry.productId)
      const typeProductId =
        product?.typeProductId ||
        product?.typeProduct?.id ||
        entry?.typeProductId ||
        requirement?.typeProductId ||
        requirement?.typeProduct?.id ||
        null
      increment(typeProductId)
    })
  }

  return usage
}

const validateSkeletonSelections = (type) => {
  const errors = []
  const componentLinksPayload = []
  const pieceLinksPayload = []
  const productLinksPayload = []

  for (const requirement of type.componentRequirements || []) {
    const entries = getComponentRequirementEntries(requirement.id)
    const min = requirement.minCount ?? (requirement.required ? 1 : 0)
    const max = requirement.maxCount ?? null

    if (entries.length < min) {
      errors.push(
        `Le groupe "${requirement.label || requirement.typeComposant?.name || 'Composants'}" nécessite au moins ${min} élément(s).`,
      )
    }

    if (max !== null && entries.length > max) {
      errors.push(
        `Le groupe "${requirement.label || requirement.typeComposant?.name || 'Composants'}" ne peut dépasser ${max} élément(s).`,
      )
    }

    entries.forEach((entry) => {
      const resolvedTypeId = entry.typeComposantId || requirement.typeComposantId || null
      if (!resolvedTypeId) {
        errors.push(
          `Le groupe "${requirement.label || requirement.typeComposant?.name || 'Composants'}" nécessite un type de composant.`,
        )
        return
      }

      const payload = {
        requirementId: requirement.id,
        typeComposantId: resolvedTypeId,
      }

      if (entry.linkId) {
        payload.id = entry.linkId
        payload.linkId = entry.linkId
      }

      if (entry.composantId) {
        payload.composantId = entry.composantId
      }

      const overrides = sanitizeDefinitionOverrides(entry.definition)
      if (overrides) {
        payload.overrides = overrides
      }

      Object.assign(
        payload,
        extractParentLinkIdentifiers(requirement),
        extractParentLinkIdentifiers(entry),
      )

      componentLinksPayload.push(payload)
    })
  }

  for (const requirement of type.pieceRequirements || []) {
    const entries = getPieceRequirementEntries(requirement.id)
    const min = requirement.minCount ?? (requirement.required ? 1 : 0)
    const max = requirement.maxCount ?? null

    if (entries.length < min) {
      errors.push(
        `Le groupe "${requirement.label || requirement.typePiece?.name || 'Pièces'}" nécessite au moins ${min} élément(s).`,
      )
    }

    if (max !== null && entries.length > max) {
      errors.push(
        `Le groupe "${requirement.label || requirement.typePiece?.name || 'Pièces'}" ne peut dépasser ${max} élément(s).`,
      )
    }

    entries.forEach((entry) => {
      const resolvedTypeId = entry.typePieceId || requirement.typePieceId || null
      if (!resolvedTypeId) {
        errors.push(
          `Le groupe "${requirement.label || requirement.typePiece?.name || 'Pièces'}" nécessite un type de pièce.`,
        )
        return
      }

      const payload = {
        requirementId: requirement.id,
        typePieceId: resolvedTypeId,
      }

      if (entry.linkId) {
        payload.id = entry.linkId
        payload.linkId = entry.linkId
      }

      if (entry.pieceId) {
        payload.pieceId = entry.pieceId
      }

      if (entry.composantId) {
        payload.composantId = entry.composantId
      }

      const overrides = sanitizeDefinitionOverrides(entry.definition)
      if (overrides) {
        payload.overrides = overrides
      }

      Object.assign(
        payload,
        extractParentLinkIdentifiers(requirement),
        extractParentLinkIdentifiers(entry),
      )

      pieceLinksPayload.push(payload)
    })
  }

  const productUsage = computeSkeletonProductUsage(type)

  for (const requirement of type.productRequirements || []) {
    const entries = getProductRequirementEntries(requirement.id)
    const max = requirement.maxCount ?? null

    if (max !== null && entries.length > max) {
      errors.push(
        `Le groupe "${requirement.label || requirement.typeProduct?.name || 'Produits'}" ne peut dépasser ${max} sélection(s) directe(s).`,
      )
    }

    const typeProductId =
      requirement.typeProductId ||
      requirement.typeProduct?.id ||
      null

    const count = typeProductId ? productUsage.get(typeProductId) ?? 0 : 0
    const min = requirement.minCount ?? (requirement.required ? 1 : 0)

    if (count < min) {
      errors.push(
        `Le groupe "${requirement.label || requirement.typeProduct?.name || 'Produits'}" nécessite au moins ${min} sélection(s).`,
      )
    }

    if (max !== null && count > max) {
      errors.push(
        `Le groupe "${requirement.label || requirement.typeProduct?.name || 'Produits'}" ne peut dépasser ${max} sélection(s).`,
      )
    }

    entries.forEach((entry) => {
      if (!entry.productId) {
        errors.push(
          `Sélectionner un produit pour "${requirement.label || requirement.typeProduct?.name || 'Produits'}".`,
        )
        return
      }

      const product = findProductById(entry.productId)
      if (!product) {
        errors.push(`Le produit sélectionné est introuvable (ID: ${entry.productId}).`)
        return
      }

      const productTypeId =
        product.typeProductId ||
        product.typeProduct?.id ||
        entry.typeProductId ||
        null

      if (
        typeProductId &&
        productTypeId &&
        productTypeId !== typeProductId
      ) {
        errors.push(
          `Le produit "${product.name || product.reference || product.id}" n'appartient pas à la catégorie attendue.`,
        )
        return
      }

      const payload = {
        requirementId: requirement.id,
        productId: entry.productId,
      }

      if (entry.linkId) {
        payload.id = entry.linkId
        payload.linkId = entry.linkId
      }

      if (entry.typeProductId) {
        payload.typeProductId = entry.typeProductId
      }

      Object.assign(
        payload,
        extractParentLinkIdentifiers(requirement),
        extractParentLinkIdentifiers(entry),
      )

      productLinksPayload.push(payload)
    })
  }

  if (errors.length > 0) {
    return { valid: false, error: errors[0] }
  }

  return {
    valid: true,
    componentLinks: componentLinksPayload,
    pieceLinks: pieceLinksPayload,
    productLinks: productLinksPayload,
  }
}

const applySkeletonReconfigurationResult = async (data) => {
  if (!data) return

  const updatedMachine = data.machine || data
  if (updatedMachine) {
    machine.value = {
      ...machine.value,
      ...updatedMachine,
      documents: updatedMachine.documents || machine.value?.documents || [],
    }
    initMachineFields()
    machineDocumentsLoaded.value = !!(machine.value.documents?.length)
  }

  const linksApplied = applyMachineLinks(data) || applyMachineLinks(updatedMachine)
  if (linksApplied) {
    if (machine.value) {
      machine.value.componentLinks = machineComponentLinks.value
      machine.value.pieceLinks = machinePieceLinks.value
      machine.value.productLinks = machineProductLinks.value
    }
    collapseAllComponents()
    return
  }

  const newComponents = data.components ?? updatedMachine?.components ?? null
  if (Array.isArray(newComponents)) {
    components.value = transformComponentCustomFields(newComponents)
    collapseAllComponents()
  }

  const newPieces = data.pieces ?? updatedMachine?.pieces ?? null
  if (Array.isArray(newPieces)) {
    pieces.value = transformCustomFields(newPieces)
  }

  const productLinks = resolveLinkArray(data, ['productLinks', 'machineProductLinks'])
    ?? resolveLinkArray(updatedMachine, ['productLinks', 'machineProductLinks'])
  if (Array.isArray(productLinks)) {
    machineProductLinks.value = productLinks
    if (machine.value) {
      machine.value.productLinks = productLinks
    }
  }

}

const saveSkeletonConfiguration = async () => {
  if (!machine.value?.id) {
    return
  }

  const type = machineType.value
  let payload = { componentLinks: [], pieceLinks: [], productLinks: [] }

  if (type && machineHasSkeletonRequirements.value) {
    const validation = validateSkeletonSelections(type)
    if (!validation.valid) {
      toast.showError(validation.error)
      return
    }
    payload = {
      componentLinks: validation.componentLinks,
      pieceLinks: validation.pieceLinks,
      productLinks: validation.productLinks,
    }
  }

  skeletonEditor.submitting = true
  try {
    const result = await reconfigureMachineSkeleton(machine.value.id, payload)
    if (result.success) {
      await applySkeletonReconfigurationResult(result.data)
      await changeMachineView('details')
    } else if (result.error) {
      toast.showError(result.error)
    }
  } catch (error) {
    console.error('Erreur lors de la reconfiguration du squelette de la machine:', error)
    toast.showError('Erreur lors de la mise à jour des éléments du squelette')
  } finally {
    skeletonEditor.submitting = false
    skeletonEditor.loading = false
  }
}

const handleMachineConstructeurChange = async (value) => {
  machineConstructeurIds.value = uniqueConstructeurIds(value)
  await updateMachineInfo()
}

// Mode d'édition
const isEditMode = ref(false)
const debug = ref(false) // Ajout de debug pour afficher les infos de debug

const machineViewTitle = computed(() => {
  if (isSkeletonView.value) {
    return 'Squelette de la machine'
  }
  return isEditMode.value ? 'Modification de la machine' : 'Détails de la machine'
})

// Gestion du pliage global des composants
const componentsCollapsed = ref(true)
const collapseToggleToken = ref(0)

const toggleAllComponents = () => {
  componentsCollapsed.value = !componentsCollapsed.value
  collapseToggleToken.value += 1
}

const collapseAllComponents = () => {
  componentsCollapsed.value = true
  collapseToggleToken.value += 1
}

// Méthodes pour initialiser les champs
const initMachineFields = () => {
  if (machine.value) {
    machineName.value = machine.value.name || ''
    machineReference.value = machine.value.reference || ''
    machineConstructeurIds.value = uniqueConstructeurIds(
      machine.value.constructeurIds,
      machine.value.constructeurs,
      machine.value.constructeur,
    )
  }
}

// Fonctions pour générer des IDs uniques
const getMachineFieldId = (fieldName) => {
  return machine.value ? `machine-${fieldName}-${machine.value.id}` : `machine-${fieldName}`
}

// Computed
const machinePieces = computed(() => {
  const filteredPieces = pieces.value.filter((piece) => {
    const parentLinkId = resolveIdentifier(
      piece.parentComponentLinkId,
      piece.machinePieceLink?.parentComponentLinkId,
      piece.parentLinkId,
    )
    if (parentLinkId) {
      return false
    }
    return !piece.composantId
  })
  return filteredPieces
})

const machineDocumentsList = computed(() => machine.value?.documents || [])
const documentIcon = (doc) => getFileIcon({ name: doc.filename || doc.name, mime: doc.mimeType })

const flattenComponents = (list = []) => {
  const result = []
  const traverse = (items) => {
    items.forEach((item) => {
      result.push(item)
      if (item.subComponents && item.subComponents.length) {
        traverse(item.subComponents)
      }
    })
  }
  traverse(list)
  return result
}

const flattenedComponents = computed(() => flattenComponents(components.value))

const collectConstructeurs = (...sources) => {
  const ids = uniqueConstructeurIds(...sources)
  if (!ids.length) {
    return []
  }

  const pools = sources
    .flatMap((source) => {
      if (Array.isArray(source)) {
        return [source]
      }
      if (source && typeof source === 'object' && source.id) {
        return [[source]]
      }
      return []
    })
    .filter(Boolean)

  return resolveConstructeurs(ids, ...pools)
}

const componentRequirementGroups = computed(() => {
  const requirements = machine.value?.typeMachine?.componentRequirements || []
  if (!requirements.length) return []

  const groups = requirements.map((requirement) => ({
    requirement,
    components: [],
  }))

  const map = new Map(groups.map((group) => [group.requirement.id, group]))

  flattenedComponents.value.forEach((component) => {
    const reqId = component.typeMachineComponentRequirementId
    if (reqId && map.has(reqId)) {
      map.get(reqId).components.push({
        ...component,
        __productDisplay: getProductDisplay(component),
      })
    }
  })

  return groups
})

const pieceRequirementGroups = computed(() => {
  const requirements = machine.value?.typeMachine?.pieceRequirements || []
  if (!requirements.length) return []

  const groups = requirements.map((requirement) => ({
    requirement,
    pieces: [],
  }))

  const map = new Map(groups.map((group) => [group.requirement.id, group]))

  const collectPieces = () => {
    const collected = []

    // Pièces rattachées à la machine directement
    machinePieces.value.forEach((piece) => {
      collected.push({
        ...piece,
        constructeurs: piece.constructeurs || [],
        parentComponentName: null,
        __productDisplay: getProductDisplay(piece),
      })
    })

    // Pièces rattachées aux composants
    flattenedComponents.value.forEach((component) => {
      if (component.pieces && component.pieces.length) {
        component.pieces.forEach((piece) => {
          collected.push({
            ...piece,
            constructeurs: piece.constructeurs || [],
            parentComponentName: component.name,
            __productDisplay: getProductDisplay(piece),
          })
        })
      }
    })

    return collected
  }

  collectPieces().forEach((piece) => {
    const reqId = piece.typeMachinePieceRequirementId
    if (reqId && map.has(reqId)) {
      map.get(reqId).pieces.push(piece)
    }
  })

  return groups
})

const productRequirementGroups = computed(() => {
  const requirements = machine.value?.typeMachine?.productRequirements || []
  if (!requirements.length) return []

  const componentAggregates = flattenedComponents.value || []
  const pieceAggregates = collectPiecesForSkeleton()
  const links = Array.isArray(machineProductLinks.value) ? machineProductLinks.value : []

  return requirements.map((requirement) => {
    const typeProductId =
      requirement.typeProductId ||
      requirement.typeProduct?.id ||
      null

    const directProducts = links
      .filter((link) => {
        const requirementId = resolveIdentifier(
          link?.typeMachineProductRequirementId,
          link?.requirementId,
        )
        return requirementId === requirement.id
      })
      .map((link) => {
        const productId = resolveIdentifier(link?.productId, link?.product?.id)
        const product =
          productId ? findProductById(productId) : link?.product ?? null

        const supplierLabel = Array.isArray(product?.constructeurs)
          ? product.constructeurs.map((constructeur) => constructeur?.name).filter(Boolean).join(', ')
          : link?.constructeursLabel || null

        const priceValue =
          product?.supplierPrice ??
          link?.supplierPrice ??
          null

        let priceLabel = null
        if (priceValue !== undefined && priceValue !== null) {
          const numericPrice = Number(priceValue)
          if (!Number.isNaN(numericPrice)) {
            priceLabel = `${numericPrice.toFixed(2)} €`
          }
        }

        return {
          id: productId || link?.id || null,
          name: product?.name || link?.productName || productId || 'Produit',
          reference: product?.reference || link?.reference || null,
          supplierLabel,
          priceLabel,
        }
      })

    let componentCount = 0
    componentAggregates.forEach((component) => {
      const componentTypeProductId =
        component?.product?.typeProductId ||
        component?.product?.typeProduct?.id ||
        null
      if (typeProductId && componentTypeProductId === typeProductId) {
        componentCount += 1
      }
    })

    let pieceCount = 0
    pieceAggregates.forEach((piece) => {
      const pieceTypeProductId =
        piece?.product?.typeProductId ||
        piece?.product?.typeProduct?.id ||
        null
      if (typeProductId && pieceTypeProductId === typeProductId) {
        pieceCount += 1
      }
    })

    const totalCount = directProducts.length + componentCount + pieceCount

    return {
      requirement,
      directProducts,
      componentCount,
      pieceCount,
      totalCount,
    }
  })
})

const machineDirectProducts = computed(() => {
  return productRequirementGroups.value.flatMap((group) =>
    (group.directProducts || []).map((product) => ({
      ...product,
      groupLabel:
        group.requirement.label ||
        group.requirement.typeProduct?.name ||
        'Produit requis',
    })),
  )
})

const findComponentById = (items, id) => {
  for (const item of items || []) {
    if (item.id === id) return item
    const found = findComponentById(item.subComponents, id)
    if (found) return found
  }
  return null
}

const findPieceById = (pieceId) => {
  const direct = pieces.value.find((piece) => piece.id === pieceId)
  if (direct) return direct

  const searchInComponents = (items) => {
    for (const item of items || []) {
      const match = (item.pieces || []).find((piece) => piece.id === pieceId)
      if (match) return match
      const nested = searchInComponents(item.subComponents)
      if (nested) return nested
    }
    return null
  }

  return searchInComponents(components.value)
}

const refreshMachineDocuments = async () => {
  if (!machine.value?.id) return
  const result = await loadDocumentsByMachine(machine.value.id, { updateStore: false })
  if (result.success && machine.value) {
    machine.value.documents = result.data || []
    machineDocumentsLoaded.value = true
  }
}

const handleMachineFilesAdded = async (files) => {
  if (!files.length || !machine.value?.id) return
  machineDocumentsUploading.value = true
  try {
    const result = await uploadDocuments(
      {
        files,
        context: { machineId: machine.value.id }
      },
      { updateStore: false }
    )

    if (result.success && machine.value) {
      const newDocs = result.data || []
      machine.value.documents = [...newDocs, ...(machine.value.documents || [])]
      machineDocumentFiles.value = []
    }
  } finally {
    machineDocumentsUploading.value = false
  }
}

const removeMachineDocument = async (documentId) => {
  if (!documentId) return
  const result = await deleteDocument(documentId, { updateStore: false })
  if (result.success && machine.value) {
    machine.value.documents = (machine.value.documents || []).filter(doc => doc.id !== documentId)
  }
}

const downloadDocument = (doc) => {
  if (!doc?.path) return

  if (doc.path.startsWith('data:')) {
    const link = document.createElement('a')
    link.href = doc.path
    link.download = doc.filename || doc.name || 'document'
    link.click()
    return
  }

  window.open(doc.path, '_blank')
}

const openPreview = (doc) => {
  if (!canPreviewDocument(doc)) return
  previewDocument.value = doc
  previewVisible.value = true
}

const closePreview = () => {
  previewVisible.value = false
  previewDocument.value = null
}

// Print functions → imported from useMachinePrint composable
const ensurePrintSelectionEntries = () => _ensurePrintEntries(components.value, machinePieces.value)
const setAllPrintSelection = (value) => _setAllPrint(value, components.value, machinePieces.value)
const openPrintModal = () => _openPrintModal(components.value, machinePieces.value)
const handlePrintConfirm = () => _handlePrintConfirm(machine.value, machineName.value, machineReference.value, machinePieces.value, components.value)

const formatSize = (size) => {
  if (size === undefined || size === null) return '—'
  if (size === 0) return '0 B'
  const units = ['B', 'KB', 'MB', 'GB']
  const index = Math.min(units.length - 1, Math.floor(Math.log(size) / Math.log(1024)))
  const formatted = size / Math.pow(1024, index)
  return `${formatted.toFixed(1)} ${units[index]}`
}

const PDF_PREVIEW_MAX_BYTES = 5 * 1024 * 1024

const shouldInlinePdf = (document) => {
  if (!document || !isPdfDocument(document) || !document.path) {
    return false
  }
  if (typeof document.size === 'number' && document.size > PDF_PREVIEW_MAX_BYTES) {
    return false
  }
  return true
}

const appendPdfViewerParams = (src) => {
  if (!src || src.startsWith('data:')) {
    return src || ''
  }
  if (src.includes('#')) {
    return `${src}&toolbar=0&navpanes=0`
  }
  return `${src}#toolbar=0&navpanes=0`
}

const documentPreviewSrc = (document) => {
  if (!document?.path) {
    return ''
  }
  if (isPdfDocument(document)) {
    return appendPdfViewerParams(document.path)
  }
  return document.path
}

const documentThumbnailClass = (document) => {
  if (shouldInlinePdf(document) || (isImageDocument(document) && document?.path)) {
    return 'h-24 w-20'
  }
  return 'h-16 w-16'
}

// formatCustomFieldValue, shouldDisplayCustomField → imported from customFieldUtils

const visibleMachineCustomFields = computed(() => {
  const fields = Array.isArray(machineCustomFields.value) ? machineCustomFields.value : []
  if (isEditMode.value) {
    return fields
  }
  return fields.filter((field) => shouldDisplayCustomField(field))
})

// summarizeCustomFields → imported from customFieldUtils

// extractDefinitionName, extractDefinitionType, extractDefinitionRequired,
// extractOptionList, extractDefinitionOptions, extractDefinitionDefaultValue,
// coerceValueForType, normalizeExistingCustomFieldDefinitions,
// normalizeCustomFieldDefinitionEntry
// → all imported from customFieldUtils

// extractDefinitionRequired → imported from customFieldUtils

// extractOptionList → imported from customFieldUtils

// extractDefinitionOptions → imported from customFieldUtils

// extractDefinitionDefaultValue → imported from customFieldUtils

// coerceValueForType → imported from customFieldUtils

// normalizeExistingCustomFieldDefinitions → imported from customFieldUtils

// normalizeCustomFieldDefinitionEntry → imported from customFieldUtils

const getStructureCustomFields = (structure) => {
  if (!structure || typeof structure !== 'object') {
    return []
  }
  const normalized = normalizeStructureForEditor(structure)
  return Array.isArray(normalized.customFields) ? normalized.customFields : []
}

// normalizeCustomFieldValueEntry → imported from customFieldUtils

// mergeCustomFieldValuesWithDefinitions → imported from customFieldUtils

// dedupeCustomFieldEntries → imported from customFieldUtils

const transformCustomFields = (pieces) => {
  return (pieces || []).map((piece) => {
    const requirement = piece.typeMachinePieceRequirement || {}
    const typePiece = requirement.typePiece || piece.typePiece || {}

    const normalizeStructureDefinitions = (structure) => (
      structure ? normalizeStructureForEditor(structure) : null
    )

    const normalizedStructureDefinitions = [
      normalizeStructureDefinitions(piece.definition?.structure),
      normalizeStructureDefinitions(piece.typePiece?.structure),
      normalizeStructureDefinitions(typePiece.structure),
      normalizeStructureDefinitions(typePiece.pieceSkeleton),
      normalizeStructureDefinitions(piece.typePiece?.pieceSkeleton),
      normalizeStructureDefinitions(requirement.structure),
      normalizeStructureDefinitions(requirement.pieceSkeleton),
    ]

    const valueEntries = [
      ...(Array.isArray(piece.customFieldValues) ? piece.customFieldValues : []),
      ...(Array.isArray(piece.customFields)
        ? piece.customFields
            .map(normalizeCustomFieldValueEntry)
            .filter((entry) => entry !== null)
        : []),
      ...(Array.isArray(typePiece.customFieldValues)
        ? typePiece.customFieldValues
            .map(normalizeCustomFieldValueEntry)
            .filter((entry) => entry !== null)
        : []),
    ]

    const customFields = dedupeCustomFieldEntries(
      mergeCustomFieldValuesWithDefinitions(
        valueEntries,
        normalizeExistingCustomFieldDefinitions(piece.customFields),
        normalizeExistingCustomFieldDefinitions(piece.definition?.customFields),
        normalizeExistingCustomFieldDefinitions(piece.typePiece?.customFields),
        normalizeExistingCustomFieldDefinitions(typePiece.customFields),
        normalizeExistingCustomFieldDefinitions(requirement.typePiece?.customFields),
        normalizeExistingCustomFieldDefinitions(requirement.customFields),
        normalizeExistingCustomFieldDefinitions(requirement.definition?.customFields),
        ...normalizedStructureDefinitions.map((definition) =>
          getStructureCustomFields(definition),
        ),
      ),
    )

    const constructeurIds = uniqueConstructeurIds(
      piece.constructeurIds,
      piece.constructeurId,
      piece.constructeur,
      piece.originalPiece?.constructeurIds,
      piece.originalPiece?.constructeurId,
      piece.originalPiece?.constructeur,
    )

    const { product: resolvedProduct, productId: resolvedProductId } = resolveProductReference(piece)

    const constructeursList = resolveConstructeurs(
      constructeurIds,
      Array.isArray(piece.constructeurs) ? piece.constructeurs : [],
      piece.constructeur ? [piece.constructeur] : [],
      Array.isArray(piece.originalPiece?.constructeurs)
        ? piece.originalPiece?.constructeurs
        : [],
      piece.originalPiece?.constructeur ? [piece.originalPiece.constructeur] : [],
      constructeurs.value,
    )
    const normalizedPiece = {
      ...piece,
      product: resolvedProduct || piece.product || null,
      productId:
        resolvedProductId ||
        piece.productId ||
        piece.product?.id ||
        null,
    }
    const productDisplay = getProductDisplay(normalizedPiece)

    return {
      ...normalizedPiece,
      customFields,
      documents: piece.documents || [],
      constructeurs: constructeursList,
      constructeur: constructeursList[0] || piece.constructeur || null,
      constructeurIds,
      constructeurId: constructeurIds[0] || null,
      typePieceId: piece.typePieceId
        || piece.typeMachinePieceRequirement?.typePieceId
        || piece.typePiece?.id
        || null,
      __productDisplay: productDisplay,
    }
  })
}

// Transform custom fields for components (now handles nested structure)
const transformComponentCustomFields = (componentsData) => {
  const normalizeStructureDefinitions = (structure) => (
    structure ? normalizeStructureForEditor(structure) : null
  )

  return (componentsData || []).map((component) => {
    const requirement = component.typeMachineComponentRequirement || {}
    const type = requirement.typeComposant || component.typeComposant || {}

    const normalizedStructureDefinitions = [
      normalizeStructureDefinitions(component.definition?.structure),
      normalizeStructureDefinitions(component.typeComposant?.structure),
      normalizeStructureDefinitions(type.structure),
      normalizeStructureDefinitions(type.componentSkeleton),
      normalizeStructureDefinitions(requirement.structure),
      normalizeStructureDefinitions(requirement.componentSkeleton),
    ]

    const actualComponent = component.originalComposant || component

    const valueEntries = [
      ...(Array.isArray(component.customFieldValues) ? component.customFieldValues : []),
      ...(Array.isArray(component.customFields)
        ? component.customFields
            .map(normalizeCustomFieldValueEntry)
            .filter((entry) => entry !== null)
        : []),
      ...(Array.isArray(actualComponent?.customFields)
        ? actualComponent.customFields
            .map(normalizeCustomFieldValueEntry)
            .filter((entry) => entry !== null)
        : []),
    ]

    const customFields = dedupeCustomFieldEntries(
      mergeCustomFieldValuesWithDefinitions(
        valueEntries,
        normalizeExistingCustomFieldDefinitions(component.customFields),
        normalizeExistingCustomFieldDefinitions(component.definition?.customFields),
        normalizeExistingCustomFieldDefinitions(component.typeComposant?.customFields),
        normalizeExistingCustomFieldDefinitions(type.customFields),
        normalizeExistingCustomFieldDefinitions(actualComponent?.customFields),
        normalizeExistingCustomFieldDefinitions(requirement.typeComposant?.customFields),
        normalizeExistingCustomFieldDefinitions(requirement.customFields),
        normalizeExistingCustomFieldDefinitions(requirement.definition?.customFields),
        ...normalizedStructureDefinitions.map((definition) =>
          getStructureCustomFields(definition),
        ),
      ),
    )

    const pieces = component.pieces
      ? transformCustomFields(component.pieces).map((piece) => ({
          ...piece,
          parentComponentName: component.name,
        }))
      : []

    const subComponents = component.sousComposants
      ? transformComponentCustomFields(component.sousComposants)
      : []

    const constructeurIds = uniqueConstructeurIds(
      component.constructeurIds,
      component.constructeurId,
      component.constructeur,
      actualComponent?.constructeurIds,
      actualComponent?.constructeurId,
      actualComponent?.constructeur,
    )

    const constructeursList = resolveConstructeurs(
      constructeurIds,
      Array.isArray(component.constructeurs) ? component.constructeurs : [],
      component.constructeur ? [component.constructeur] : [],
      Array.isArray(actualComponent?.constructeurs) ? actualComponent.constructeurs : [],
      actualComponent?.constructeur ? [actualComponent.constructeur] : [],
      constructeurs.value,
    )
    const { product: resolvedProduct, productId: resolvedProductId } = resolveProductReference(component)
    const normalizedComponent = {
      ...component,
      product: resolvedProduct || component.product || null,
      productId:
        resolvedProductId ||
        component.productId ||
        component.product?.id ||
        null,
    }
    const productDisplay = getProductDisplay(normalizedComponent)

    return {
      ...normalizedComponent,
      customFields,
      pieces,
      subComponents,
      documents: component.documents || [],
      constructeurs: constructeursList,
      constructeur: constructeursList[0] || component.constructeur || null,
      constructeurIds,
      constructeurId: constructeurIds[0] || null,
      typeComposantId: component.typeComposantId
        || component.typeMachineComponentRequirement?.typeComposantId
        || component.typeComposant?.id
        || null,
      __productDisplay: productDisplay,
    }
  })
}

const syncMachineCustomFields = () => {
  if (!machine.value) {
    machineCustomFields.value = []
    return
  }

  const valueEntries = [
    ...(Array.isArray(machine.value.customFieldValues) ? machine.value.customFieldValues : []),
    ...(Array.isArray(machine.value.customFields)
      ? machine.value.customFields
          .map(normalizeCustomFieldValueEntry)
          .filter((entry) => entry !== null)
      : []),
  ]

  const merged = dedupeCustomFieldEntries(
    mergeCustomFieldValuesWithDefinitions(
      valueEntries,
      normalizeExistingCustomFieldDefinitions(machine.value.customFields),
      normalizeExistingCustomFieldDefinitions(machine.value.typeMachine?.customFields),
    ),
  ).map((field) => ({
    ...field,
    readOnly: false,
  }))

  machineCustomFields.value = merged
}

// mergePieceLists, mergeComponentTrees → imported from useMachineHierarchy
// buildMachineHierarchyFromLinks → imported from useMachineHierarchy

// resolveLinkArray → imported from useMachineHierarchy

const applyMachineLinks = (source) => {
  const container = source?.machine ?? null
  const componentLinks =
    resolveLinkArray(source, ['componentLinks', 'machineComponentLinks']) ??
    resolveLinkArray(container, ['componentLinks', 'machineComponentLinks'])
  const pieceLinks =
    resolveLinkArray(source, ['pieceLinks', 'machinePieceLinks']) ??
    resolveLinkArray(container, ['pieceLinks', 'machinePieceLinks'])
  const productLinks =
    resolveLinkArray(source, ['productLinks', 'machineProductLinks']) ??
    resolveLinkArray(container, ['productLinks', 'machineProductLinks'])

  if (componentLinks === null && pieceLinks === null && productLinks === null) {
    return false
  }

  const normalizedComponentLinks = componentLinks ?? []
  const normalizedPieceLinks = pieceLinks ?? []
  const normalizedProductLinks = productLinks ?? []

  machineComponentLinks.value = normalizedComponentLinks
  machinePieceLinks.value = normalizedPieceLinks
  machineProductLinks.value = normalizedProductLinks

  const { components: hierarchy, machinePieces: machineLevelPieces } =
    buildMachineHierarchyFromLinks(normalizedComponentLinks, normalizedPieceLinks, findProductById, constructeurs.value)

  components.value = transformComponentCustomFields(hierarchy)
  pieces.value = transformCustomFields(machineLevelPieces)

  return true
}

// Methods
const loadMachineData = async () => {
  loading.value = true
  try {
    const machineResult = await get(`/machines/${machineId}/skeleton`)

    if (!machineResult.success) {
      console.error('Machine non trouvée:', machineId, machineResult.error)
      machine.value = null
      components.value = []
      pieces.value = []
      return
    }

    const machinePayload = machineResult.data?.machine && typeof machineResult.data.machine === 'object'
      ? machineResult.data.machine
      : machineResult.data

    if (!machinePayload || typeof machinePayload !== 'object') {
      console.error('Réponse machine invalide pour', machineId)
      machine.value = null
      components.value = []
      pieces.value = []
      return
    }

    machine.value = {
      ...machinePayload,
      documents: machinePayload.documents || [],
      customFieldValues: machinePayload.customFieldValues || [],
    }

    machineDocumentsLoaded.value = machine.value.documents.length > 0
    syncMachineCustomFields()
    initMachineFields()

    if (!productInventory.value.length) {
      try {
        await loadProducts()
      } catch (error) {
        console.error('Erreur lors du chargement des produits:', error)
      }
    }

    const linksApplied = applyMachineLinks(machineResult.data)

    if (machine.value) {
      machine.value.componentLinks = machineComponentLinks.value
      machine.value.pieceLinks = machinePieceLinks.value
      machine.value.productLinks = machineProductLinks.value
    }

    if (!linksApplied) {
      components.value = transformComponentCustomFields(machinePayload.components || [])
      pieces.value = transformCustomFields(machinePayload.pieces || [])
      machineProductLinks.value = Array.isArray(machinePayload.productLinks)
        ? machinePayload.productLinks
        : []
    }

    if (machine.value) {
      machine.value.productLinks = machineProductLinks.value
    }

    collapseAllComponents()

    if (!machineDocumentsLoaded.value) {
      await refreshMachineDocuments()
    }
  } catch (error) {
    console.error('Erreur lors du chargement des données:', error)
  } finally {
    loading.value = false
  }
}

const updateMachineInfo = async () => {
  if (!machine.value) return

  try {
    const constructeurIds = uniqueConstructeurIds(machineConstructeurIds.value)
    machineConstructeurIds.value = constructeurIds

    const result = await updateMachineApi(machine.value.id, {
      name: machineName.value,
      reference: machineReference.value,
      constructeurIds,
    })
    if (result.success) {
      const machinePayload = result.data?.machine && typeof result.data.machine === 'object'
        ? result.data.machine
        : result.data

      if (machinePayload && typeof machinePayload === 'object') {
        machine.value = {
          ...machine.value,
          ...machinePayload,
          documents: machinePayload.documents || machine.value.documents || [],
          customFieldValues: machinePayload.customFieldValues || machine.value.customFieldValues || [],
        }
        machineConstructeurIds.value = uniqueConstructeurIds(
          machine.value.constructeurIds,
          machine.value.constructeurs,
          machine.value.constructeur,
        )

        const linksApplied = applyMachineLinks(result.data)
        if (linksApplied && machine.value) {
          machine.value.componentLinks = machineComponentLinks.value
          machine.value.pieceLinks = machinePieceLinks.value
        }
      }
    }
  } catch (error) {
    console.error('Erreur lors de la mise à jour de la machine:', error)
  }
}

const updateComponent = async (updatedComponent) => {
  try {
    const constructeurIds = uniqueConstructeurIds(
      updatedComponent.constructeurIds,
      updatedComponent.constructeurId,
      updatedComponent.constructeur,
    )
    const productId = updatedComponent.productId ? String(updatedComponent.productId) : null
    const prix =
      updatedComponent.prix !== null &&
      updatedComponent.prix !== undefined &&
      String(updatedComponent.prix).trim() !== ''
        ? Number(updatedComponent.prix)
        : null

    const result = await updateComposantApi(updatedComponent.id, {
      name: updatedComponent.name,
      reference: updatedComponent.reference,
      constructeurIds,
      prix: Number.isNaN(prix) ? null : prix,
      productId,
    })
    if (result.success) {
      const transformed = transformComponentCustomFields([result.data])[0]
      Object.assign(updatedComponent, transformed)
    }
  } catch (error) {
    console.error('Erreur lors de la mise à jour du composant:', error)
  }
}

const updatePieceFromComponent = async (updatedPiece) => {
  try {
    const constructeurIds = uniqueConstructeurIds(
      updatedPiece.constructeurIds,
      updatedPiece.constructeurId,
      updatedPiece.constructeur,
    )
    const productId = updatedPiece.productId ? String(updatedPiece.productId) : null
    const prix =
      updatedPiece.prix !== null &&
      updatedPiece.prix !== undefined &&
      String(updatedPiece.prix).trim() !== ''
        ? Number(updatedPiece.prix)
        : null

    const result = await updatePieceApi(updatedPiece.id, {
      name: updatedPiece.name,
      reference: updatedPiece.reference,
      constructeurIds,
      prix: Number.isNaN(prix) ? null : prix,
      productId,
    })
    if (result.success) {
      const transformed = transformCustomFields([result.data])[0]
      Object.assign(updatedPiece, transformed)
      // Si la pièce a des champs personnalisés mis à jour, les traiter
      if (updatedPiece.customFields) {
        for (const field of updatedPiece.customFields) {
          if (field.value !== undefined) {
            await upsertCustomFieldValue(
              field.id,
              'piece',
              updatedPiece.id,
              field.value
            )
          }
        }
      }
    }
  } catch (error) {
    console.error('Erreur lors de la mise à jour de la pièce:', error)
  }
}

const updatePieceInfo = async (updatedPiece) => {
  try {
    const constructeurIds = uniqueConstructeurIds(
      updatedPiece.constructeurIds,
      updatedPiece.constructeurId,
      updatedPiece.constructeur,
    )
    const productId = updatedPiece.productId ? String(updatedPiece.productId) : null
    const prix =
      updatedPiece.prix !== null &&
      updatedPiece.prix !== undefined &&
      String(updatedPiece.prix).trim() !== ''
        ? Number(updatedPiece.prix)
        : null

    const result = await updatePieceApi(updatedPiece.id, {
      name: updatedPiece.name,
      reference: updatedPiece.reference,
      constructeurIds,
      prix: Number.isNaN(prix) ? null : prix,
      productId,
    })
    if (result.success) {
      const transformed = transformCustomFields([result.data])[0]
      Object.assign(updatedPiece, transformed)
    }
  } catch (error) {
    console.error('Erreur lors de la mise à jour de la pièce:', error)
  }
}

// Méthodes pour les champs personnalisés de la machine
const setMachineCustomFieldValue = (field, value) => {
  if (!field) {
    return
  }

  field.value = value

  if (field.customFieldValueId && machine.value?.customFieldValues) {
    const stored = machine.value.customFieldValues.find((fv) => fv.id === field.customFieldValueId)
    if (stored) {
      stored.value = value
    }
  }
}

const updateMachineCustomField = async (field) => {
  if (!machine.value || !field) {
    return
  }

  const { id: customFieldId, customFieldValueId } = field
  const fieldLabel = field.name || 'Champ personnalisé'

  try {
    if (customFieldValueId) {
      const result = await updateCustomFieldValueApi(customFieldValueId, { value: field.value ?? '' })
      if (result.success) {
        toast.showSuccess(`Champ "${fieldLabel}" de la machine mis à jour avec succès`)
        syncMachineCustomFields()
      } else {
        toast.showError(`Erreur lors de la mise à jour du champ "${fieldLabel}"`)
      }
      return
    }

    if (!customFieldId) {
      toast.showError('Impossible de mettre à jour ce champ personnalisé (identifiant manquant).')
      return
    }

    const result = await upsertCustomFieldValue(customFieldId, 'machine', machine.value.id, field.value ?? '')
    if (result.success) {
      const createdValue = result.data
      toast.showSuccess(`Champ "${fieldLabel}" de la machine mis à jour avec succès`)

      if (createdValue?.id) {
        if (!createdValue.customField) {
          createdValue.customField = {
            id: customFieldId,
            name: field.name,
            type: field.type,
            required: field.required,
            options: field.options,
          }
        }
        field.customFieldValueId = createdValue.id
        field.readOnly = false

        const existingValues = Array.isArray(machine.value.customFieldValues)
          ? machine.value.customFieldValues.filter((item) => item.id !== createdValue.id)
          : []

        machine.value.customFieldValues = [...existingValues, createdValue]
      }

      syncMachineCustomFields()
    } else {
      toast.showError(`Erreur lors de la mise à jour du champ "${fieldLabel}"`)
    }
  } catch (error) {
    console.error('Erreur lors de la mise à jour du champ personnalisé de la machine:', error)
    toast.showError(`Erreur lors de la mise à jour du champ "${fieldLabel}"`)
  }
}

const updatePieceCustomField = async (fieldUpdate) => {
  const { showSuccess, showError } = useToast()

  try {
    const result = await upsertCustomFieldValue(
      fieldUpdate.fieldId,
      'piece',
      fieldUpdate.pieceId,
      fieldUpdate.value
    )
    if (result.success) {
      showSuccess(`Champ personnalisé mis à jour avec succès`)
    } else {
      showError(`Erreur lors de la mise à jour du champ personnalisé`)
    }
  } catch (error) {
    showError(`Erreur lors de la mise à jour du champ personnalisé`)
    console.error('Erreur lors de la mise à jour du champ personnalisé:', error)
  }
}

const editComponent = () => {
  toast.showInfo('La modification des composants sera bientôt disponible')
}

const editPiece = () => {
  toast.showInfo('La modification des pièces sera bientôt disponible')
}

const toggleEditMode = () => {
  isEditMode.value = !isEditMode.value
  debug.value = !debug.value // Inversez la valeur de debug
  if (isEditMode.value && !machineDocumentsLoaded.value) {
    refreshMachineDocuments()
  }
}

watch(
  () => machine.value?.customFieldValues,
  () => {
    syncMachineCustomFields()
  },
  { deep: true }
)

watch(
  () => machine.value?.customFields,
  () => {
    syncMachineCustomFields()
  },
  { deep: true }
)

watch(
  () => machine.value?.typeMachine?.customFields,
  () => {
    syncMachineCustomFields()
  },
  { deep: true }
)

watch(
  () => [components.value.length, machinePieces.value.length],
  () => {
    ensurePrintSelectionEntries()
  },
  { immediate: true }
)

// Lifecycle
onMounted(() => {
  loadMachineData()
  if (!constructeurs.value.length) {
    loadConstructeurs()
  }
  if (!componentTypes.value.length) {
    loadComponentTypes()
  }
  if (!pieceTypes.value.length) {
    loadPieceTypes()
  }

  // Vérifier si on doit activer le mode édition depuis l'URL
  const route = useRoute()
  if (route.query.edit === 'true') {
    isEditMode.value = true
  }
})
</script> 
