<template>
  <main class="mx-auto flex w-full max-w-5xl flex-col gap-8 px-4 py-8 sm:px-6 lg:px-8">
    <header class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
      <div class="space-y-1">
        <h1 class="text-3xl font-semibold text-base-content">Nouvelle pièce</h1>
        <p class="text-sm text-base-content/70">
          Choisissez la catégorie adaptée puis renseignez toutes les informations de votre pièce.
        </p>
      </div>
      <button type="button" class="btn btn-ghost btn-sm md:btn-md self-start" @click="$router.back()">
        Retour au catalogue
      </button>
    </header>

    <section class="card border border-base-200 bg-base-100 shadow-sm">
      <div class="card-body space-y-6">
        <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
          <div class="form-control">
            <label class="label">
              <span class="label-text">Catégorie de pièce</span>
            </label>
            <SearchSelect
              v-model="selectedTypeId"
              :options="pieceTypeList"
              :loading="loadingTypes"
              size="sm"
              placeholder="Rechercher une catégorie..."
              empty-text="Aucune catégorie disponible"
              :option-label="typeOptionLabel"
              :option-description="typeOptionDescription"
              :disabled="!canEdit || loadingTypes || submitting"
            />
            <p v-if="loadingTypes" class="text-xs text-gray-500 mt-1">
              Chargement des catégories…
            </p>
          </div>
        </div>

        <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
          <div class="form-control">
            <label class="label">
              <span class="label-text">Nom de la pièce</span>
            </label>
            <input
              v-model="creationForm.name"
              type="text"
              class="input input-bordered input-sm md:input-md"
              :disabled="!canEdit || submitting || !selectedType"
              placeholder="Nom affiché dans le catalogue"
              required
            >
          </div>
        </div>

        <div class="form-control">
          <label class="label">
            <span class="label-text">Description</span>
          </label>
          <textarea
            v-model="creationForm.description"
            class="textarea textarea-bordered textarea-sm md:textarea-md"
            :disabled="!canEdit || submitting || !selectedType"
            placeholder="Description de la pièce (optionnel)"
            rows="3"
          />
        </div>

        <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
          <div class="form-control">
            <label class="label">
              <span class="label-text">Référence</span>
            </label>
            <input
              v-model="creationForm.reference"
              type="text"
              class="input input-bordered input-sm md:input-md"
              :disabled="!canEdit || submitting || !selectedType"
              placeholder="Référence interne ou fournisseur"
            >
          </div>

          <div class="form-control">
            <label class="label">
              <span class="label-text">Fournisseur</span>
            </label>
            <ConstructeurSelect
              v-model="creationForm.constructeurIds"
              class="w-full"
              :disabled="!canEdit || submitting || !selectedType"
              placeholder="Rechercher un ou plusieurs fournisseurs..."
            />
          </div>
        </div>

        <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
          <div class="form-control">
            <label class="label">
              <span class="label-text">Prix indicatif (€)</span>
            </label>
            <input
              v-model="creationForm.prix"
              type="number"
              step="0.01"
              min="0"
              class="input input-bordered input-sm md:input-md"
              :disabled="!canEdit || submitting || !selectedType"
              placeholder="Valeur indicatrice"
            >
          </div>
        </div>

        <div
          v-if="structureProducts.length"
          class="space-y-3 rounded-lg border border-base-200 bg-base-200/40 p-4"
        >
          <header class="space-y-1">
            <h2 class="font-semibold text-base-content">
              Produit requis par le squelette
            </h2>
            <p class="text-xs text-base-content/70">
              Sélectionnez un produit catalogue compatible avec les exigences ci-dessous.
            </p>
          </header>
          <ul class="space-y-2 text-sm text-base-content/80">
            <li
              v-for="(description, index) in productRequirementDescriptions"
              :key="`requirement-${index}`"
              class="flex items-start gap-2"
            >
              <span class="mt-0.5 inline-flex h-2 w-2 flex-shrink-0 rounded-full bg-primary"></span>
              <span>{{ description }}</span>
            </li>
          </ul>
          <div class="grid grid-cols-1 gap-3 md:grid-cols-2">
            <div
              v-for="entry in productRequirementEntries"
              :key="entry.key"
              class="form-control"
            >
              <label class="label">
                <span class="label-text text-xs font-medium">
                  {{ entry.label }}
                </span>
              </label>
              <ProductSelect
                :model-value="productSelections[entry.index] || null"
                :disabled="!canEdit || submitting || !selectedType"
                :type-product-id="entry.typeProductId"
                helper-text="Un produit est requis pour cette pièce."
                @update:model-value="(value) => setProductSelection(entry.index, value)"
              />
            </div>
          </div>
        </div>

        <StructureSkeletonPreview
          v-if="selectedType"
          :structure="selectedType.structure"
          :description="selectedType.description || 'Ce squelette définit la structure et les champs personnalisés de la pièce.'"
          :preview-badge="formatPieceStructurePreview(selectedType.structure)"
          variant="piece"
        />

        <div v-if="customFieldInputs.length" class="space-y-4 rounded-lg border border-base-200 bg-base-200/40 p-4">
          <header class="space-y-1">
            <h2 class="font-semibold text-base-content">Champs personnalisés</h2>
            <p class="text-xs text-base-content/70">
              Renseignez les valeurs propres à cette pièce. Ces champs complètent le squelette sélectionné.
            </p>
          </header>
          <CustomFieldInputGrid :fields="customFieldInputs" :disabled="!canEdit || submitting" />
        </div>

        <div class="space-y-4 rounded-lg border border-base-200 bg-base-200/40 p-4">
          <header class="flex flex-col gap-1 md:flex-row md:items-center md:justify-between">
            <div>
              <h2 class="font-semibold text-base-content">Documents</h2>
              <p class="text-xs text-base-content/70">
                Ajoutez des documents (PDF, images, textes…) liés à cette pièce.
              </p>
            </div>
            <span v-if="selectedDocuments.length" class="badge badge-outline">
              {{ selectedDocuments.length }} document{{ selectedDocuments.length > 1 ? 's' : '' }} prêt{{ selectedDocuments.length > 1 ? 's' : '' }} à être ajouté{{ selectedDocuments.length > 1 ? 's' : '' }}
            </span>
          </header>
          <div :class="{ 'pointer-events-none opacity-60': !canEdit || submitting }">
            <DocumentUpload
              v-model="selectedDocuments"
              title="Déposer vos fichiers"
              subtitle="Formats acceptés : PDF, images, documents…"
            />
          </div>
          <p v-if="uploadingDocuments" class="text-xs text-base-content/70">
            Téléversement des documents en cours…
          </p>
        </div>

        <div class="flex flex-col gap-3 md:flex-row md:justify-end">
          <NuxtLink to="/pieces-catalog" class="btn btn-ghost" :class="{ 'btn-disabled': submitting }">
            Annuler
          </NuxtLink>
          <button type="button" class="btn btn-primary" :disabled="!canSubmit" @click="submitCreation">
            <span v-if="submitting" class="loading loading-spinner loading-sm mr-2"></span>
            Créer la pièce
          </button>
        </div>
      </div>
    </section>
  </main>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { useRoute, useRouter } from '#imports'
