<template>
  <form class="reception-form" @submit.prevent="submitForm">
    <!-- Progress Stepper -->
    <div class="form-stepper">
      <div class="stepper-line"></div>
      <div
        class="step"
        :class="{ active: currentStep >= 1, done: currentStep > 1 }"
      >
        <div class="step-dot"><i class="fas fa-file-alt"></i></div>
        <span class="step-label">Informations</span>
      </div>
      <div
        class="step"
        :class="{ active: currentStep >= 2, done: currentStep > 2 }"
      >
        <div class="step-dot"><i class="fas fa-boxes"></i></div>
        <span class="step-label">Articles</span>
      </div>
      <div class="step" :class="{ active: currentStep >= 3 }">
        <div class="step-dot"><i class="fas fa-check"></i></div>
        <span class="step-label">Validation</span>
      </div>
    </div>

    <!-- Section 1: Informations générales -->
    <div class="form-card" :class="{ collapsed: currentStep > 1 }">
      <div class="card-header" @click="currentStep = 1">
        <div class="card-header-left">
          <div class="card-icon"><i class="fas fa-file-invoice"></i></div>
          <div>
            <h3 class="card-title">Informations générales</h3>
            <p class="card-subtitle">
              Commande, entrepôt et détails de réception
            </p>
          </div>
        </div>
        <div class="card-header-right">
          <SoftBadge
            v-if="currentStep > 1"
            color="success"
            variant="gradient"
            size="sm"
            class="badge-complete-soft"
          >
            <i class="fas fa-check-circle"></i> Complété
          </SoftBadge>
          <i
            class="fas fa-chevron-down card-toggle"
            :class="{ rotated: currentStep === 1 }"
          ></i>
        </div>
      </div>

      <transition name="slide-down">
        <div v-show="currentStep === 1" class="card-body">
          <!-- Row 1: Commande + Entrepôt -->
          <div class="field-grid two-col">
            <div
              class="field-group"
              :class="{ 'has-error': errors.purchase_order_id }"
            >
              <label class="field-label">
                <i class="fas fa-shopping-cart label-icon"></i>
                Commande Fournisseur
                <span class="required-dot"></span>
              </label>
              <div class="select-wrapper">
                <select
                  v-model="formData.purchase_order_id"
                  class="field-select"
                >
                  <option value="">— Sélectionner une commande —</option>
                  <option
                    v-for="po in purchaseOrders"
                    :key="po.id"
                    :value="po.id"
                  >
                    {{ po.po_number }} ·
                    {{
                      po.fournisseur?.nom || "Fournisseur " + po.fournisseur_id
                    }}
                  </option>
                </select>
                <i class="fas fa-chevron-down select-chevron"></i>
              </div>
              <transition name="shake">
                <span v-if="errors.purchase_order_id" class="field-error">
                  <i class="fas fa-exclamation-circle"></i>
                  {{ errors.purchase_order_id }}
                </span>
              </transition>
            </div>

            <div
              class="field-group position-relative warehouse-search-container"
              :class="{ 'has-error': errors.warehouse_id }"
            >
              <label class="field-label">
                <i class="fas fa-warehouse label-icon"></i>
                Entrepôt de Destination
                <span class="required-dot"></span>
              </label>
              <div class="search-wrapper">
                <i class="fas fa-search search-icon"></i>
                <input
                  v-model="warehouseSearchQuery"
                  type="text"
                  class="field-input search-input"
                  placeholder="Rechercher un entrepôt…"
                  @input="handleWarehouseSearch"
                  @focus="showWarehouseResults = true"
                />
                <transition name="fade">
                  <button
                    v-if="warehouseSearchQuery && formData.warehouse_id"
                    type="button"
                    class="clear-btn"
                    @click="clearWarehouse"
                  >
                    <i class="fas fa-times"></i>
                  </button>
                </transition>
              </div>

              <transition name="dropdown">
                <div
                  v-if="
                    showWarehouseResults &&
                    (warehouseSearchResults.length > 0 || isSearchingWarehouses)
                  "
                  class="results-dropdown"
                >
                  <div v-if="isSearchingWarehouses" class="dropdown-loading">
                    <div class="loading-dots">
                      <span></span><span></span><span></span>
                    </div>
                    <span>Recherche…</span>
                  </div>
                  <template v-else>
                    <button
                      v-for="warehouse in warehouseSearchResults"
                      :key="warehouse.id"
                      type="button"
                      class="result-item"
                      @click="selectWarehouse(warehouse)"
                    >
                      <div class="result-icon">
                        <i class="fas fa-warehouse"></i>
                      </div>
                      <div class="result-info">
                        <span class="result-name">{{ warehouse.name }}</span>
                        <span class="result-meta"
                          >{{ warehouse.city || "Ville non spécifiée" }} ·
                          {{ warehouse.country_code || "" }}</span
                        >
                      </div>
                    </button>
                  </template>
                </div>
              </transition>

              <transition name="shake">
                <span v-if="errors.warehouse_id" class="field-error">
                  <i class="fas fa-exclamation-circle"></i>
                  {{ errors.warehouse_id }}
                </span>
              </transition>
            </div>
          </div>

          <!-- Row 2: Numéro, Date, Statut -->
          <div class="field-grid three-col">
            <div class="field-group">
              <label class="field-label">
                <i class="fas fa-hashtag label-icon"></i>
                Numéro de Réception
              </label>
              <input
                v-model="formData.receipt_number"
                type="text"
                class="field-input"
                placeholder="Auto-généré si vide"
              />
              <span class="field-hint"
                >Laissez vide pour génération automatique</span
              >
            </div>

            <div class="field-group">
              <label class="field-label">
                <i class="fas fa-calendar-day label-icon"></i>
                Date de Réception
                <span class="required-dot"></span>
              </label>
              <input
                v-model="formData.receipt_date"
                type="date"
                class="field-input"
                required
              />
            </div>

            <div class="field-group">
              <label class="field-label">
                <i class="fas fa-tag label-icon"></i>
                Statut
              </label>
              <div class="status-toggle">
                <SoftButton
                  type="button"
                  color="warning"
                size="sm"
                  :variant="
                    formData.status === 'draft' ? 'gradient' : 'outline'
                  "
                  :active="formData.status === 'draft'"
                  @click="formData.status = 'draft'"
                >
                  Brouillon
                </SoftButton>
                <SoftButton
                  type="button"
                  color="success"
                  size="sm"
                  :variant="
                    formData.status === 'posted' ? 'gradient' : 'outline'
                  "
                  :active="formData.status === 'posted'"
                  @click="formData.status = 'posted'"
                >
                  <i class="fas fa-check-double"></i> Validée
                </SoftButton>
              </div>
            </div>
          </div>

          <!-- Notes -->
          <div class="field-group">
            <label class="field-label">
              <i class="fas fa-sticky-note label-icon"></i>
              Notes internes
            </label>
            <textarea
              v-model="formData.notes"
              class="field-textarea"
              placeholder="Informations complémentaires sur cette réception…"
              rows="3"
            ></textarea>
          </div>

          <div class="card-actions">
            <SoftButton
              type="button"
              color="primary"
              variant="gradient"
              class="soft-action-btn"
              @click="goToStep2"
            >
              Continuer vers les articles
              <i class="fas fa-arrow-right"></i>
            </SoftButton>
          </div>
        </div>
      </transition>
    </div>

    <!-- Section 2: Lignes de réception -->
    <div class="form-card" :class="{ collapsed: currentStep < 2 }">
      <div class="card-header" @click="currentStep >= 2 && (currentStep = 2)">
        <div class="card-header-left">
          <div class="card-icon card-icon--blue">
            <i class="fas fa-boxes"></i>
          </div>
          <div>
            <h3 class="card-title">Lignes de Réception</h3>
            <p class="card-subtitle">
              {{ formData.lines.length }} article{{
                formData.lines.length > 1 ? "s" : ""
              }}
              ajouté{{ formData.lines.length > 1 ? "s" : "" }}
            </p>
          </div>
        </div>
        <div class="card-header-right">
          <SoftBadge
            v-if="currentStep > 2"
            color="success"
            variant="gradient"
            size="sm"
            class="badge-complete-soft"
          >
            <i class="fas fa-check-circle"></i> Complété
          </SoftBadge>
          <i
            v-if="currentStep >= 2"
            class="fas fa-chevron-down card-toggle"
            :class="{ rotated: currentStep === 2 }"
          ></i>
        </div>
      </div>

      <transition name="slide-down">
        <div v-show="currentStep === 2" class="card-body">
          <!-- Lines Table Header -->
          <div class="lines-header">
            <span class="col-product">Produit</span>
            <span class="col-pkg">Conditionnement</span>
            <span class="col-colis">Colis Reçus</span>
            <span class="col-units">Unités Reçues</span>
            <span class="col-price">Prix Unitaire</span>
            <span class="col-actions"></span>
          </div>

          <transition-group name="line-list" tag="div" class="lines-list">
            <div
              v-for="(line, index) in formData.lines"
              :key="index"
              class="line-row"
            >
              <!-- Product Search -->
              <div
                class="cell cell-product position-relative product-search-container"
              >
                <div class="search-wrapper">
                  <i class="fas fa-cube search-icon-sm"></i>
                  <input
                    v-model="line.searchQuery"
                    type="text"
                    class="field-input field-input--sm"
                    placeholder="Rechercher un produit…"
                    @input="handleProductSearch(index)"
                    @focus="
                      activeLineIndex = index;
                      showProductResults = true;
                    "
                  />
                </div>
                <transition name="dropdown">
                  <div
                    v-show="showProductResults && activeLineIndex === index"
                    class="results-dropdown results-dropdown--sm"
                  >
                    <div v-if="isSearchingProducts" class="dropdown-loading">
                      <div class="loading-dots">
                        <span></span><span></span><span></span>
                      </div>
                    </div>
                    <div
                      v-else-if="productSearchResults.length === 0"
                      class="dropdown-empty"
                    >
                      <i class="fas fa-search-minus"></i> Aucun produit trouvé
                    </div>
                    <template v-else>
                      <button
                        v-for="product in productSearchResults"
                        :key="product.id"
                        type="button"
                        class="result-item result-item--sm"
                        @mousedown.prevent="selectProduct(index, product)"
                      >
                        <div class="result-icon result-icon--sm">
                          <i class="fas fa-cube"></i>
                        </div>
                        <div class="result-info">
                          <span class="result-name">{{ product.nom }}</span>
                          <span class="result-meta"
                            >Réf: {{ product.reference }} · Stock:
                            {{ product.stock_actuel }} {{ product.unite }}</span
                          >
                        </div>
                      </button>
                    </template>
                  </div>
                </transition>
              </div>

              <!-- Packaging -->
              <div class="cell cell-pkg">
                <div class="select-wrapper select-wrapper--sm">
                  <select
                    v-model="line.packaging_id"
                    class="field-select field-select--sm"
                  >
                    <option :value="null">Unité</option>
                    <option
                      v-for="pkg in getPackagings(line.product_id)"
                      :key="pkg.id"
                      :value="pkg.id"
                    >
                      {{ pkg.name }} ({{ pkg.qty_base }})
                    </option>
                  </select>
                  <i
                    class="fas fa-chevron-down select-chevron select-chevron--sm"
                  ></i>
                </div>
              </div>

              <!-- Packages qty -->
              <div class="cell cell-number">
                <input
                  v-model.number="line.packages_qty_received"
                  type="number"
                  class="field-input field-input--sm field-input--number"
                  placeholder="0"
                  min="0"
                  step="0.001"
                />
              </div>

              <!-- Units qty -->
              <div class="cell cell-number">
                <input
                  v-model.number="line.units_qty_received"
                  type="number"
                  class="field-input field-input--sm field-input--number"
                  placeholder="0"
                  min="0"
                  step="0.001"
                />
              </div>

              <!-- Unit Price -->
              <div class="cell cell-number">
                <div class="price-input-wrapper">
                  <span class="currency-symbol">€</span>
                  <input
                    v-model.number="line.unit_price"
                    type="number"
                    class="field-input field-input--sm field-input--price"
                    placeholder="0.00"
                    min="0"
                    step="0.01"
                  />
                </div>
              </div>

              <!-- Actions -->
              <div class="cell cell-actions">
                <SoftButton
                  type="button"
                  class="line-delete-btn"
                  color="danger"
                  variant="outline"
                  size="sm"
                  :disabled="formData.lines.length === 1"
                  title="Supprimer"
                  @click="removeLine(index)"
                >
                  <i class="fas fa-trash"></i>
                </SoftButton>
              </div>
            </div>
          </transition-group>

          <!-- Add Line + Totals -->
          <div class="lines-footer">
            <SoftButton
              type="button"
              color="primary"
              variant="outline"
              size="sm"
              class="btn-add-line-soft"
              @click="addLine"
            >
              <i class="fas fa-plus-circle"></i>
              Ajouter une ligne
            </SoftButton>
            <div class="lines-summary">
              <div class="summary-item">
                <span class="summary-label">Total lignes</span>
                <span class="summary-value">{{
                  formData.lines.filter((l) => l.product_id).length
                }}</span>
              </div>
              <div class="summary-item">
                <span class="summary-label">Total unités</span>
                <span class="summary-value">{{ totalUnits }}</span>
              </div>
              <div class="summary-item summary-item--total">
                <span class="summary-label">Montant total</span>
                <span class="summary-value">{{ totalAmount }} €</span>
              </div>
            </div>
          </div>

          <div class="card-actions card-actions--spread">
            <SoftButton
              type="button"
              color="secondary"
              variant="outline"
              class="soft-action-btn"
              @click="currentStep = 1"
            >
              <i class="fas fa-arrow-left"></i> Retour
            </SoftButton>
            <SoftButton
              type="button"
              color="primary"
              variant="gradient"
              class="soft-action-btn"
              @click="goToStep3"
            >
              Vérifier et enregistrer
              <i class="fas fa-arrow-right"></i>
            </SoftButton>
          </div>
        </div>
      </transition>
    </div>

    <!-- Section 3: Récapitulatif & Validation -->
    <div class="form-card" :class="{ collapsed: currentStep < 3 }">
      <div class="card-header">
        <div class="card-header-left">
          <div class="card-icon card-icon--green">
            <i class="fas fa-clipboard-check"></i>
          </div>
          <div>
            <h3 class="card-title">Récapitulatif</h3>
            <p class="card-subtitle">Vérifiez avant d'enregistrer</p>
          </div>
        </div>
      </div>

      <transition name="slide-down">
        <div v-show="currentStep === 3" class="card-body">
          <div class="recap-grid">
            <div class="recap-item">
              <span class="recap-label"
                ><i class="fas fa-shopping-cart"></i> Commande</span
              >
              <span class="recap-value">{{ selectedPOLabel }}</span>
            </div>
            <div class="recap-item">
              <span class="recap-label"
                ><i class="fas fa-warehouse"></i> Entrepôt</span
              >
              <span class="recap-value">{{ warehouseSearchQuery || "—" }}</span>
            </div>
            <div class="recap-item">
              <span class="recap-label"
                ><i class="fas fa-calendar-day"></i> Date</span
              >
              <span class="recap-value">{{ formData.receipt_date }}</span>
            </div>
            <div class="recap-item">
              <span class="recap-label"><i class="fas fa-tag"></i> Statut</span>
              <span class="recap-value">
                <SoftBadge
                  :color="formData.status === 'draft' ? 'warning' : 'success'"
                  variant="gradient"
                  size="sm"
                >
                  {{ formData.status === "draft" ? "Brouillon" : "Validée" }}
                </SoftBadge>
              </span>
            </div>
            <div class="recap-item">
              <span class="recap-label"
                ><i class="fas fa-boxes"></i> Articles</span
              >
              <span class="recap-value"
                >{{
                  formData.lines.filter((l) => l.product_id).length
                }}
                produit(s)</span
              >
            </div>
            <div class="recap-item">
              <span class="recap-label"
                ><i class="fas fa-coins"></i> Montant total</span
              >
              <span class="recap-value recap-total">{{ totalAmount }} €</span>
            </div>
          </div>

          <div class="card-actions card-actions--spread">
            <SoftButton
              type="button"
              color="secondary"
              variant="outline"
              class="soft-action-btn"
              @click="currentStep = 2"
            >
              <i class="fas fa-arrow-left"></i> Modifier
            </SoftButton>
            <div class="action-group">
              <SoftButton
                type="button"
                color="danger"
                variant="outline"
                class="soft-action-btn"
                @click="cancelForm"
              >
                <i class="fas fa-times"></i> Annuler
              </SoftButton>
              <SoftButton
                type="submit"
                color="primary"
                variant="gradient"
                class="soft-action-btn"
                :disabled="props.loading"
              >
                <span v-if="props.loading" class="btn-spinner"></span>
                <i v-else class="fas fa-check"></i>
                {{
                  props.loading ? "Enregistrement…" : "Enregistrer la réception"
                }}
              </SoftButton>
            </div>
          </div>
        </div>
      </transition>
    </div>
  </form>
