<template>
  <div :class="wrapperClass">
    <section v-if="!isRoot" class="rounded-lg border border-base-200 bg-base-100 p-4 space-y-3">
      <div class="space-y-1">
        <h4 class="text-sm font-semibold text-base-content">
          {{ requirementLabel }}
        </h4>
        <p class="text-xs text-base-content/70">
          {{ requirementDescription }}
        </p>
      </div>

      <div class="form-control">
        <label class="label">
          <span class="label-text text-xs">Sélectionner un composant</span>
        </label>
        <SearchSelect
          :model-value="assignment.selectedComponentId || ''"
          :options="componentOptions"
          :loading="componentsLoading || componentLoadingByPath[assignment.path]"
          size="sm"
          placeholder="Rechercher un composant..."
          :empty-text="componentOptions.length ? 'Aucun résultat' : 'Aucun composant disponible'"
          :option-label="componentOptionLabel"
          :option-description="componentOptionDescription"
          @search="fetchComponentOptions"
          @update:modelValue="(value) => { assignment.selectedComponentId = normalizeSelectionValue(value); }"
        />
      </div>
    </section>

    <section v-if="assignment.pieces.length" class="rounded-lg border border-dashed border-base-300 bg-base-200/40 p-4 space-y-4">
      <header class="space-y-1">
        <h4 class="text-sm font-semibold text-base-content">
          {{ isRoot ? 'Pièces requises par le squelette' : 'Pièces associées à ce sous-composant' }}
        </h4>
        <p class="text-xs text-base-content/70">
          Sélectionnez les pièces concrètes à associer pour chaque emplacement.
        </p>
      </header>

      <div
        v-for="pieceAssignment in assignment.pieces"
        :key="pieceAssignment.path"
        class="rounded-md border border-base-200 bg-base-100 p-3 space-y-2"
      >
        <div class="space-y-1">
          <p class="text-xs font-medium text-base-content">
            {{ describePieceRequirement(pieceAssignment) }}
          </p>
          <p v-if="!getPieceOptions(pieceAssignment).length" class="text-[11px] text-error">
            Aucune pièce disponible pour cette famille.
          </p>
        </div>

        <SearchSelect
          :model-value="pieceAssignment.selectedPieceId || ''"
          :options="getPieceOptions(pieceAssignment)"
          :loading="piecesLoading || pieceLoadingByPath[pieceAssignment.path]"
          size="xs"
          placeholder="Rechercher une pièce..."
          :empty-text="getPieceOptions(pieceAssignment).length ? 'Aucun résultat' : 'Aucune pièce disponible'"
          :option-label="pieceOptionLabel"
          :option-description="pieceOptionDescription"
          @search="(term) => fetchPieceOptions(pieceAssignment, term)"
          @update:modelValue="(value) => { pieceAssignment.selectedPieceId = normalizeSelectionValue(value); }"
        />
      </div>
    </section>

    <section v-if="assignment.products.length" class="rounded-lg border border-dashed border-base-300 bg-base-200/40 p-4 space-y-4">
      <header class="space-y-1">
        <h4 class="text-sm font-semibold text-base-content">
          {{ isRoot ? 'Produits requis par le squelette' : 'Produits associés à ce sous-composant' }}
        </h4>
        <p class="text-xs text-base-content/70">
          Sélectionnez les produits catalogue à lier sur chaque position définie.
        </p>
      </header>

      <div
        v-for="productAssignment in assignment.products"
        :key="productAssignment.path"
        class="rounded-md border border-base-200 bg-base-100 p-3 space-y-2"
      >
        <div class="space-y-1">
          <p class="text-xs font-medium text-base-content">
            {{ describeProductRequirement(productAssignment) }}
          </p>
          <p v-if="!getProductOptions(productAssignment).length" class="text-[11px] text-error">
            Aucun produit disponible pour cette catégorie.
          </p>
        </div>

        <SearchSelect
          :model-value="productAssignment.selectedProductId || ''"
          :options="getProductOptions(productAssignment)"
          :loading="productsLoading || productLoadingByPath[productAssignment.path]"
          size="xs"
          placeholder="Rechercher un produit..."
          :empty-text="getProductOptions(productAssignment).length ? 'Aucun résultat' : 'Aucun produit disponible'"
          :option-label="productOptionLabel"
          :option-description="productOptionDescription"
          @search="(term) => fetchProductOptions(productAssignment, term)"
          @update:modelValue="(value) => { productAssignment.selectedProductId = normalizeSelectionValue(value); }"
        />
      </div>
    </section>

    <section v-if="assignment.subcomponents.length" class="space-y-4">
      <header class="space-y-1">
        <h4 class="text-sm font-semibold text-base-content">
          {{ isRoot ? 'Sous-composants définis par le squelette' : 'Sous-composants imbriqués' }}
        </h4>
        <p class="text-xs text-base-content/70">
          Choisissez un composant existant pour chaque sous-niveau requis.
        </p>
      </header>

      <ComponentStructureAssignmentNode
        v-for="subAssignment in assignment.subcomponents"
        :key="subAssignment.path"
        :assignment="subAssignment"
        :pieces="pieces"
        :products="products"
        :components="components"
        :components-loading="componentsLoading"
        :pieces-loading="piecesLoading"
        :products-loading="productsLoading"
        :depth="depth + 1"
      />
    </section>
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import SearchSelect from '~/components/common/SearchSelect.vue';
import { useStructureAssignmentFetch } from '~/composables/useStructureAssignmentFetch';
import type {
  ComponentOption,
  PieceOption,
  ProductOption,
} from '~/composables/useStructureAssignmentFetch';