import ConstructeurSelect from '~/components/ConstructeurSelect.vue'
import DocumentUpload from '~/components/DocumentUpload.vue'
import ProductSelect from '~/components/ProductSelect.vue'
import SearchSelect from '~/components/common/SearchSelect.vue'
import { usePieceTypes } from '~/composables/usePieceTypes'
import { usePieces } from '~/composables/usePieces'
import { useToast } from '~/composables/useToast'
import { humanizeError } from '~/shared/utils/errorMessages'
import { useCustomFields } from '~/composables/useCustomFields'
import { useDocuments } from '~/composables/useDocuments'
import { formatPieceStructurePreview } from '~/shared/modelUtils'
import { uniqueConstructeurIds } from '~/shared/constructeurUtils'
import type { PieceModelStructure } from '~/shared/types/inventory'
import type { ModelType } from '~/services/modelTypes'
import {
  getStructureProducts,
  buildProductRequirementDescriptions,
  buildProductRequirementEntries,
  resizeProductSelections,
  areProductSelectionsFilled,
  applyProductSelection,
  collectNormalizedProductIds,
} from '~/shared/utils/pieceProductSelectionUtils'
import {
  type CustomFieldInput,
  normalizeCustomFieldInputs,
  requiredCustomFieldsFilled as _requiredCustomFieldsFilled,
  saveCustomFieldValues as _saveCustomFieldValues,
} from '~/shared/utils/customFieldFormUtils'