</template>

<script setup>
import {
  ref,
  watch,
  computed,
  defineEmits,
  defineProps,
  onMounted,
  onUnmounted,
} from "vue";
import WarehouseService from "@/services/warehouse";
import ProductService from "@/services/product";
import { PurchaseOrderService } from "@/services/purchaseOrder";
import SoftButton from "@/components/SoftButton.vue";
import SoftBadge from "@/components/SoftBadge.vue";

const props = defineProps({
  loading: { type: Boolean, default: false },
  purchaseOrders: { type: Array, default: () => [] },
});

const emit = defineEmits(["submit", "cancel"]);

// Step management
const currentStep = ref(1);

// Warehouse Search
const warehouseSearchQuery = ref("");
const warehouseSearchResults = ref([]);
const isSearchingWarehouses = ref(false);
const showWarehouseResults = ref(false);
let searchTimeout = null;

const handleWarehouseSearch = () => {
  if (warehouseSearchQuery.value.length < 2) {
    warehouseSearchResults.value = [];
    if (searchTimeout) clearTimeout(searchTimeout);
    isSearchingWarehouses.value = false;
    return;
  }
  if (searchTimeout) clearTimeout(searchTimeout);
  searchTimeout = setTimeout(async () => {
    isSearchingWarehouses.value = true;
    showWarehouseResults.value = true;
    try {
      const results = await WarehouseService.searchWarehouses(
        warehouseSearchQuery.value
      );
      warehouseSearchResults.value = results.filter((w) => w && w.id);
    } catch (e) {
      console.error(e);
    } finally {
      isSearchingWarehouses.value = false;
    }
  }, 300);
};