export type {
  StructureAssignmentNode,
  StructurePieceAssignment,
  StructureProductAssignment,
} from '~/composables/useStructureAssignmentFetch';

const props = withDefaults(
  defineProps<{
    assignment: import('~/composables/useStructureAssignmentFetch').StructureAssignmentNode;
    pieces: PieceOption[] | null;
    products: ProductOption[] | null;
    components: ComponentOption[] | null;
    depth?: number;
    componentsLoading?: boolean;
    piecesLoading?: boolean;
    productsLoading?: boolean;
    pieceTypeLabelMap?: Record<string, string>;
    productTypeLabelMap?: Record<string, string>;
    componentTypeLabelMap?: Record<string, string>;
  }>(),
  {
    depth: 0,
    pieces: () => [],
    products: () => [],
    components: () => [],
    componentsLoading: false,
    piecesLoading: false,
    productsLoading: false,
    pieceTypeLabelMap: () => ({}),
    productTypeLabelMap: () => ({}),
    componentTypeLabelMap: () => ({}),
  },
);

const depth = computed(() => props.depth ?? 0);
const isRoot = computed(() => depth.value === 0);

const wrapperClass = computed(() =>
  depth.value === 0 ? 'space-y-6' : 'space-y-6 border-l border-base-300 pl-4',
);

const {
  pieceLoadingByPath,
  productLoadingByPath,
  componentLoadingByPath,
  componentOptions,
  componentOptionLabel,
  componentOptionDescription,
  fetchComponentOptions,
  getPieceOptions,
  pieceOptionLabel,
  pieceOptionDescription,
  fetchPieceOptions,
  describePieceRequirement,
  getProductOptions,
  productOptionLabel,
  productOptionDescription,
  fetchProductOptions,
  describeProductRequirement,
} = useStructureAssignmentFetch({
  assignment: props.assignment,
  pieces: props.pieces,
  products: props.products,
  components: props.components,
  isRoot: () => isRoot.value,
  pieceTypeLabelMap: props.pieceTypeLabelMap ?? {},
  productTypeLabelMap: props.productTypeLabelMap ?? {},
  componentTypeLabelMap: props.componentTypeLabelMap ?? {},
});

const normalizeSelectionValue = (value: unknown) => {
  if (value === null || value === undefined || value === '') {
    return '';
  }
  if (typeof value === 'string') {
    return value;
  }
  if (typeof value === 'number') {
    return String(value);
  }
  return '';
};

const requirementLabel = computed(() => {
  const definition = props.assignment.definition || {};
  const alias = definition.alias || definition.typeComposantLabel;
  if (alias) {
    return alias;
  }
  if (definition.typeComposantId && props.componentTypeLabelMap[definition.typeComposantId]) {
    return props.componentTypeLabelMap[definition.typeComposantId];
  }
  if (definition.typeComposant?.name) {
    return definition.typeComposant.name;
  }
  if (definition.familyCode) {
    return `Famille ${definition.familyCode}`;
  }
  return 'Sous-composant';
});

const requirementDescription = computed(() => {
  const definition = props.assignment.definition || {};
  const family =
    definition.typeComposantLabel
    || (definition.typeComposantId ? props.componentTypeLabelMap[definition.typeComposantId] : null)
    || definition.typeComposant?.name
    || definition.familyCode;
  if (family) {
    return `Doit appartenir à la famille "${family}".`;
  }
  return 'Sélectionnez un composant enfant conforme à cette position.';
});
</script>