interface PieceCatalogType extends ModelType {
  structure: PieceModelStructure | null
  customFields?: Array<Record<string, any>>
}

const route = useRoute()
const router = useRouter()

const { pieceTypes, loadPieceTypes, loadingPieceTypes: loadingTypes } = usePieceTypes()
const { createPiece } = usePieces()
const toast = useToast()
const { upsertCustomFieldValue, updateCustomFieldValue } = useCustomFields()
const { uploadDocuments } = useDocuments()
const { canEdit } = usePermissions()

const initialTypeId = ref<string>(typeof route.query.typeId === 'string' ? route.query.typeId : '')
const selectedTypeId = ref<string>(initialTypeId.value)
const submitting = ref(false)
const creationForm = reactive({
  name: '' as string,
  description: '' as string,
  reference: '' as string,
  constructeurIds: [] as string[],
  prix: '' as string,
})
const productSelections = ref<(string | null)[]>([])

const lastSuggestedName = ref('')
const customFieldInputs = ref<CustomFieldInput[]>([])
const selectedDocuments = ref<File[]>([])
const uploadingDocuments = ref(false)

watch(
  () => route.query.typeId,
  (value) => {
    if (typeof value === 'string') {
      selectedTypeId.value = value
    }
  },
)

watch(selectedTypeId, (id) => {
  const current = typeof route.query.typeId === 'string' ? route.query.typeId : ''
  if ((id || '') === current) {
    return
  }
  const nextQuery = { ...route.query }
  if (id) {
    nextQuery.typeId = id
  } else {
    delete nextQuery.typeId
  }
  router.replace({ path: route.path, query: nextQuery }).catch(() => {})
})

const pieceTypeList = computed<PieceCatalogType[]>(() => (pieceTypes.value || []) as PieceCatalogType[])

const typeOptionLabel = (type?: PieceCatalogType) =>
  type?.name || 'Catégorie'

const typeOptionDescription = (type?: PieceCatalogType) =>
  type?.description ? String(type.description) : ''

const selectedType = computed(() => {
  if (!selectedTypeId.value) {
    return null
  }
  return pieceTypeList.value.find((type) => type.id === selectedTypeId.value) ?? null
})

const structureProducts = computed(() =>
  getStructureProducts(selectedType.value?.structure ?? null),
)

const requiresProductSelection = computed(() => structureProducts.value.length > 0)

const productRequirementDescriptions = computed(() =>
  buildProductRequirementDescriptions(structureProducts.value),
)

const ensureProductSelections = (count: number) => {
  productSelections.value = resizeProductSelections(productSelections.value, count)
}

const productRequirementEntries = computed(() =>
  buildProductRequirementEntries(structureProducts.value, 'piece-create-product-requirement'),
)

const productSelectionsFilled = computed(() =>
  areProductSelectionsFilled(
    requiresProductSelection.value,
    productRequirementEntries.value,
    productSelections.value,
  ),
)

const setProductSelection = (index: number, value: string | null) => {
  productSelections.value = applyProductSelection(productSelections.value, index, value)
}