const selectWarehouse = (warehouse) => {
  if (!warehouse?.id) return;
  if (searchTimeout) clearTimeout(searchTimeout);
  formData.value.warehouse_id = warehouse.id;
  warehouseSearchQuery.value = warehouse.name;
  showWarehouseResults.value = false;
};

const clearWarehouse = () => {
  formData.value.warehouse_id = "";
  warehouseSearchQuery.value = "";
  warehouseSearchResults.value = [];
};

// Product Search
const productSearchResults = ref([]);
const isSearchingProducts = ref(false);
const showProductResults = ref(false);
const activeLineIndex = ref(null);
const productPackagings = ref({});
let productSearchTimeout = null;

const handleProductSearch = (index) => {
  activeLineIndex.value = index;
  const query = formData.value.lines[index].searchQuery;
  if (query.length < 2) {
    productSearchResults.value = [];
    if (productSearchTimeout) clearTimeout(productSearchTimeout);
    return;
  }
  if (productSearchTimeout) clearTimeout(productSearchTimeout);
  productSearchTimeout = setTimeout(async () => {
    isSearchingProducts.value = true;
    showProductResults.value = true;
    try {
      const response = await ProductService.searchProducts(query);
      let results = [];
      if (response?.data) {
        results = Array.isArray(response.data)
          ? response.data
          : response.data.data || [];
      }
      productSearchResults.value = results.filter((p) => p && p.id);
    } catch (e) {
      console.error(e);
    } finally {
      isSearchingProducts.value = false;
    }
  }, 300);
};

const selectProduct = (index, product) => {
  if (!product?.id) return;
  if (productSearchTimeout) clearTimeout(productSearchTimeout);
  const line = formData.value.lines[index];
  if (!line) return;
  line.product_id = product.id;
  line.searchQuery = product.nom;
  loadProductPackagings(product.id);
  showProductResults.value = false;
  activeLineIndex.value = null;
};

const loadProductPackagings = async (productId) => {
  try {
    const response = await ProductService.getProduct(productId);
    if (response?.data) {
      productPackagings.value[productId] = response.data.conditionnement
        ? [
            {
              id: 1,
              name: response.data.conditionnement_nom || "Conditionnement",
              qty_base: response.data.conditionnement_quantite || 1,
            },
          ]
        : [];
    }
  } catch (e) {
    console.error(e);
  }
};

const getPackagings = (productId) => productPackagings.value[productId] || [];

// Click outside
const handleClickOutside = (event) => {
  if (
    !document
      .querySelector(".warehouse-search-container")
      ?.contains(event.target)
  ) {
    showWarehouseResults.value = false;
  }
  let insideProduct = false;
  document.querySelectorAll(".product-search-container").forEach((c) => {
    if (c.contains(event.target)) insideProduct = true;
  });
  if (!insideProduct) showProductResults.value = false;
};