watch(structureProducts, (products) => {
  ensureProductSelections(products.length)
})

watch(selectedType, (type) => {
  if (!type) {
    clearCreationForm()
    customFieldInputs.value = []
    return
  }
  if (!creationForm.name || creationForm.name === lastSuggestedName.value) {
    creationForm.name = type.name
  }
  lastSuggestedName.value = creationForm.name
  customFieldInputs.value = normalizeCustomFieldInputs(type.structure)
  productSelections.value = Array.from({ length: structureProducts.value.length }, () => null)
})

const requiredCustomFieldsFilled = computed(() =>
  _requiredCustomFieldsFilled(customFieldInputs.value),
)

const canSubmit = computed(() =>
  Boolean(
    canEdit.value &&
    selectedType.value &&
    creationForm.name &&
    requiredCustomFieldsFilled.value &&
    productSelectionsFilled.value &&
    !submitting.value,
  ),
)

const clearCreationForm = () => {
  creationForm.name = ''
  creationForm.description = ''
  creationForm.reference = ''
  creationForm.constructeurIds = []
  creationForm.prix = ''
  productSelections.value = []
  lastSuggestedName.value = ''
}

const submitCreation = async () => {
  if (!selectedType.value) {
    toast.showError('Sélectionnez une catégorie de pièce.')
    return
  }

  if (!productSelectionsFilled.value) {
    toast.showError('Sélectionnez un produit conforme au squelette.')
    return
  }

  const payload: Record<string, any> = {
    name: creationForm.name.trim(),
    typePieceId: selectedType.value.id,
  }

  const description = creationForm.description.trim()
  if (description) {
    payload.description = description
  }

  const reference = creationForm.reference.trim()
  if (reference) {
    payload.reference = reference
  }

  payload.constructeurIds = uniqueConstructeurIds(creationForm.constructeurIds)

  const normalizedProductIds = collectNormalizedProductIds(
    productRequirementEntries.value,
    productSelections.value,
  )
  if (normalizedProductIds.length) {
    payload.productIds = normalizedProductIds
    payload.productId = normalizedProductIds[0]
  }

  const rawPrice = typeof creationForm.prix === 'string'
    ? creationForm.prix.trim()
    : creationForm.prix === null || creationForm.prix === undefined
      ? ''
      : String(creationForm.prix).trim()

  if (rawPrice) {
    const parsed = Number(rawPrice)
    if (!Number.isNaN(parsed)) {
      payload.prix = String(parsed)
    }
  }

  submitting.value = true
  try {
    const result = await createPiece(payload)
    if (result.success && result.data) {
      const createdPiece = result.data as Record<string, any>
      await _saveCustomFieldValues(
        'piece',
        createdPiece.id,
        [
          createdPiece?.typePiece?.structure?.customFields,
        ],
        { customFieldInputs, upsertCustomFieldValue, updateCustomFieldValue, toast },
      )
      if (selectedDocuments.value.length && createdPiece.id) {
        uploadingDocuments.value = true
        const uploadResult = await uploadDocuments(
          {
            files: selectedDocuments.value,
            context: { pieceId: createdPiece.id },
          },
          { updateStore: false },
        )
        if (!uploadResult.success) {
          const message = uploadResult.error
            ? `Documents non ajoutés : ${uploadResult.error}`
            : 'Documents non ajoutés : une erreur est survenue.'
          toast.showError(message)
        }
        selectedDocuments.value = []
      }
      toast.showSuccess('Pièce créée avec succès')
      await router.replace(`/piece/${createdPiece.id}?edit=true`)
    } else if (result.error) {
      toast.showError(result.error)
    }
  } catch (error: any) {
    toast.showError(humanizeError(error?.message) || 'Impossible de créer la pièce')
  } finally {
    submitting.value = false
    uploadingDocuments.value = false
  }
}

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

</script>