onMounted(() => document.addEventListener("click", handleClickOutside));
onUnmounted(() => document.removeEventListener("click", handleClickOutside));

// Form Data
const formData = ref({
  purchase_order_id: "",
  warehouse_id: "",
  receipt_number: "",
  receipt_date: new Date().toISOString().split("T")[0],
  status: "draft",
  notes: "",
  lines: [
    {
      product_id: "",
      searchQuery: "",
      packaging_id: null,
      packages_qty_received: null,
      units_qty_received: null,
      unit_price: null,
    },
  ],
});

const errors = ref({});

// Computed
const selectedPOLabel = computed(() => {
  const po = props.purchaseOrders.find(
    (p) => p.id == formData.value.purchase_order_id
  );
  return po
    ? `${po.po_number} · ${
        po.fournisseur?.nom || "Fournisseur " + po.fournisseur_id
      }`
    : "—";
});

const totalUnits = computed(() =>
  formData.value.lines.reduce(
    (s, l) => s + (Number(l.units_qty_received) || 0),
    0
  )
);

const totalAmount = computed(() =>
  formData.value.lines
    .reduce(
      (s, l) =>
        s + (Number(l.units_qty_received) || 0) * (Number(l.unit_price) || 0),
      0
    )
    .toFixed(2)
);

// Hydrate from PO
const hydrateLinesFromPurchaseOrder = async (purchaseOrderId) => {
  if (!purchaseOrderId) return;
  try {
    const response = await PurchaseOrderService.getPurchaseOrder(
      parseInt(purchaseOrderId)
    );
    const order = response?.data;
    const orderLines = Array.isArray(order?.lines)
      ? order.lines
      : Array.isArray(order?.lines?.data)
      ? order.lines.data
      : [];
    if (!orderLines.length) return;
    formData.value.lines = orderLines.map((line) => ({
      product_id: line.product_id || "",
      searchQuery: line.product?.nom || line.description || "",
      packaging_id: null,
      packages_qty_received: null,
      units_qty_received: Number(line.quantity || 0) || null,
      unit_price: Number(line.unit_price || 0) || null,
    }));
  } catch (e) {
    console.error(e);
  }
};

watch(
  () => formData.value.purchase_order_id,
  async (newId) => {
    if (!newId) {
      formData.value.lines = [
        {
          product_id: "",
          searchQuery: "",
          packaging_id: null,
          packages_qty_received: null,
          units_qty_received: null,
          unit_price: null,
        },
      ];
      return;
    }
    await hydrateLinesFromPurchaseOrder(newId);
  }
);

// Line management
const addLine = () => {
  formData.value.lines.push({
    product_id: "",
    searchQuery: "",
    packaging_id: null,
    packages_qty_received: null,
    units_qty_received: null,
    unit_price: null,
  });
};

const removeLine = (index) => {
  if (formData.value.lines.length > 1) formData.value.lines.splice(index, 1);
};

// Navigation
const goToStep2 = () => {
  errors.value = {};
  if (!formData.value.purchase_order_id)
    errors.value.purchase_order_id = "La commande fournisseur est requise.";
  if (!formData.value.warehouse_id)
    errors.value.warehouse_id = "L'entrepôt est requis.";
  if (!Object.keys(errors.value).length) currentStep.value = 2;
};

const goToStep3 = () => {
  currentStep.value = 3;
};

const cancelForm = () => emit("cancel");

const submitForm = () => {
  errors.value = {};
  if (!formData.value.purchase_order_id)
    errors.value.purchase_order_id = "La commande fournisseur est requise.";
  if (!formData.value.warehouse_id)
    errors.value.warehouse_id = "L'entrepôt est requis.";
  if (Object.keys(errors.value).length) {
    currentStep.value = 1;
    return;
  }

  emit("submit", {
    purchase_order_id: parseInt(formData.value.purchase_order_id),
    warehouse_id: parseInt(formData.value.warehouse_id),
    receipt_number: formData.value.receipt_number || undefined,
    receipt_date: formData.value.receipt_date,
    status: formData.value.status,
    notes: formData.value.notes || undefined,
    lines: formData.value.lines
      .map((line) => ({
        product_id: parseInt(line.product_id),
        packaging_id: line.packaging_id ? parseInt(line.packaging_id) : null,
        packages_qty_received: line.packages_qty_received,
        units_qty_received: line.units_qty_received,
        unit_price: line.unit_price,
      }))
      .filter((line) => line.product_id),
  });
};
</script>

<style scoped>
/* ─────────────────────────────────────────────
   FONTS & TOKENS
───────────────────────────────────────────── */
@import url("https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700&family=DM+Mono:wght@400;500&display=swap");

* {
  box-sizing: border-box;
}

.reception-form {
  font-family: "DM Sans", sans-serif;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 960px;
  margin: 0 auto;
  padding: 0.5rem;

  --clr-primary: #5e72e4;
  --clr-primary-light: #eef1ff;
  --clr-primary-dark: #4b61da;
  --clr-success: #12b886;
  --clr-success-light: #e6f9f4;
  --clr-danger: #f03e3e;
  --clr-danger-light: #fff5f5;
  --clr-warning: #f59f00;
  --clr-border: #e8ecf0;
  --clr-bg: #f7f8fc;
  --clr-surface: #ffffff;
  --clr-text: #212529;
  --clr-text-muted: #868e96;
  --clr-text-subtle: #adb5bd;
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.12);
  --transition: 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ─────────────────────────────────────────────
   STEPPER
───────────────────────────────────────────── */
.form-stepper {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  padding: 1.5rem 2rem 0.5rem;
  position: relative;
}

.stepper-line {
  position: absolute;
  top: calc(1.5rem + 18px);
  left: calc(50% - 120px);
  width: 240px;
  height: 2px;
  background: var(--clr-border);
  z-index: 0;
}

.step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  flex: 1;
  position: relative;
  z-index: 1;
}

.step-dot {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--clr-surface);
  border: 2px solid var(--clr-border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--clr-text-subtle);
  font-size: 0.8rem;
  transition: all var(--transition);
}

.step.active .step-dot {
  background: var(--clr-primary);
  border-color: var(--clr-primary);
  color: #fff;
  box-shadow: 0 0 0 4px var(--clr-primary-light);
}

.step.done .step-dot {
  background: var(--clr-success);
  border-color: var(--clr-success);
  color: #fff;
}

.step-label {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--clr-text-subtle);
  transition: color var(--transition);
}

.step.active .step-label {
  color: var(--clr-primary);
}
.step.done .step-label {
  color: var(--clr-success);
}

/* ─────────────────────────────────────────────
   CARDS
───────────────────────────────────────────── */
.form-card {
  background: var(--clr-surface);
  border: 1.5px solid var(--clr-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: box-shadow var(--transition), border-color var(--transition);
}

.form-card:not(.collapsed) {
  box-shadow: var(--shadow-md);
  border-color: #d0d8ff;
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 1.5rem;
  cursor: pointer;
  user-select: none;
  transition: background var(--transition);
}

.card-header:hover {
  background: #fafbff;
}

.card-header-left {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.card-icon {
  width: 44px;
  height: 44px;
  border-radius: var(--radius-md);
  background: var(--clr-primary-light);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--clr-primary);
  font-size: 1rem;
  flex-shrink: 0;
}

.card-icon--blue {
  background: #e3f2fd;
  color: #1976d2;
}
.card-icon--green {
  background: var(--clr-success-light);
  color: var(--clr-success);
}

.card-title {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--clr-text);
}

.card-subtitle {
  margin: 2px 0 0;
  font-size: 0.78rem;
  color: var(--clr-text-muted);
}

.card-header-right {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.badge-complete {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--clr-success);
  background: var(--clr-success-light);
  border-radius: 99px;
  padding: 0.25rem 0.6rem;
  display: flex;
  align-items: center;
  gap: 4px;
}

.badge-complete-soft {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.card-toggle {
  color: var(--clr-text-muted);
  transition: transform var(--transition);
}

.card-toggle.rotated {
  transform: rotate(180deg);
}

.card-body {
  padding: 1.25rem 1.5rem 1.5rem;
  border-top: 1.5px solid var(--clr-border);
  background: #fafbff;
}

/* ─────────────────────────────────────────────
   FIELDS
───────────────────────────────────────────── */
.field-grid {
  display: grid;
  gap: 1.25rem;
  margin-bottom: 1.25rem;
}

.two-col {
  grid-template-columns: 1fr 1fr;
}
.three-col {
  grid-template-columns: 1fr 1fr 1fr;
}

@media (max-width: 640px) {
  .two-col,
  .three-col {
    grid-template-columns: 1fr;
  }
}

.field-group {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.field-group.has-error .field-input,
.field-group.has-error .field-select {
  border-color: var(--clr-danger) !important;
}

.field-label {
  font-size: 0.78rem;
  font-weight: 600;
  color: #4a5568;
  letter-spacing: 0.02em;
  display: flex;
  align-items: center;
  gap: 5px;
}

.label-icon {
  color: var(--clr-primary);
  opacity: 0.7;
  font-size: 0.7rem;
}

.required-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--clr-danger);
  margin-left: 2px;
  flex-shrink: 0;
}

.field-input,
.field-select {
  height: 40px;
  padding: 0 12px;
  border: 1.5px solid var(--clr-border);
  border-radius: var(--radius-md);
  background: var(--clr-surface);
  font-family: "DM Sans", sans-serif;
  font-size: 0.875rem;
  color: var(--clr-text);
  transition: border-color var(--transition), box-shadow var(--transition);
  width: 100%;
  outline: none;
}

.field-input:focus,
.field-select:focus {
  border-color: var(--clr-primary);
  box-shadow: 0 0 0 3px rgba(59, 91, 219, 0.12);
}

.field-input::placeholder {
  color: var(--clr-text-subtle);
}

.field-input--sm {
  height: 36px;
  font-size: 0.8rem;
  padding: 0 10px;
}
.field-input--number {
  text-align: right;
  font-family: "DM Mono", monospace;
}
.field-input--price {
  padding-left: 28px;
  text-align: right;
  font-family: "DM Mono", monospace;
}

.field-select {
  appearance: none;
  cursor: pointer;
}

.field-textarea {
  padding: 10px 12px;
  border: 1.5px solid var(--clr-border);
  border-radius: var(--radius-md);
  background: var(--clr-surface);
  font-family: "DM Sans", sans-serif;
  font-size: 0.875rem;
  color: var(--clr-text);
  resize: vertical;
  width: 100%;
  outline: none;
  transition: border-color var(--transition), box-shadow var(--transition);
  line-height: 1.5;
}

.field-textarea:focus {
  border-color: var(--clr-primary);
  box-shadow: 0 0 0 3px rgba(59, 91, 219, 0.12);
}

.field-textarea::placeholder {
  color: var(--clr-text-subtle);
}

.field-hint {
  font-size: 0.72rem;
  color: var(--clr-text-muted);
}

.field-error {
  font-size: 0.75rem;
  color: var(--clr-danger);
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 4px;
}

/* ─────────────────────────────────────────────
   SELECT WRAPPER
───────────────────────────────────────────── */
.select-wrapper {
  position: relative;
}
.select-chevron {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--clr-text-muted);
  pointer-events: none;
  font-size: 0.65rem;
}
.select-wrapper--sm .field-select--sm {
  height: 36px;
  font-size: 0.8rem;
  padding: 0 28px 0 8px;
}
.select-chevron--sm {
  font-size: 0.6rem;
  right: 8px;
}

/* ─────────────────────────────────────────────
   SEARCH WRAPPER
───────────────────────────────────────────── */
.search-wrapper {
  position: relative;
}

.search-icon {
  position: absolute;
  left: 11px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--clr-text-subtle);
  pointer-events: none;
  font-size: 0.75rem;
}

.search-wrapper .field-input {
  padding-left: 34px;
}

.search-icon-sm {
  font-size: 0.65rem;
  left: 9px;
}
.search-wrapper .field-input--sm {
  padding-left: 28px;
}

.clear-btn {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  color: var(--clr-text-muted);
  font-size: 0.7rem;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background var(--transition), color var(--transition);
}
.clear-btn:hover {
  background: #eee;
  color: var(--clr-text);
}

/* ─────────────────────────────────────────────
   RESULTS DROPDOWN
───────────────────────────────────────────── */
.results-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--clr-surface);
  border: 1.5px solid var(--clr-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  max-height: 280px;
  overflow-y: auto;
  z-index: 1000;
  scrollbar-width: thin;
}

.results-dropdown--sm {
  max-height: 220px;
}

.result-item {
  width: 100%;
  padding: 10px 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  background: none;
  border: none;
  border-bottom: 1px solid #f1f3f5;
  cursor: pointer;
  text-align: left;
  transition: background var(--transition);
}

.result-item:last-child {
  border-bottom: none;
}
.result-item:hover {
  background: var(--clr-primary-light);
}

.result-item--sm {
  padding: 8px 10px;
}

.result-icon {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  background: var(--clr-primary-light);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--clr-primary);
  font-size: 0.75rem;
  flex-shrink: 0;
}

.result-icon--sm {
  width: 26px;
  height: 26px;
  font-size: 0.65rem;
}

.result-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow: hidden;
}

.result-name {
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--clr-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.result-meta {
  font-size: 0.72rem;
  color: var(--clr-text-muted);
}

.dropdown-loading {
  padding: 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  color: var(--clr-text-muted);
  font-size: 0.8rem;
}

.dropdown-empty {
  padding: 1rem;
  text-align: center;
  color: var(--clr-text-muted);
  font-size: 0.8rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.loading-dots {
  display: flex;
  gap: 4px;
}
.loading-dots span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--clr-primary);
  animation: bounce 1s infinite;
}
.loading-dots span:nth-child(2) {
  animation-delay: 0.15s;
}
.loading-dots span:nth-child(3) {
  animation-delay: 0.3s;
}
@keyframes bounce {
  0%,
  80%,
  100% {
    transform: scale(0.6);
    opacity: 0.4;
  }
  40% {
    transform: scale(1);
    opacity: 1;
  }
}

/* ─────────────────────────────────────────────
   STATUS TOGGLE
───────────────────────────────────────────── */
.status-toggle {
  display: flex;
  gap: 6px;
  padding: 4px;
  background: var(--clr-bg);
  border: 1.5px solid var(--clr-border);
  border-radius: var(--radius-md);
}

.status-btn {
  flex: 1;
  height: 32px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font-family: "DM Sans", sans-serif;
  font-size: 0.78rem;
  font-weight: 500;
  cursor: pointer;
  color: var(--clr-text-muted);
  transition: all var(--transition);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
}

.status-btn.active {
  background: var(--clr-surface);
  color: var(--clr-primary);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}

.status-toggle :deep(.btn) {
  flex: 1;
}

/* ─────────────────────────────────────────────
   LINES TABLE
───────────────────────────────────────────── */
.lines-header {
  display: grid;
  grid-template-columns: 2.5fr 1.4fr 1fr 1fr 1fr 44px;
  gap: 8px;
  padding: 0 12px 8px;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--clr-text-muted);
}

.lines-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.line-row {
  display: grid;
  grid-template-columns: 2.5fr 1.4fr 1fr 1fr 1fr 44px;
  gap: 8px;
  align-items: center;
  background: var(--clr-surface);
  border: 1.5px solid var(--clr-border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  transition: box-shadow var(--transition), border-color var(--transition);
}

.line-row:hover {
  box-shadow: var(--shadow-sm);
  border-color: #d0d8ff;
}

.cell {
  position: relative;
}

.price-input-wrapper {
  position: relative;
}
.currency-symbol {
  position: absolute;
  left: 9px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--clr-text-muted);
  font-family: "DM Mono", monospace;
  pointer-events: none;
}

.line-delete-btn {
  width: 32px;
  height: 32px;
  min-width: 32px;
  padding: 0;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  transition: all var(--transition);
}

.line-delete-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ─────────────────────────────────────────────
   LINES FOOTER
───────────────────────────────────────────── */
.lines-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 0 0;
  border-top: 1.5px dashed var(--clr-border);
  margin-top: 0.75rem;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.btn-add-line {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border: 1.5px dashed var(--clr-primary);
  background: var(--clr-primary-light);
  color: var(--clr-primary);
  border-radius: var(--radius-md);
  font-family: "DM Sans", sans-serif;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--transition);
}

.btn-add-line:hover {
  background: var(--clr-primary);
  color: #fff;
  border-style: solid;
}

.lines-summary {
  display: flex;
  gap: 1.25rem;
  align-items: center;
}

.summary-item {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1px;
}

.summary-label {
  font-size: 0.65rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--clr-text-muted);
}

.summary-value {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--clr-text);
  font-family: "DM Mono", monospace;
}

.summary-item--total .summary-value {
  color: var(--clr-primary);
  font-size: 1rem;
}

/* ─────────────────────────────────────────────
   RECAP GRID
───────────────────────────────────────────── */
.recap-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 1rem;
  margin-bottom: 1.5rem;
}

@media (max-width: 640px) {
  .recap-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.recap-item {
  background: var(--clr-surface);
  border: 1.5px solid var(--clr-border);
  border-radius: var(--radius-md);
  padding: 0.9rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.recap-label {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--clr-text-muted);
  display: flex;
  align-items: center;
  gap: 5px;
}

.recap-value {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--clr-text);
}

.recap-total {
  font-size: 1.1rem;
  color: var(--clr-primary);
  font-family: "DM Mono", monospace;
}

.status-pill {
  font-size: 0.72rem;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 99px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.status-pill.draft {
  background: #fff3bf;
  color: #946500;
}

.status-pill.posted {
  background: var(--clr-success-light);
  color: #0b7a5e;
}

/* ─────────────────────────────────────────────
   BUTTONS
───────────────────────────────────────────── */
.card-actions {
  display: flex;
  justify-content: flex-end;
  padding-top: 1.25rem;
  border-top: 1.5px solid var(--clr-border);
  margin-top: 1.25rem;
}

.card-actions--spread {
  justify-content: space-between;
}

.action-group {
  display: flex;
  gap: 0.75rem;
  align-items: center;
}

.btn-primary,
.btn-success {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 1.25rem;
  border: none;
  border-radius: var(--radius-md);
  font-family: "DM Sans", sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--transition);
}

.btn-primary {
  background: var(--clr-primary);
  color: #fff;
}
.btn-primary:hover {
  background: var(--clr-primary-dark);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(59, 91, 219, 0.3);
}

.btn-success {
  background: var(--clr-success);
  color: #fff;
}
.btn-success:hover:not(:disabled) {
  filter: brightness(1.08);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(18, 184, 134, 0.3);
}
.btn-success:disabled {
  opacity: 0.65;
  cursor: not-allowed;
  transform: none;
}

.btn-ghost {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 1rem;
  border: 1.5px solid var(--clr-border);
  background: transparent;
  border-radius: var(--radius-md);
  font-family: "DM Sans", sans-serif;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--clr-text-muted);
  cursor: pointer;
  transition: all var(--transition);
}
.btn-ghost:hover {
  border-color: var(--clr-primary);
  color: var(--clr-primary);
  background: var(--clr-primary-light);
}

.btn-outline-danger {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 1rem;
  border: 1.5px solid #ffc9c9;
  background: transparent;
  border-radius: var(--radius-md);
  font-family: "DM Sans", sans-serif;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--clr-danger);
  cursor: pointer;
  transition: all var(--transition);
}
.btn-outline-danger:hover {
  background: var(--clr-danger-light);
  border-color: var(--clr-danger);
}

.btn-spinner {
  width: 16px;
  height: 16px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

.soft-action-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.btn-add-line-soft {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* ─────────────────────────────────────────────
   TRANSITIONS
───────────────────────────────────────────── */
.slide-down-enter-active,
.slide-down-leave-active {
  transition: all 0.22s cubic-bezier(0.4, 0, 0.2, 1);
  overflow: hidden;
}
.slide-down-enter-from,
.slide-down-leave-to {
  opacity: 0;
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
}
.slide-down-enter-to,
.slide-down-leave-from {
  max-height: 800px;
}

.dropdown-enter-active,
.dropdown-leave-active {
  transition: all 0.16s ease;
}
.dropdown-enter-from,
.dropdown-leave-to {
  opacity: 0;
  transform: translateY(-6px);
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.15s;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

.shake-enter-active {
  animation: shake 0.3s ease;
}
@keyframes shake {
  0%,
  100% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-4px);
  }
  75% {
    transform: translateX(4px);
  }
}

.line-list-enter-active {
  transition: all 0.2s ease;
}
.line-list-leave-active {
  transition: all 0.15s ease;
}
.line-list-enter-from {
  opacity: 0;
  transform: translateY(-8px);
}
.line-list-leave-to {
  opacity: 0;
  transform: translateX(20px);
}

/* ─────────────────────────────────────────────
   MISC
───────────────────────────────────────────── */
.position-relative {
  position: relative;
}
</style>
