@extends('layouts.app')

@section('content')
    @php
        $productsForJs = $products->map(function ($product) {
            return [
                'id' => $product->id,
                'name' => $product->name,
                'material_ids' => $product->materials->pluck('id')->values()->toArray(),
            ];
        })->values()->toArray();

        $materialsForJs = collect($materialsJson ?? [])->values()->toArray();

        $customersForJs = $customers->map(function ($customer) {
            return [
                'id' => $customer->id,
                'name' => $customer->name,
                'member_type' => $customer->member_type,
                'phone' => $customer->phone ?? '',
                'contact_person' => $customer->contact_person ?? '',
                'npwp' => $customer->npwp ?? '',
                'email' => $customer->email ?? '',
            ];
        })->values()->toArray();

        $customersMapForJs = $customers->mapWithKeys(function ($customer) {
            return [$customer->id => $customer->member_type];
        })->toArray();

        $loggedInUserName = auth()->user()->name ?? auth()->user()->email ?? 'User';
    @endphp

    <x-common.page-breadcrumb pageTitle="{{ $title ?? 'Buat Order Baru' }}" />

    <div class="mb-4 rounded-2xl border border-amber-200 bg-gradient-to-r from-amber-50 via-white to-amber-50 p-3 shadow-sm dark:border-amber-500/30 dark:from-amber-500/10 dark:via-white/[0.03] dark:to-amber-500/10">
        <div class="flex flex-col gap-3 lg:flex-row lg:items-center">
            <div class="flex shrink-0 items-center gap-2 rounded-xl bg-amber-100 px-3 py-2 text-amber-900 dark:bg-amber-500/20 dark:text-amber-100">
                <span class="inline-flex size-7 items-center justify-center rounded-lg bg-amber-500 text-white shadow-sm">
                    <svg class="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v3.75m0 3.75h.008v.008H12V16.5zm0-13.5a9 9 0 100 18 9 9 0 000-18z" />
                    </svg>
                </span>
                <span class="text-sm font-bold">Pengingat Input</span>
            </div>

            <div class="relative min-w-0 flex-1 overflow-hidden rounded-xl border border-amber-100 bg-white/80 px-3 py-2 dark:border-amber-500/20 dark:bg-gray-900/40">
                <div class="pointer-events-none absolute inset-y-0 left-0 w-8 bg-gradient-to-r from-white/95 to-transparent dark:from-gray-900/95"></div>
                <div class="pointer-events-none absolute inset-y-0 right-0 w-8 bg-gradient-to-l from-white/95 to-transparent dark:from-gray-900/95"></div>
                <div class="marquee-track flex whitespace-nowrap text-sm font-semibold text-amber-800 dark:text-amber-200">
                    <span class="mr-12">
                        Halo {{ $loggedInUserName }} — cek Nama Pemesan dulu sebelum pilih item. Pastikan produk, bahan, nama file, ukuran, qty, sisi, harga, dan catatan finishing sudah tepat sebelum simpan.
                    </span>
                    <span class="mr-12" aria-hidden="true">
                        Halo {{ $loggedInUserName }} — cek Nama Pemesan dulu sebelum pilih item. Pastikan produk, bahan, nama file, ukuran, qty, sisi, harga, dan catatan finishing sudah tepat sebelum simpan.
                    </span>
                </div>
            </div>

            <a
                href="https://wa.me/628990799960?text=Halo%20admin%2C%20saya%20butuh%20bantuan%20karena%20ada%20error%20saat%20input%20order."
                target="_blank"
                rel="noopener noreferrer"
                class="inline-flex shrink-0 items-center justify-center gap-2 rounded-xl bg-gray-100 px-4 py-2.5 text-sm font-semibold text-gray-800 transition hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-gray-400/30 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
                title="Hubungi bantuan via WhatsApp"
            >
                <svg class="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 4v-4z" />
                </svg>
                Bantuan Error
            </a>
        </div>
    </div>

    <div class="mb-6 rounded-2xl border border-gray-200 bg-white p-5 shadow-sm dark:border-gray-800 dark:bg-white/[0.03]">
        <div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
            <div class="min-w-0">
                <div class="flex items-center gap-2">
                    <span class="inline-flex size-9 items-center justify-center rounded-xl bg-gray-900 text-white dark:bg-white dark:text-gray-900">
                        <svg class="size-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                                  d="M13 16h-1v-4h-1m1-4h.01M12 20a8 8 0 100-16 8 8 0 000 16z"/>
                        </svg>
                    </span>
                    <div>
                        <p class="text-sm font-semibold text-gray-900 dark:text-white/90">
                            Mode Input Cepat — akurasi dulu, baru ngebut.
                        </p>
                        <p class="mt-0.5 text-xs text-gray-500 dark:text-gray-400">
                            Urutan aman:
                            <span class="font-semibold">Nama Pemesan → Produk → Bahan → Nama File → Unit → Ukuran (jika meter/m²) → Qty → Sisi → Harga → Catatan finishing</span>.
                            Kalau ragu, tulis catatan finishing biar produksi nggak salah tafsir.
                        </p>
                    </div>
                </div>
            </div>

            <div class="flex flex-wrap items-center gap-2">
                <span class="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-3 py-2 text-xs font-semibold text-gray-800 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100">
                    <kbd class="rounded bg-white px-1.5 py-0.5 text-[11px] font-bold text-gray-900 shadow-sm dark:bg-gray-900 dark:text-white">Ctrl</kbd>
                    +
                    <kbd class="rounded bg-white px-1.5 py-0.5 text-[11px] font-bold text-gray-900 shadow-sm dark:bg-gray-900 dark:text-white">Enter</kbd>
                    <span class="text-gray-500 dark:text-gray-400">Simpan</span>
                </span>
                <span class="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-3 py-2 text-xs font-semibold text-gray-800 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100">
                    <kbd class="rounded bg-white px-1.5 py-0.5 text-[11px] font-bold text-gray-900 shadow-sm dark:bg-gray-900 dark:text-white">Ctrl</kbd>
                    +
                    <kbd class="rounded bg-white px-1.5 py-0.5 text-[11px] font-bold text-gray-900 shadow-sm dark:bg-gray-900 dark:text-white">D</kbd>
                    <span class="text-gray-500 dark:text-gray-400">Duplikat</span>
                </span>
                <span class="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-3 py-2 text-xs font-semibold text-gray-800 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100">
                    <kbd class="rounded bg-white px-1.5 py-0.5 text-[11px] font-bold text-gray-900 shadow-sm dark:bg-gray-900 dark:text-white">Alt</kbd>
                    +
                    <span class="text-[11px] font-bold">↑/↓</span>
                    <span class="text-gray-500 dark:text-gray-400">Pindah baris</span>
                </span>
            </div>
        </div>
    </div>

    <div x-data="orderForm()" x-init="init()" class="space-y-6" @keydown.window="handleGlobalKeydown($event)">
        <div class="rounded-2xl border border-gray-200 bg-white dark:border-gray-800 dark:bg-white/[0.03]">
            <div class="border-b border-gray-200 px-5 py-4 dark:border-gray-800 flex items-center justify-between">
                <div class="flex items-center gap-2">
                    <span class="inline-flex size-9 items-center justify-center rounded-xl bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-100">
                        <svg class="size-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                                  d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
                        </svg>
                    </span>
                    <div>
                        <h3 class="text-lg font-semibold text-gray-800 dark:text-white/90">Form Order Baru</h3>
                        <p class="text-xs text-gray-500 dark:text-gray-400">Fokus baris aktif otomatis di-highlight.</p>
                    </div>
                </div>
            </div>

            <div class="p-5">
                <form id="form-order" action="{{ route('orders.store') }}" method="POST" enctype="multipart/form-data" @submit="prepareSubmit" @keydown.enter="handleFormEnter($event)" autocomplete="off">
                    @csrf

                    <div class="flex flex-wrap items-end gap-3 mb-6 pb-5 border-b border-gray-200 dark:border-gray-700">
                        <div class="w-72">
                            <label class="mb-1.5 block text-sm font-medium text-gray-700 dark:text-gray-400">
                                Nama Pemesan <span class="text-red-500">*</span>
                            </label>

                            <div class="relative" @click.outside="customerDropdownOpen = false; customerSearch = ''">
                                <button
                                    type="button"
                                    @click="customerDropdownOpen = !customerDropdownOpen; customerSearch = ''; if(customerDropdownOpen) $nextTick(() => document.getElementById('customer-search')?.focus())"
                                    class="relative h-11 w-full rounded-lg border bg-white px-3 pr-10 text-left text-sm shadow-sm focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:bg-gray-900 dark:text-white"
                                    :class="errors.customer_id ? 'border-red-500' : 'border-gray-300 dark:border-gray-700'"
                                >
                                    <span class="block truncate" x-text="selectedCustomerName || 'Pilih Nama Pemesan...'"></span>
                                    <span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3 text-gray-500">
                                        <svg class="h-4 w-4" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
                                            <path d="M4.79175 7.396L10.0001 12.6043L15.2084 7.396"/>
                                        </svg>
                                    </span>
                                </button>

                                <div x-show="customerDropdownOpen" x-transition class="absolute z-50 left-0 mt-1 max-h-64 w-full overflow-auto rounded-xl border border-gray-200 bg-white py-1 shadow-lg dark:border-gray-800 dark:bg-gray-900" style="display:none;">
                                    <div class="sticky top-0 bg-white px-2 py-2 dark:bg-gray-900">
                                        <input
                                            id="customer-search"
                                            type="text"
                                            x-model="customerSearch"
                                            placeholder="Cari Nama Pemesan / Instansi / Kontak / Email..."
                                            class="w-full rounded-lg border border-gray-300 bg-gray-50 px-3 py-2 text-sm text-gray-800 focus:border-gray-900 focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:border-gray-700 dark:bg-gray-800 dark:text-white"
                                            @keydown.enter.prevent="selectFirstCustomer()"
                                            @keydown.escape.prevent="customerDropdownOpen = false"
                                        >
                                    </div>

                                    <div x-show="!customerSearch.trim() && selectedCustomer" class="border-b border-gray-100 px-4 py-2 text-xs text-gray-500 dark:border-gray-800 dark:text-gray-400" style="display:none;">
                                        Terpilih saat ini
                                    </div>

                                    <template x-for="customer in filteredCustomers" :key="customer.id">
                                        <button
                                            type="button"
                                            @click="selectCustomer(customer)"
                                            class="flex w-full items-center justify-between gap-2 px-4 py-2 text-left text-sm hover:bg-gray-100 dark:hover:bg-gray-800"
                                            :class="String(customer_id) === String(customer.id) ? 'bg-gray-50 font-semibold text-gray-900 dark:bg-white/[0.06] dark:text-white' : 'text-gray-700 dark:text-gray-300'"
                                        >
                                            <span class="min-w-0">
                                                <span class="block truncate" x-text="customer.name"></span>
                                                <span class="mt-0.5 block truncate text-[11px] font-normal text-gray-500 dark:text-gray-400"
                                                      x-text="[customer.contact_person, customer.phone, customer.email].filter(Boolean).join(' • ')"></span>
                                            </span>
                                            <span class="shrink-0 rounded-full bg-gray-100 px-2 py-0.5 text-[10px] uppercase text-gray-500 dark:bg-gray-800 dark:text-gray-400" x-text="customer.member_type || 'umum'"></span>
                                        </button>
                                    </template>

                                    <div x-show="filteredCustomers.length === 0" class="px-4 py-3 text-sm text-gray-500">
                                        <span x-show="!customerSearch.trim()">Belum ada daftar ditampilkan. Ketik nama pelanggan untuk mencari.</span>
                                        <span x-show="customerSearch.trim().length === 1">Lanjutkan ketik minimal 2 huruf supaya hasil lebih akurat.</span>
                                        <span x-show="customerSearch.trim().length >= 2">Tidak ditemukan. Klik tombol + untuk tambah Nama Pemesan baru.</span>
                                    </div>
                                </div>

                                <input type="hidden" name="customer_id" x-model="customer_id">
                            </div>

                            <p x-show="errors.customer_id" x-text="errors.customer_id" class="mt-1 text-xs text-red-500" style="display:none;"></p>
                            <p x-show="customerSuccessMessage" x-text="customerSuccessMessage" class="mt-1 text-xs text-green-600 dark:text-green-400" style="display:none;"></p>
                        </div>

                        <button
                            type="button"
                            @click="$dispatch('open-customer-modal')"
                            class="h-11 w-11 inline-flex items-center justify-center rounded-lg bg-gray-900 text-white shadow-sm hover:bg-gray-800 dark:bg-white dark:text-gray-900 dark:hover:bg-gray-200"
                            title="Tambah Nama Pemesan (Ctrl+N)"
                        >
                            <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
                            </svg>
                        </button>

                        <div class="flex-1 min-w-[240px]">
                            <x-form.input name="notes" label="Catatan" placeholder="Catatan order (opsional)..." />
                        </div>

                        <label class="flex items-center gap-2 px-4 py-2.5 rounded-lg border border-gray-300 dark:border-gray-600 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
                            <input
                                type="checkbox"
                                name="is_credit"
                                value="1"
                                x-model="is_credit"
                                class="w-4 h-4 rounded border-gray-300 text-orange-500 focus:ring-orange-500 dark:border-gray-600 dark:bg-gray-700"
                            >
                            <span class="text-sm font-semibold text-orange-600 dark:text-orange-400">Piutang</span>
                        </label>
                    </div>

                    <div class="mb-6">
                        <div class="flex items-center justify-between mb-3">
                            <h4 class="text-sm font-semibold text-gray-800 dark:text-white/90">Item Order</h4>
                            <span class="text-xs text-gray-500 dark:text-gray-400" x-text="`${items.length} item`"></span>
                        </div>

                        <div class="mb-3 rounded-xl border border-blue-100 bg-blue-50 px-4 py-3 text-xs font-medium text-blue-700 dark:border-blue-500/20 dark:bg-blue-500/10 dark:text-blue-300">
                            Setiap kolom sudah diberi judul di atas input agar operator mudah mengisi: Produk, Bahan, Nama File, File Upload, Unit, Ukuran, Nilai, Qty, Sisi, Harga, Manual, Subtotal, Catatan Finishing, dan Keterangan Cetak.
                        </div>

                        <div class="space-y-2 overflow-x-auto pb-2" id="items-container">
                            <template x-for="(item, index) in items" :key="item.id">
                                <div
                                    class="border rounded-xl p-3 transition-all duration-150"
                                    :class="activeRow === index ? 'border-gray-900 bg-gray-50 ring-1 ring-gray-900/10 dark:border-white/60 dark:bg-white/[0.03]' : 'border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-900/20'"
                                    @click="activeRow = index"
                                    :data-row="index"
                                >
                                    <div class="grid min-w-[1540px] grid-cols-[36px_155px_155px_140px_150px_95px_125px_85px_100px_90px_120px_120px_130px] items-start gap-3">
                                        <div class="flex items-center justify-center pt-6">
                                            <span class="w-6 h-6 flex items-center justify-center rounded-full bg-gray-900 text-white text-xs font-bold dark:bg-white dark:text-gray-900" x-text="index + 1"></span>
                                        </div>

                                        <div class="relative min-w-0">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Produk</label>
                                            <div @click.outside="item.productDropdownOpen = false; item.productSearch = ''">
                                                <button
                                                    type="button"
                                                    @click="item.productDropdownOpen = !item.productDropdownOpen; item.productSearch = ''; if(item.productDropdownOpen) $nextTick(() => document.getElementById('psearch-'+index)?.focus())"
                                                    @focus="activeRow = index"
                                                    class="relative h-9 w-full text-left appearance-none rounded-lg border bg-white px-2 pr-8 text-sm focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:bg-gray-900 dark:border-gray-700 dark:text-white"
                                                    :class="errors[`items.${index}.product_id`] ? 'border-red-500' : 'border-gray-300'"
                                                    :data-field="'product-' + index"
                                                >
                                                    <span class="block truncate" x-text="item.product_name || 'Produk'"></span>
                                                    <span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2 text-gray-500">
                                                        <svg class="h-4 w-4" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
                                                            <path d="M4.79175 7.396L10.0001 12.6043L15.2084 7.396"/>
                                                        </svg>
                                                    </span>
                                                </button>

                                                <div x-show="item.productDropdownOpen" x-transition class="absolute z-50 left-0 mt-1 max-h-60 w-56 overflow-auto rounded-xl border border-gray-200 bg-white py-1 shadow-lg dark:border-gray-800 dark:bg-gray-900" style="display:none;">
                                                    <div class="px-2 py-1 sticky top-0 bg-white dark:bg-gray-900">
                                                        <input
                                                            :id="'psearch-'+index"
                                                            x-model="item.productSearch"
                                                            type="text"
                                                            class="w-full rounded-lg border border-gray-300 bg-gray-50 px-3 py-2 text-sm text-gray-800 focus:border-gray-900 focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:border-gray-700 dark:bg-gray-800 dark:text-white"
                                                            placeholder="Cari produk..."
                                                            @keydown.enter.prevent="selectFirstProduct(index)"
                                                            @keydown.escape.prevent="item.productDropdownOpen = false"
                                                        >
                                                    </div>

                                                    <template x-for="p in filteredProducts(index)" :key="p.id">
                                                        <div
                                                            @click="selectProduct(index, p)"
                                                            class="cursor-pointer px-4 py-2 text-sm hover:bg-gray-100 dark:hover:bg-gray-800"
                                                            :class="item.product_id == p.id ? 'bg-gray-50 text-gray-900 font-semibold dark:bg-white/[0.06] dark:text-white' : 'text-gray-700 dark:text-gray-300'"
                                                        >
                                                            <span x-text="p.name"></span>
                                                        </div>
                                                    </template>

                                                    <div x-show="filteredProducts(index).length === 0" class="px-4 py-2 text-sm text-gray-500">Tidak ditemukan</div>
                                                </div>

                                                <input type="hidden" :name="`items[${index}][product_id]`" x-model="item.product_id">
                                                <input type="hidden" :name="`items[${index}][product_name]`" x-model="item.product_name">
                                            </div>

                                            <p x-show="errors[`items.${index}.product_id`]" x-text="errors[`items.${index}.product_id`]" class="absolute top-full left-0 mt-0.5 text-[10px] text-red-500 leading-tight w-full" style="display:none;"></p>
                                        </div>

                                        <div class="relative min-w-0" @click.outside="item.materialDropdownOpen = false; item.materialSearch = ''">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Bahan</label>
                                            <button
                                                type="button"
                                                @click="if(!item.loadingMaterials) { item.materialDropdownOpen = !item.materialDropdownOpen; item.materialSearch = ''; if(item.materialDropdownOpen) $nextTick(() => document.getElementById('msearch-'+index)?.focus()); }"
                                                @focus="activeRow = index"
                                                :disabled="item.loadingMaterials"
                                                class="relative h-9 w-full text-left appearance-none rounded-lg border bg-white px-2 pr-8 text-sm focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:bg-gray-900 dark:border-gray-700 dark:text-white disabled:opacity-60"
                                                :class="errors[`items.${index}.material_id`] ? 'border-red-500' : 'border-gray-300'"
                                                :data-field="'material-' + index"
                                            >
                                                <span class="block truncate" x-text="item.loadingMaterials ? 'Loading...' : (item.material_name || 'Bahan')"></span>
                                                <span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2 text-gray-500">
                                                    <svg class="h-4 w-4" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
                                                        <path d="M4.79175 7.396L10.0001 12.6043L15.2084 7.396"/>
                                                    </svg>
                                                </span>
                                            </button>

                                            <div x-show="item.materialDropdownOpen" x-transition class="absolute z-50 left-0 mt-1 max-h-60 w-56 overflow-auto rounded-xl border border-gray-200 bg-white py-1 shadow-lg dark:border-gray-800 dark:bg-gray-900" style="display:none;">
                                                <div class="px-2 py-1 sticky top-0 bg-white dark:bg-gray-900">
                                                    <input
                                                        :id="'msearch-'+index"
                                                        x-model="item.materialSearch"
                                                        type="text"
                                                        class="w-full rounded-lg border border-gray-300 bg-gray-50 px-3 py-2 text-sm text-gray-800 focus:border-gray-900 focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:border-gray-700 dark:bg-gray-800 dark:text-white"
                                                        placeholder="Cari bahan..."
                                                        @keydown.enter.prevent="selectFirstMaterial(index)"
                                                        @keydown.escape.prevent="item.materialDropdownOpen = false"
                                                    >
                                                </div>

                                                <template x-for="mat in filteredMaterials(index)" :key="mat.id">
                                                    <div
                                                        @click="selectMaterial(index, mat)"
                                                        class="cursor-pointer px-4 py-2 text-sm hover:bg-gray-100 dark:hover:bg-gray-800"
                                                        :class="item.material_id == mat.id ? 'bg-gray-50 text-gray-900 font-semibold dark:bg-white/[0.06] dark:text-white' : (mat.available_for_order === false ? 'text-red-500 dark:text-red-400' : 'text-gray-700 dark:text-gray-300')"
                                                    >
                                                        <span x-text="materialOptionLabel(mat)"></span>
                                                    </div>
                                                </template>

                                                <div x-show="filteredMaterials(index).length === 0" class="px-4 py-2 text-sm text-gray-500">Tidak ditemukan</div>
                                            </div>

                                            <input type="hidden" :name="`items[${index}][material_id]`" x-model="item.material_id">
                                            <input type="hidden" :name="`items[${index}][material_name]`" x-model="item.material_name">

                                            <p x-show="errors[`items.${index}.material_id`]" x-text="errors[`items.${index}.material_id`]" class="absolute top-full left-0 mt-0.5 text-[10px] text-red-500 leading-tight w-full" style="display:none;"></p>
                                        </div>

                                        <div class="relative min-w-0">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Nama File</label>
                                            <input
                                                type="text"
                                                :name="`items[${index}][file_name]`"
                                                x-model="item.file_name"
                                                @input="clearError(`items.${index}.file_name`)"
                                                @focus="activeRow = index"
                                                @keydown.enter.prevent="focusNextField($el, 'unit')"
                                                placeholder="Nama File"
                                                class="w-full h-9 rounded-lg border px-2 text-sm focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:bg-gray-900"
                                                :class="errors[`items.${index}.file_name`] ? 'border-red-500' : 'border-gray-300 dark:border-gray-700'"
                                                :data-field="'filename-' + index"
                                            >
                                            <p x-show="errors[`items.${index}.file_name`]" x-text="'Wajib!'" class="absolute top-full left-0 mt-0.5 text-[10px] text-red-500 leading-tight" style="display:none;"></p>
                                        </div>

                                        <div class="min-w-0">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">File Upload</label>
                                            <div
                                                class="group relative flex h-10 w-full cursor-pointer items-center justify-center overflow-hidden rounded-lg px-3 text-[10px] font-bold text-white shadow-sm transition focus:outline-none focus:ring-2 focus:ring-brand-300 dark:focus:ring-brand-500/30 bg-gray-900 text-white hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-60 dark:bg-white dark:text-gray-900 dark:hover:bg-gray-200"
                                                :class="item.preview_image_url ? 'opacity-90' : ''"
                                                @click.prevent.stop="window.openOrderPreviewUploader(index)"
                                                tabindex="0"
                                                title="Upload Preview"
                                            >
                                                <template x-if="item.preview_image_url">
                                                    <img :src="item.preview_image_url" class="h-full w-full object-cover" alt="Preview">
                                                </template>

                                                <template x-if="!item.preview_image_url">
                                                    <span class="px-1 text-center leading-tight">Upload<br>Preview</span>
                                                </template>

                                                <div
                                                    x-show="item.preview_image_url"
                                                    class="absolute inset-0 hidden items-center justify-center bg-black/45 text-[10px] font-bold text-white group-hover:flex"
                                                >
                                                    Lihat
                                                </div>

                                                <button
                                                    type="button"
                                                    x-show="item.preview_image_url"
                                                    @click.stop="item.preview_image_url = ''; item.preview_image_name = ''; document.getElementById(`preview-input-${index}`).value = ''"
                                                    class="absolute right-0.5 top-0.5 flex h-4 w-4 items-center justify-center rounded-full bg-black/70 text-[10px] text-white"
                                                    title="Hapus preview"
                                                >×</button>
                                            </div>

                                            <input
                                                type="file"
                                                class="hidden"
                                                :name="`items[${index}][preview_image]`"
                                                accept="image/jpeg,image/png,image/webp"
                                                :id="`preview-input-${index}`"
                                                @change="if (window.handleOrderPreviewFileInput) window.handleOrderPreviewFileInput($event, index)"
                                            >
                                        </div>


                                        <div class="min-w-0">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Unit</label>
                                            <select
                                                :name="`items[${index}][size_unit]`"
                                                x-model="item.size_unit"
                                                @change="handleUnitChange(index)"
                                                @focus="activeRow = index"
                                                @keydown.enter.prevent="focusAfterUnit(index)"
                                                class="h-9 w-full rounded-lg border border-gray-300 bg-white px-2 text-sm text-gray-900 shadow-sm focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:border-gray-700 dark:bg-gray-900 dark:text-white"
                                                :data-field="'unit-' + index"
                                                title="Unit"
                                            >
                                                <option value="m2">m²</option>
                                                <option value="meter">meter</option>
                                                <option value="lembar">lembar</option>
                                            </select>
                                        </div>

                                        <div class="relative min-w-0">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Ukuran</label>
                                            <input
                                                type="text"
                                                :name="`items[${index}][size_description]`"
                                                x-model="item.size_description"
                                                x-show="item.size_unit === 'm2' || item.size_unit === 'meter'"
                                                @input="parseSize(index)"
                                                @focus="activeRow = index"
                                                @keydown.enter.prevent="focusNextField($el, 'qty')"
                                                placeholder="2x3 / 80x200"
                                                class="w-full h-9 rounded-lg border px-2 text-sm focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:bg-gray-900"
                                                :class="errors[`items.${index}.size`] ? 'border-red-500' : 'border-gray-300 dark:border-gray-700'"
                                                :data-field="'size-' + index"
                                                title="Ukuran (wajib untuk meter/m²)"
                                                style="display:none;"
                                            >
                                            <div x-show="!(item.size_unit === 'm2' || item.size_unit === 'meter')" class="flex h-9 items-center justify-center text-gray-400 text-sm">-</div>
                                            <p x-show="errors[`items.${index}.size`]" x-text="'Wajib!'" class="absolute top-full left-0 mt-0.5 text-[10px] text-red-500 leading-tight" style="display:none;"></p>
                                        </div>

                                        <div class="min-w-0">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Nilai</label>
                                            <div x-show="item.size_unit === 'm2'" class="flex items-center" style="display:none;">
                                                <input
                                                    type="number"
                                                    :name="`items[${index}][size_value]`"
                                                    x-model.number="item.size_value"
                                                    @input="calculateSubtotal(index)"
                                                    @focus="activeRow = index"
                                                    step="0.0001"
                                                    min="0.0001"
                                                    class="w-full h-9 rounded-lg border border-gray-300 bg-white px-2 text-sm text-center focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:border-gray-700 dark:bg-gray-900 dark:text-white"
                                                    :data-field="'sizevalue-' + index"
                                                    title="Nilai m²"
                                                >
                                            </div>

                                            <div x-show="item.size_unit === 'meter'" class="flex items-center" style="display:none;">
                                                <input
                                                    type="text"
                                                    :value="item.size_value > 0 ? formatDecimal(item.size_value) : ''"
                                                    readonly
                                                    tabindex="-1"
                                                    class="w-full h-9 rounded-lg border border-gray-300 bg-gray-50 px-2 text-sm text-center text-gray-700 focus:outline-hidden dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200"
                                                    title="Nilai meter"
                                                >
                                            </div>

                                            <div x-show="item.size_unit !== 'm2' && item.size_unit !== 'meter'" class="flex h-9 items-center justify-center text-gray-400 text-sm">-</div>
                                        </div>

                                        <div class="relative min-w-0">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Qty</label>
                                            <input
                                                type="number"
                                                :name="`items[${index}][qty]`"
                                                x-model.number="item.qty"
                                                @input="clearError(`items.${index}.qty`); lookupPrice(index); calculateSubtotal(index);"
                                                @focus="activeRow = index"
                                                @keydown.enter.prevent="focusNextField($el, 'sisi')"
                                                min="1"
                                                class="w-full h-9 rounded-lg border px-2 text-sm text-center focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:bg-gray-900"
                                                :class="errors[`items.${index}.qty`] ? 'border-red-500' : 'border-gray-300 dark:border-gray-700'"
                                                :data-field="'qty-' + index"
                                                title="Qty"
                                            >
                                            <p x-show="errors[`items.${index}.qty`]" x-text="'!'" class="absolute -top-2 -right-2 text-[10px] font-bold text-red-500" style="display:none;"></p>
                                        </div>

                                        <div class="min-w-0">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Sisi</label>
                                            <template x-if="item.size_unit === 'm2'">
                                                <div class="flex h-9 w-16 items-center justify-center text-gray-400 text-sm">-</div>
                                            </template>

                                            <template x-if="item.size_unit !== 'm2'">
                                                <select
                                                    :name="`items[${index}][sisi]`"
                                                    x-model.number="item.sisi"
                                                    @change="lookupPrice(index); calculateSubtotal(index);"
                                                    @focus="activeRow = index"
                                                    class="h-9 w-16 rounded-lg border border-gray-300 bg-transparent px-2 py-1.5 text-sm text-gray-800 shadow-theme-xs focus:border-brand-300 focus:outline-hidden focus:ring-3 focus:ring-brand-500/20 dark:border-gray-700 dark:bg-gray-900 dark:text-white/90 dark:focus:border-brand-800"
                                                    :data-field="'sisi-' + index"
                                                    title="Jumlah sisi cetak"
                                                >
                                                    <option value="1">1</option>
                                                    <option value="2">2</option>
                                                </select>
                                            </template>

                                            <template x-if="item.size_unit === 'm2'">
                                                <input type="hidden" :name="`items[${index}][sisi]`" value="1">
                                            </template>
                                        </div>

                                        <div class="min-w-0">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Harga</label>
                                            <input
                                                type="number"
                                                :name="`items[${index}][base_price]`"
                                                x-model.number="item.base_price"
                                                @input="calculateSubtotal(index)"
                                                @focus="activeRow = index"
                                                @keydown.enter.prevent="handlePriceEnter(index)"
                                                min="0"
                                                class="w-full h-9 rounded-lg border border-gray-300 bg-white px-2 text-sm text-right focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:border-gray-700 dark:bg-gray-900 dark:text-white"
                                                :data-field="'price-' + index"
                                                title="Harga satuan (Enter = baris baru)"
                                            >
                                        </div>

                                        <div class="min-w-0">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Manual</label>
                                            <input
                                                type="number"
                                                :name="`items[${index}][manual_price]`"
                                                x-model.number="item.manual_price"
                                                @input="calculateSubtotal(index)"
                                                @focus="activeRow = index"
                                                @keydown.enter.prevent="handlePriceEnter(index)"
                                                min="0"
                                                placeholder="Auto"
                                                class="h-9 w-full rounded-lg border border-gray-300 bg-white px-2 text-right text-sm focus:ring-2 focus:ring-gray-900/10 dark:border-gray-700 dark:bg-gray-900 dark:text-white"
                                                :data-field="'manual-' + index"
                                                title="Isi jika harga final mau dibuat manual. Kosongkan/0 untuk harga otomatis + minimal order Rp 10.000."
                                            >
                                        </div>

                                        <div class="min-w-0">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Subtotal</label>
                                            <div class="flex h-9 items-center justify-end rounded-lg border border-gray-200 bg-gray-50 px-2 text-right leading-tight dark:border-gray-700 dark:bg-gray-800">
                                                <span class="font-semibold text-gray-900 dark:text-white" x-text="formatRupiah(item.subtotal)"></span>
                                                <div x-show="item.manual_price > 0" class="text-[10px] font-semibold text-blue-600" style="display:none;">Manual</div>
                                                <div x-show="item.minimum_order_applied" class="text-[10px] font-semibold text-amber-600" style="display:none;">Min. Rp 10rb</div>
                                            </div>
                                        </div>

                                        <div class="min-w-0 xl:col-span-4 2xl:col-span-4">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Catatan Finishing</label>
                                            <input
                                                type="text"
                                                :name="`items[${index}][finishing_note]`"
                                                x-model="item.finishing_note"
                                                @focus="activeRow = index"
                                                placeholder="Mata ayam/lipat/lebihbahan"
                                                class="w-full h-9 rounded-lg border border-gray-300 bg-white px-2 text-sm focus:outline-hidden focus:ring-2 focus:ring-gray-900/10 dark:border-gray-700 dark:bg-gray-900 dark:text-white"
                                                :data-field="'finishing-' + index"
                                            >
                                        </div>

                                        <div class="min-w-0 xl:col-span-7 2xl:col-span-7">
                                            <label class="mb-1 block text-[11px] font-bold uppercase tracking-wide text-gray-500 dark:text-gray-400">Keterangan Cetak</label>
                                            <div class="flex gap-2">
                                                <textarea
                                                    readonly
                                                    rows="2"
                                                    :value="buildPrintDescription(item)"
                                                    class="min-h-[36px] w-full resize-none rounded-lg border border-gray-300 bg-gray-50 px-2 py-1.5 text-[11px] leading-snug text-gray-700 focus:outline-hidden dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200"
                                                    title="Ringkasan otomatis untuk keterangan cetak"
                                                ></textarea>

                                                <button
                                                    type="button"
                                                    @click="copyPrintDescription(index)"
                                                    class="inline-flex h-9 shrink-0 items-center justify-center rounded-lg bg-gray-900 px-2.5 text-[11px] font-semibold text-white hover:bg-gray-800 dark:bg-white dark:text-gray-900 dark:hover:bg-gray-200"
                                                    title="Copy keterangan cetak"
                                                >
                                                    Copy
                                                </button>
                                            </div>
                                        </div>

                                        <div class="flex items-end justify-end gap-1 xl:col-span-2 2xl:col-span-2">
                                            <button
                                                type="button"
                                                @click="duplicateItem(index)"
                                                class="inline-flex items-center justify-center rounded-lg bg-gray-100 p-2 text-gray-700 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
                                                title="Duplikat (Ctrl+D)"
                                            >
                                                <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                                                          d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/>
                                                </svg>
                                            </button>

                                            <button
                                                type="button"
                                                @click="removeItem(index)"
                                                x-show="items.length > 1"
                                                class="inline-flex items-center justify-center rounded-lg bg-gray-100 p-2 text-gray-700 hover:bg-red-50 hover:text-red-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-red-500/10 dark:hover:text-red-400"
                                                title="Hapus (Ctrl+Backspace)"
                                                style="display:none;"
                                            >
                                                <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
                                                </svg>
                                            </button>
                                        </div>
                                    </div>
                                </div>
                            </template>
                        </div>

                        <button
                            type="button"
                            @click="addItem(); focusNewRow()"
                            class="w-full mt-3 inline-flex items-center justify-center gap-2 rounded-xl border-2 border-dashed border-gray-300 bg-gray-50 py-2.5 text-sm font-semibold text-gray-800 hover:bg-gray-100 dark:border-gray-700 dark:bg-gray-900/30 dark:text-gray-100 dark:hover:bg-gray-900/50"
                        >
                            <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
                            </svg>
                            Tambah Item
                        </button>
                    </div>

                    <div class="flex items-center justify-between pt-5 border-t border-gray-200 dark:border-gray-700">
                        <div>
                            <span class="text-sm text-gray-500 dark:text-gray-400">Grand Total</span>
                            <span class="ml-2 text-2xl font-bold text-gray-900 dark:text-white" x-text="formatRupiah(grandTotal)"></span>
                        </div>

                        <div class="flex gap-3">
                            <a
                                href="{{ route('orders.index') }}"
                                class="h-11 inline-flex items-center justify-center rounded-lg bg-gray-100 px-5 text-sm font-semibold text-gray-800 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
                            >
                                Batal
                            </a>

                            <button
                                type="submit"
                                :disabled="isSubmitting"
                                class="h-11 inline-flex items-center justify-center rounded-lg bg-gray-900 px-6 text-sm font-semibold text-white shadow-sm hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-60 dark:bg-white dark:text-gray-900 dark:hover:bg-gray-200"
                            >
                                <span x-show="!isSubmitting">Simpan</span>
                                <span x-show="isSubmitting" style="display:none;">Menyimpan...</span>
                            </button>
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>


    <div x-data="{
        isOpen: false,
        name: '',
        contact_person: '',
        phone: '',
        npwp: '',
        email: '',
        member_type: 'umum',
        isLoading: false,
        errors: {},

        init() {
            window.addEventListener('open-customer-modal', () => {
                this.isOpen = true;
                this.$nextTick(() => document.querySelector('[name=new_customer_name]')?.focus());
            });
        },

        close() {
            this.isOpen = false;
            this.name = '';
            this.contact_person = '';
            this.phone = '';
            this.npwp = '';
            this.email = '';
            this.member_type = 'umum';
            this.errors = {};
        },

        async submit() {
            this.isLoading = true;
            this.errors = {};

            try {
                const response = await fetch('{{ route('customers.store') }}', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'X-CSRF-TOKEN': '{{ csrf_token() }}',
                        'Accept': 'application/json'
                    },
                    body: JSON.stringify({
                        name: this.name,
                        member_type: this.member_type,
                        contact_person: this.contact_person,
                        phone: this.phone,
                        npwp: this.npwp,
                        email: this.email
                    })
                });

                const data = await response.json();

                if (response.ok) {
                    const customer = data.customer || data.data || data;
                    window.dispatchEvent(new CustomEvent('customer-added', { detail: customer }));
                    this.close();
                } else {
                    this.errors = data.errors || { name: ['Gagal menyimpan Nama Pemesan'] };
                }
            } catch (e) {
                this.errors = { name: ['Terjadi kesalahan'] };
            } finally {
                this.isLoading = false;
            }
        }
    }" x-show="isOpen" x-cloak class="fixed inset-0 z-50 flex items-center justify-center" @keydown.escape.window="close()" style="display:none;">
        <div class="fixed inset-0 bg-black/50" @click="close()"></div>

        <div class="relative mx-4 w-full max-w-2xl rounded-2xl bg-white p-6 shadow-xl dark:bg-gray-900">
            <div class="mb-5">
                <h3 class="text-lg font-semibold text-gray-900 dark:text-white">Tambah Nama Pemesan</h3>
                <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
                    Lengkapi data pemesan, jenis pelanggan, instansi/perusahaan, kontak, NPWP, dan email.
                </p>
            </div>

            <form @submit.prevent="submit">
                <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
                    <div>
                        <label class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
                            Nama Pemesan <span class="text-red-500">*</span>
                        </label>
                        <input
                            type="text"
                            name="new_customer_name"
                            x-model="name"
                            required
                            placeholder="Contoh: Budi Santoso"
                            class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm dark:border-gray-600 dark:bg-gray-800 dark:text-white"
                        >
                        <p x-show="errors.name" class="mt-1 text-sm text-red-500" x-text="errors.name?.[0]"></p>
                    </div>

                    <div>
                        <label class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
                            Jenis Pelanggan <span class="text-red-500">*</span>
                        </label>
                        <select
                            x-model="member_type"
                            required
                            class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm dark:border-gray-600 dark:bg-gray-800 dark:text-white"
                        >
                            <option value="umum">Umum</option>
                            <option value="studio">Instansi</option>
                        </select>
                        <p x-show="errors.member_type" class="mt-1 text-sm text-red-500" x-text="errors.member_type?.[0]"></p>
                    </div>

                    <div>
                        <label class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
                            Nama Instansi / Perusahaan
                        </label>
                        <input
                            type="text"
                            x-model="contact_person"
                            placeholder="Contoh: PT Global Kreasi Media"
                            class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm dark:border-gray-600 dark:bg-gray-800 dark:text-white"
                        >
                        <p x-show="errors.contact_person" class="mt-1 text-sm text-red-500" x-text="errors.contact_person?.[0]"></p>
                    </div>

                    <div>
                        <label class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
                            Kontak
                        </label>
                        <input
                            type="text"
                            x-model="phone"
                            placeholder="No. HP / WhatsApp (opsional)"
                            class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm dark:border-gray-600 dark:bg-gray-800 dark:text-white"
                        >
                        <p x-show="errors.phone" class="mt-1 text-sm text-red-500" x-text="errors.phone?.[0]"></p>
                    </div>

                    <div>
                        <label class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
                            NPWP
                        </label>
                        <input
                            type="text"
                            x-model="npwp"
                            placeholder="Contoh: 12.345.678.9-012.000"
                            class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm dark:border-gray-600 dark:bg-gray-800 dark:text-white"
                        >
                        <p x-show="errors.npwp" class="mt-1 text-sm text-red-500" x-text="errors.npwp?.[0]"></p>
                    </div>

                    <div>
                        <label class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
                            Email
                        </label>
                        <input
                            type="email"
                            x-model="email"
                            placeholder="email@example.com (opsional)"
                            class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm dark:border-gray-600 dark:bg-gray-800 dark:text-white"
                        >
                        <p x-show="errors.email" class="mt-1 text-sm text-red-500" x-text="errors.email?.[0]"></p>
                    </div>
                </div>

                <div class="mt-5 rounded-xl border border-blue-100 bg-blue-50 p-4 text-sm text-blue-700 dark:border-blue-500/20 dark:bg-blue-500/10 dark:text-blue-300">
                    <strong>Catatan:</strong>
                    Kontak dan email tidak wajib diisi. Data instansi, NPWP, dan jenis pelanggan akan dipakai untuk order, invoice, PPN, dan surat jalan.
                </div>

                <div class="mt-6 flex justify-end gap-3">
                    <button
                        type="button"
                        @click="close()"
                        class="rounded-lg bg-gray-100 px-4 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
                    >
                        Batal
                    </button>

                    <button
                        type="submit"
                        :disabled="isLoading"
                        class="rounded-lg bg-gray-900 px-4 py-2 text-sm font-semibold text-white hover:bg-gray-800 disabled:opacity-50 dark:bg-white dark:text-gray-900 dark:hover:bg-gray-200"
                        x-text="isLoading ? 'Menyimpan...' : 'Simpan'"
                    ></button>
                </div>
            </form>
        </div>
    </div>


{{-- Modal upload preview global: vanilla JS supaya tombol Upload Preview pasti bereaksi --}}
<div id="order-preview-uploader-modal" class="fixed inset-0 z-[99999] hidden items-center justify-center bg-black/70 p-4">
    <div class="relative w-full max-w-xl rounded-3xl border border-gray-200/80 bg-white p-8 text-center shadow-[0_18px_45px_rgba(15,23,42,0.18)] ring-1 ring-black/5 dark:border-gray-700/80 dark:bg-gray-900 dark:shadow-[0_18px_45px_rgba(0,0,0,0.45)] dark:ring-white/10">
        <button type="button" id="order-preview-uploader-close" class="absolute right-4 top-4 flex h-9 w-9 items-center justify-center rounded-full bg-gray-100 text-gray-600 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700">×</button>
        <div class="mb-5 flex justify-center">
            <div class="flex h-14 w-14 items-center justify-center rounded-2xl bg-blue-100 text-3xl font-bold text-blue-600 dark:bg-blue-500/10 dark:text-blue-300">+</div>
        </div>
        <h3 class="text-3xl font-extrabold leading-tight text-gray-900 dark:text-white">Upload Preview</h3>
        <p class="mt-2 text-sm text-gray-500 dark:text-gray-400">Klik Upload Image, drag & drop, atau paste screenshot dengan Ctrl + V.</p>
        <div id="order-preview-uploader-zone" tabindex="0" class="mx-auto mt-7 cursor-pointer rounded-3xl border-2 border-dashed border-blue-200 bg-blue-50/60 p-6 outline-none transition hover:border-blue-400 hover:bg-blue-50 focus:border-blue-500 focus:ring-4 focus:ring-blue-100 dark:border-blue-500/30 dark:bg-blue-500/10">
            <div id="order-preview-uploader-empty">
                <p class="text-base font-bold text-gray-900 dark:text-white">Upload an image preview</p>
                <button
                    type="button"
                    id="order-preview-uploader-button"
                    class="mt-5 inline-flex min-w-[220px] items-center justify-center rounded-full px-8 py-4 text-lg font-bold shadow-lg transition focus:outline-none focus:ring-4 focus:ring-brand-300 dark:focus:ring-brand-500/30 bg-gray-900 text-white hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-60 dark:bg-white dark:text-gray-900 dark:hover:bg-gray-200"
                >
                    Upload Image
                </button>
                <p class="mt-5 text-lg font-semibold text-gray-600 dark:text-gray-300">or drop a file,</p>
                <p class="mt-2 text-sm text-gray-500 dark:text-gray-400">paste image dengan <span class="font-bold text-gray-800 dark:text-gray-200">Ctrl + V</span></p>
            </div>
            <div id="order-preview-uploader-filled" class="hidden">
                <img id="order-preview-uploader-img" src="" class="mx-auto max-h-56 max-w-full rounded-2xl border border-gray-200 object-contain shadow-sm dark:border-gray-700" alt="Preview upload">
                <p class="mt-4 text-sm font-semibold text-gray-700 dark:text-gray-300">Preview sudah masuk. Klik area ini kalau mau ganti gambar.</p>
            </div>
        </div>
        <div class="mt-5 flex justify-center gap-3">
            <button type="button" id="order-preview-uploader-remove" class="hidden rounded-lg border border-red-200 px-4 py-2 text-sm font-semibold text-red-600 hover:bg-red-50 dark:border-red-500/30 dark:hover:bg-red-500/10">Hapus Preview</button>
            <button type="button" id="order-preview-uploader-done" class="rounded-lg bg-gray-900 px-4 py-2 text-sm font-semibold text-white hover:bg-gray-800 dark:bg-white dark:text-gray-900 dark:hover:bg-gray-200">Selesai</button>
        </div>
        <p class="mt-5 text-xs text-gray-400">JPG / PNG / WEBP — otomatis dikompres backend ±50KB.</p>
    </div>
</div>

@endsection

@push('scripts')
<script>
function orderForm() {
    const allProducts = @json($productsForJs);
    const allMaterials = @json($materialsForJs);
    const allCustomers = @json($customersForJs);
    const customersMap = @json($customersMapForJs);

    const normalizeUnit = (u) => {
        const value = (u || 'm2').toString().toLowerCase().trim();
        if (value === 'pcs') return 'lembar';
        if (value === 'm²') return 'm2';
        if (value === 'm') return 'meter';
        return value;
    };

    return {
        items: [],
        allProducts,
        allMaterials,
        allCustomers,
        customersMap,
        customer_id: @json(old('customer_id', '')),
        customerSearch: '',
        customerDropdownOpen: false,
        customerSuccessMessage: '',
        customerMemberType: 'umum',
        previewModal: {
            open: false,
            src: '',
            title: '',
            index: null,
        },
        activeRow: 0,
        errors: {},
        isSubmitting: false,
        is_credit: true,

        createItem() {
            return {
                id: Date.now() + Math.random(),
                product_id: '',
                product_name: '',
                productSearch: '',
                productDropdownOpen: false,

                material_id: '',
                material_name: '',
                materialSearch: '',
                materialDropdownOpen: false,

                file_name: '',
                preview_image_url: '',
                preview_image_name: '',
                size_description: '',
                size_value: 0,
                size_unit: 'm2',
                qty: 1,
                sisi: 1,
                base_price: 0,
                manual_price: 0,
                system_subtotal: 0,
                minimum_order_applied: false,
                finishing_note: '',
                subtotal: 0,

                availableMaterials: this.getSelectableMaterialsForProduct(null),
                loadingMaterials: false,
            };
        },

        addItem() {
            this.items.push(this.createItem());
            this.activeRow = this.items.length - 1;
        },

        removeItem(index) {
            if (this.items.length > 1) {
                this.items.splice(index, 1);
                this.activeRow = Math.min(this.activeRow, this.items.length - 1);
            }
        },

        duplicateItem(index) {
            const item = this.items[index];

            const newItem = {
                ...item,
                id: Date.now() + Math.random(),
                productSearch: '',
                materialSearch: '',
                productDropdownOpen: false,
                materialDropdownOpen: false,
                loadingMaterials: false,
                availableMaterials: this.getSelectableMaterialsForProduct(item.product_id, item.material_id),
            };

            this.items.splice(index + 1, 0, newItem);
            this.activeRow = index + 1;

            this.$nextTick(() => this.focusField('product', index + 1));
        },

        get selectedCustomer() {
            return this.allCustomers.find(c => String(c.id) === String(this.customer_id)) || null;
        },

        get selectedCustomerName() {
            return this.selectedCustomer?.name || '';
        },

        get filteredCustomers() {
            const search = (this.customerSearch || '').toLowerCase().trim();

            if (!search) {
                return this.selectedCustomer ? [this.selectedCustomer] : [];
            }

            if (search.length < 2) {
                return [];
            }

            return this.allCustomers
                .filter(customer => {
                    return (customer.name || '').toLowerCase().includes(search)
                        || (customer.contact_person || '').toLowerCase().includes(search)
                        || (customer.phone || '').toLowerCase().includes(search)
                        || (customer.npwp || '').toLowerCase().includes(search)
                        || (customer.email || '').toLowerCase().includes(search)
                        || (customer.member_type || '').toLowerCase().includes(search);
                })
                .slice(0, 20);
        },

        normalizeCustomerPayload(payload) {
            const customer = payload?.customer || payload?.data || payload || {};

            return {
                id: customer.id ?? customer.customer_id ?? customer.value ?? '',
                name: customer.name ?? customer.customer_name ?? customer.label ?? '',
                phone: customer.phone ?? '',
                contact_person: customer.contact_person ?? '',
                npwp: customer.npwp ?? '',
                email: customer.email ?? '',
                member_type: customer.member_type ?? 'umum',
            };
        },

        selectCustomer(customer) {
            if (!customer?.id) return;

            this.customer_id = String(customer.id);
            this.customerMemberType = customer.member_type || this.customersMap[this.customer_id] || 'umum';
            this.customerDropdownOpen = false;
            this.customerSearch = '';
            this.customerSuccessMessage = '';
            this.clearError('customer_id');

            this.items.forEach((_, index) => {
                this.lookupPrice(index);
                this.calculateSubtotal(index);
            });
        },

        selectFirstCustomer() {
            if (this.filteredCustomers.length > 0) {
                this.selectCustomer(this.filteredCustomers[0]);
            }
        },

        addCustomerToDropdown(payload) {
            const customer = this.normalizeCustomerPayload(payload);

            if (!customer.id || !customer.name) {
                this.customerSuccessMessage = '';
                alert('Nama Pemesan berhasil disimpan, tapi response belum mengirim id/nama customer. Pastikan controller mengembalikan JSON customer.');
                return;
            }

            const id = String(customer.id);
            const existingIndex = this.allCustomers.findIndex(c => String(c.id) === id);

            if (existingIndex >= 0) {
                this.allCustomers.splice(existingIndex, 1, { ...this.allCustomers[existingIndex], ...customer, id });
            } else {
                this.allCustomers.push({ ...customer, id });
            }

            this.customersMap[id] = customer.member_type || 'umum';
            this.selectCustomer({ ...customer, id });
            this.customerSuccessMessage = `Nama Pemesan ${customer.name} berhasil ditambahkan dan dipilih.`;

            window.setTimeout(() => {
                if (this.customer_id === id) this.customerSuccessMessage = '';
            }, 3500);
        },

        syncCustomerFromDom() {
            return String(this.customer_id || '');
        },

        updateCustomer(customerId) {
            const id = String(customerId || '');
            const customer = this.allCustomers.find(c => String(c.id) === id);

            if (customer) {
                this.selectCustomer(customer);
                return;
            }

            this.customer_id = id;
            this.customerMemberType = this.customersMap[id] || 'umum';
            this.clearError('customer_id');

            this.items.forEach((_, index) => {
                this.lookupPrice(index);
                this.calculateSubtotal(index);
            });
        },

        getMaterialById(materialId) {
            return this.allMaterials.find(m => String(m.id) === String(materialId)) || null;
        },

        getCurrentMaterial(index) {
            const item = this.items[index];
            return (item.availableMaterials || []).find(m => String(m.id) === String(item.material_id)) || this.getMaterialById(item.material_id);
        },

        materialOptionLabel(material) {
            if (!material) return '-';

            let label = material.is_custom ? `${material.name} • Custom` : material.name;

            if (material.available_for_order === false) {
                label += ` • ${material.availability_message || 'Stok 0'}`;
            }

            return label;
        },

        getSelectableMaterialsForProduct(productId, currentMaterialId = null) {
            const forcedId = currentMaterialId ? String(currentMaterialId) : null;

            const baseMaterials = (this.allMaterials || []).filter(m => {
                if (forcedId && String(m.id) === forcedId) {
                    return true;
                }

                return true;
            });

            if (!productId) {
                return baseMaterials;
            }

            const product = this.allProducts.find(p => String(p.id) === String(productId));

            if (!product || !Array.isArray(product.material_ids) || product.material_ids.length === 0) {
                return baseMaterials;
            }

            const allowedIds = product.material_ids.map(id => String(id));

            return baseMaterials.filter(m => {
                if (forcedId && String(m.id) === forcedId) {
                    return true;
                }

                return allowedIds.includes(String(m.id)) || Boolean(m.is_custom);
            });
        },

        updateProduct(index) {
            const item = this.items[index];

            item.material_id = '';
            item.material_name = '';
            item.materialSearch = '';
            item.base_price = 0;
            item.size_description = '';
            item.size_value = 0;

            this.clearError(`items.${index}.product_id`);
            this.clearError(`items.${index}.material_id`);
            this.clearError(`items.${index}.size`);

            item.availableMaterials = this.getSelectableMaterialsForProduct(item.product_id);

            this.calculateSubtotal(index);
        },

        updateMaterial(index) {
            const item = this.items[index];
            const mat = this.getCurrentMaterial(index);

            if (mat) {
                item.material_name = mat.name || '';
                item.size_unit = normalizeUnit(mat.unit);
            } else {
                item.material_name = '';
                item.size_unit = 'm2';
            }

            this.handleUnitChange(index);
            this.lookupPrice(index);
            this.calculateSubtotal(index);
            this.clearError(`items.${index}.material_id`);
        },

        handleUnitChange(index) {
            const item = this.items[index];
            item.size_unit = normalizeUnit(item.size_unit);

            if (item.size_unit === 'm2') {
                item.sisi = 1;
                if (!item.size_description) item.size_value = 0;
            } else if (item.size_unit === 'meter') {
                if (!item.size_description) item.size_value = 0;
            } else {
                item.size_description = '';
                item.size_value = 1;
            }

            this.clearError(`items.${index}.size`);
            this.parseSize(index);
            this.calculateSubtotal(index);
        },

        lookupPrice(index) {
            const item = this.items[index];

            if (!item.material_id) {
                item.base_price = 0;
                return;
            }

            const mat = this.getCurrentMaterial(index);

            if (!mat) {
                item.base_price = 0;
                return;
            }

            const prices = Array.isArray(mat.prices) ? mat.prices : [];
            const qty = parseFloat(item.qty) || 1;
            const sisi = item.size_unit === 'm2' ? 1 : (parseInt(item.sisi) || 1);
            const memberType = this.customerMemberType || 'umum';

            const matchedRule = prices.find(p => {
                const minQty = parseFloat(p.min_qty) || 1;
                const maxQty = (p.max_qty === null || p.max_qty === '' || typeof p.max_qty === 'undefined')
                    ? null
                    : parseFloat(p.max_qty);

                if ((p.member_type || 'umum') !== memberType) return false;
                if ((parseInt(p.sisi) || 1) !== sisi) return false;
                if (qty < minQty) return false;
                if (maxQty !== null && qty > maxQty) return false;

                return true;
            });

            if (matchedRule) {
                item.base_price = parseFloat(matchedRule.price) || 0;
            } else {
                item.base_price = parseFloat(mat.base_price) || 0;
            }
        },

        clearError(field) {
            if (this.errors[field]) delete this.errors[field];
        },

        filteredProducts(index) {
            const search = (this.items[index].productSearch || '').toLowerCase();
            if (!search) return this.allProducts;
            return this.allProducts.filter(p => p.name.toLowerCase().includes(search));
        },

        filteredMaterials(index) {
            const item = this.items[index];
            const search = (item.materialSearch || '').toLowerCase();

            const selectedId = item.material_id ? String(item.material_id) : null;

            const materials = (item.availableMaterials || []).filter(m => {
                if (selectedId && String(m.id) === selectedId) {
                    return true;
                }

                return true;
            });

            if (!search) return materials;

            return materials.filter(m => (m.name || '').toLowerCase().includes(search));
        },

        selectProduct(index, product) {
            const item = this.items[index];
            item.product_id = product.id;
            item.product_name = product.name;
            item.productSearch = '';
            item.productDropdownOpen = false;

            this.updateProduct(index);
            this.$nextTick(() => this.focusField('material', index));
        },

        selectMaterial(index, material) {
            const item = this.items[index];
            item.material_id = material.id;
            item.material_name = material.name || '';
            item.materialSearch = '';
            item.materialDropdownOpen = false;

            this.updateMaterial(index);
            this.$nextTick(() => this.focusField('filename', index));
        },

        selectFirstProduct(index) {
            const filtered = this.filteredProducts(index);
            if (filtered.length > 0) this.selectProduct(index, filtered[0]);
        },

        selectFirstMaterial(index) {
            const filtered = this.filteredMaterials(index);
            if (filtered.length > 0) this.selectMaterial(index, filtered[0]);
        },

        parseDimensions(text) {
            const clean = (text || '')
                .toString()
                .trim()
                .toLowerCase()
                .replace(/\s+/g, '')
                .replaceAll('×', 'x')
                .replaceAll('*', 'x');

            const match = clean.match(/^(\d+(?:[.,]\d+)?)x(\d+(?:[.,]\d+)?)(cm|m)?$/i);
            if (!match) return null;

            const a = parseFloat(match[1].replace(',', '.'));
            const b = parseFloat(match[2].replace(',', '.'));
            const suffix = match[3] || '';
            let unit = 'm';

            if (suffix === 'cm') {
                unit = 'cm';
            } else if (suffix === 'm') {
                unit = 'm';
            } else {
                unit = (a >= 10 && b >= 10) ? 'cm' : 'm';
            }

            return { a, b, unit };
        },

        parseAreaM2(sizeDescription, fallback = 0) {
            const dims = this.parseDimensions(sizeDescription);

            if (!dims) {
                return Math.max(parseFloat(fallback) || 0, 0);
            }

            if (dims.unit === 'cm') {
                return (dims.a * dims.b) / 10000;
            }

            return dims.a * dims.b;
        },

        parseLinearMeter(sizeDescription, material, fallback = 0) {
            const dims = this.parseDimensions(sizeDescription);

            if (!dims) {
                return Math.max(parseFloat(fallback) || 0, 0);
            }

            const aCm = dims.unit === 'cm' ? dims.a : (dims.a * 100);
            const bCm = dims.unit === 'cm' ? dims.b : (dims.b * 100);

            const rollWidthCm = parseFloat(material?.roll_width_cm || 0);
            const allowRotation = material?.allow_rotation !== false;

            if (rollWidthCm > 0) {
                const candidates = [];

                if (aCm <= rollWidthCm) {
                    candidates.push(bCm);
                }

                if (allowRotation && bCm <= rollWidthCm) {
                    candidates.push(aCm);
                }

                if (candidates.length > 0) {
                    return Math.min(...candidates) / 100;
                }

                return Math.max(aCm, bCm) / 100;
            }

            return Math.min(aCm, bCm) / 100;
        },

        round4(value) {
            return Math.round((parseFloat(value) || 0) * 10000) / 10000;
        },

        parseSize(index) {
            const item = this.items[index];
            const material = this.getCurrentMaterial(index);

            this.clearError(`items.${index}.size`);

            if (!item.size_description) {
                if (item.size_unit === 'm2' || item.size_unit === 'meter') {
                    item.size_value = 0;
                }
                this.calculateSubtotal(index);
                return;
            }

            if (item.size_unit === 'm2') {
                item.size_value = this.round4(this.parseAreaM2(item.size_description, item.size_value));
            } else if (item.size_unit === 'meter') {
                item.size_value = this.round4(this.parseLinearMeter(item.size_description, material, item.size_value));
            }

            this.calculateSubtotal(index);
        },

        calculateSubtotal(index) {
            const item = this.items[index];

            const qty = parseFloat(item.qty) || 0;
            const base = parseFloat(item.base_price) || 0;
            const manualPrice = parseFloat(item.manual_price) || 0;
            const unit = String(item.size_unit || item.unit || 'lembar').toLowerCase().trim();
            const isMeterBased = ['m2', 'm²', 'meter2', 'meter persegi', 'per meter persegi', 'meter', 'm', 'per meter'].includes(unit);

            let sizeFactor = 1;

            if (unit === 'm2' || unit === 'm²' || unit === 'meter2' || unit === 'meter persegi' || unit === 'per meter persegi' || unit === 'meter' || unit === 'm' || unit === 'per meter') {
                sizeFactor = parseFloat(item.size_value) || 0;
            }

            const systemSubtotal = base * sizeFactor * qty;
            item.system_subtotal = systemSubtotal;

            // Harga manual adalah nilai final dari user, jangan dipaksa minimal.
            if (manualPrice > 0) {
                item.subtotal = manualPrice;
                item.minimum_order_applied = false;
                return;
            }

            // Minimal Rp10.000 + pembulatan Rp1.000 hanya untuk meter / m².
            // PCS/lembar/unit tetap harga asli.
            if (isMeterBased) {
                if (systemSubtotal > 0 && systemSubtotal < 10000) {
                    item.subtotal = this.roundPriceUp(10000);
                    item.minimum_order_applied = true;
                    return;
                }

                item.subtotal = this.roundPriceUp(systemSubtotal);
                item.minimum_order_applied = false;
                return;
            }

            item.subtotal = systemSubtotal;
            item.minimum_order_applied = false;
        },

        roundPriceUp(amount) {
            const roundTo = 1000;
            amount = parseFloat(amount) || 0;

            if (amount <= 0) {
                return 0;
            }

            if (roundTo <= 1) {
                return Math.ceil(amount);
            }

            return Math.ceil(amount / roundTo) * roundTo;
        },

        get grandTotal() {
            return this.items.reduce((sum, item) => sum + (parseFloat(item.subtotal) || 0), 0);
        },

        buildPrintDescription(item) {
            const parts = [];

            if (item.file_name) {
                parts.push(`File: ${item.file_name}`);
            }

            if (item.material_name) {
                parts.push(`Bahan: ${item.material_name}`);
            }

            if (item.size_unit === 'm2' || item.size_unit === 'meter') {
                const ukuran = item.size_description || '-';
                const nilai = parseFloat(item.size_value || 0) > 0 ? this.formatDecimal(item.size_value) : '-';
                const satuan = item.size_unit === 'm2' ? 'm²' : 'meter';
                parts.push(`Ukuran: ${ukuran} (${nilai} ${satuan})`);
            } else {
                parts.push(`Ukuran: lembar`);
            }

            parts.push(`Qty: ${item.qty || 0}`);

            if (item.size_unit !== 'm2') {
                parts.push(`Sisi: ${item.sisi || 1}`);
            }

            if (item.finishing_note) {
                parts.push(`Finishing/Ket: ${item.finishing_note}`);
            }

            return parts.join(' | ');
        },

        async copyPrintDescription(index) {
            const item = this.items[index];

            if (!item) return;

            const text = this.buildPrintDescription(item);

            if (!text) return;

            try {
                await navigator.clipboard.writeText(text);
                alert('Keterangan cetak berhasil dicopy.');
            } catch (e) {
                const temp = document.createElement('textarea');
                temp.value = text;
                temp.setAttribute('readonly', '');
                temp.style.position = 'fixed';
                temp.style.left = '-9999px';
                document.body.appendChild(temp);
                temp.select();
                document.execCommand('copy');
                document.body.removeChild(temp);
                alert('Keterangan cetak berhasil dicopy.');
            }
        },

        formatNumber(v) {
            return new Intl.NumberFormat('id-ID').format(v || 0);
        },

        formatRupiah(v) {
            return 'Rp ' + this.formatNumber(v);
        },

        formatDecimal(v) {
            const num = parseFloat(v) || 0;
            return num.toLocaleString('id-ID', {
                minimumFractionDigits: 0,
                maximumFractionDigits: 4
            });
        },

        prepareSubmit(e) {
            if (this.isSubmitting) {
                e.preventDefault();
                return;
            }

            this.closeAllDropdowns();
            this.errors = {};
            let invalid = false;

            const customerId = this.syncCustomerFromDom();
            if (!customerId) {
                this.errors.customer_id = 'Nama Pemesan wajib dipilih!';
                invalid = true;
            }

            for (let i = 0; i < this.items.length; i++) {
                const item = this.items[i];

                this.parseSize(i);
                this.calculateSubtotal(i);

                if (!item.product_id) {
                    this.errors[`items.${i}.product_id`] = 'Produk wajib dipilih!';
                    invalid = true;
                }

                if (!item.material_id) {
                    this.errors[`items.${i}.material_id`] = 'Bahan wajib dipilih!';
                    invalid = true;
                } else {
                    const material = this.getCurrentMaterial(i);

                    if (material && material.available_for_order === false) {
                        this.errors[`items.${i}.material_id`] = material.availability_message || 'Stok 0, order tidak bisa dilanjutkan.';
                        invalid = true;
                    }
                }

                if (!item.file_name) {
                    this.errors[`items.${i}.file_name`] = 'Nama File wajib diisi!';
                    invalid = true;
                }

                if (item.size_unit === 'm2' || item.size_unit === 'meter') {
                    if (!item.size_description) {
                        this.errors[`items.${i}.size`] = 'Ukuran wajib diisi!';
                        invalid = true;
                    }

                    if (!item.size_value || item.size_value <= 0) {
                        this.errors[`items.${i}.size`] = item.size_unit === 'm2'
                            ? 'Nilai m² wajib diisi!'
                            : 'Nilai meter wajib terbentuk!';
                        invalid = true;
                    }
                }

                if (!item.qty || item.qty <= 0) {
                    this.errors[`items.${i}.qty`] = 'Qty harus > 0!';
                    invalid = true;
                }
            }

            if (invalid) {
                e.preventDefault();
                this.isSubmitting = false;
                this.focusFirstError();
                window.scrollTo({ top: 0, behavior: 'smooth' });
                return;
            }

            this.isSubmitting = true;
        },

        closeAllDropdowns() {
            this.items.forEach(item => {
                item.productDropdownOpen = false;
                item.materialDropdownOpen = false;
                item.productSearch = '';
                item.materialSearch = '';
            });
        },

        handleFormEnter(e) {
            const tag = (e.target?.tagName || '').toLowerCase();
            const type = (e.target?.type || '').toLowerCase();

            if (tag === 'textarea') return;
            if (type === 'submit' || type === 'button') return;
            if (e.ctrlKey || e.metaKey) return;

            e.preventDefault();
        },

        focusFirstError() {
            const firstKey = Object.keys(this.errors)[0];
            if (!firstKey) return;

            const rowMatch = firstKey.match(/^items\.(\d+)\./);
            if (rowMatch) {
                const rowIndex = parseInt(rowMatch[1]);
                this.activeRow = rowIndex;

                const fieldMap = {
                    product_id: 'product',
                    material_id: 'material',
                    file_name: 'filename',
                    size: 'size',
                    qty: 'qty',
                };

                const fieldName = firstKey.split('.').pop();
                this.$nextTick(() => this.focusField(fieldMap[fieldName] || 'product', rowIndex));
                return;
            }

            if (firstKey === 'customer_id') {
                this.customerDropdownOpen = true;
                this.$nextTick(() => document.getElementById('customer-search')?.focus());
            }
        },

        focusField(fieldType, rowIndex) {
            const field = document.querySelector(`[data-field="${fieldType}-${rowIndex}"]`);
            if (field) field.focus();
        },

        focusNextField(currentEl, nextFieldType) {
            const currentField = currentEl.getAttribute('data-field');
            if (!currentField) return;

            const rowIndex = parseInt(currentField.split('-').pop());
            this.$nextTick(() => this.focusField(nextFieldType, rowIndex));
        },

        focusAfterUnit(index) {
            const item = this.items[index];
            if (item.size_unit === 'm2' || item.size_unit === 'meter') {
                this.focusField('size', index);
            } else {
                this.focusField('qty', index);
            }
        },

        focusNewRow() {
            this.$nextTick(() => this.focusField('product', this.items.length - 1));
        },

        handlePriceEnter(index) {
            if (index === this.items.length - 1) {
                this.addItem();
                this.focusNewRow();
            } else {
                this.activeRow = index + 1;
                this.focusField('product', index + 1);
            }
        },

        handleGlobalKeydown(e) {
            if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
                e.preventDefault();
                if (!this.isSubmitting) {
                    this.closeAllDropdowns();
                    document.getElementById('form-order')?.requestSubmit();
                }
                return;
            }

            if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'n') {
                e.preventDefault();
                window.dispatchEvent(new CustomEvent('open-customer-modal'));
                return;
            }

            if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'd') {
                e.preventDefault();
                this.duplicateItem(this.activeRow);
                return;
            }

            if ((e.ctrlKey || e.metaKey) && e.key === 'Backspace') {
                e.preventDefault();
                if (this.items.length > 1) this.removeItem(this.activeRow);
                return;
            }

            if (e.key === 'ArrowUp' && e.altKey) {
                e.preventDefault();
                if (this.activeRow > 0) {
                    this.activeRow--;
                    this.focusField('product', this.activeRow);
                }
                return;
            }

            if (e.key === 'ArrowDown' && e.altKey) {
                e.preventDefault();
                if (this.activeRow < this.items.length - 1) {
                    this.activeRow++;
                    this.focusField('product', this.activeRow);
                }
                return;
            }
        },

        init() {
            this.items = [this.createItem()];

            this.$nextTick(() => {
                const customerId = this.syncCustomerFromDom();
                if (customerId) this.updateCustomer(customerId);
            });

            window.addEventListener('customer-added', (event) => {
                this.addCustomerToDropdown(event.detail);
            });
        }
    };
}

/* Upload Preview popup global - tidak bergantung pada method Alpine lama */
(function () {
    let currentIndex = null;
    let objectUrl = null;

    function modal() { return document.getElementById('order-preview-uploader-modal'); }
    function zone() { return document.getElementById('order-preview-uploader-zone'); }
    function emptyBox() { return document.getElementById('order-preview-uploader-empty'); }
    function filledBox() { return document.getElementById('order-preview-uploader-filled'); }
    function imgEl() { return document.getElementById('order-preview-uploader-img'); }
    function removeBtn() { return document.getElementById('order-preview-uploader-remove'); }

    function getAlpineData() {
        const roots = Array.from(document.querySelectorAll('[x-data]'));
        const root = roots.find(el => (el.getAttribute('x-data') || '').includes('orderForm') || (el.getAttribute('x-data') || '').includes('orderEditForm'));
        return root && window.Alpine ? window.Alpine.$data(root) : null;
    }

    function getInput(index) { return document.getElementById('preview-input-' + index); }

    function syncPreview(url) {
        const data = getAlpineData();
        if (data && data.items && data.items[currentIndex]) {
            data.items[currentIndex].preview_image_url = url || '';
            data.items[currentIndex].preview_image_name = url ? 'preview-image' : '';
        }
        if (url) {
            imgEl().src = url;
            emptyBox().classList.add('hidden');
            filledBox().classList.remove('hidden');
            removeBtn().classList.remove('hidden');
        } else {
            imgEl().removeAttribute('src');
            filledBox().classList.add('hidden');
            emptyBox().classList.remove('hidden');
            removeBtn().classList.add('hidden');
        }
    }

    function currentPreviewUrl(index) {
        const data = getAlpineData();
        return data && data.items && data.items[index] ? (data.items[index].preview_image_url || '') : '';
    }

    function assignFile(file) {
        if (currentIndex === null || !file || !file.type || !file.type.startsWith('image/')) return;
        const input = getInput(currentIndex);
        if (!input) {
            alert('Input upload preview tidak ditemukan. Pastikan file blade sudah terpasang penuh.');
            return;
        }
        const transfer = new DataTransfer();
        transfer.items.add(file);
        input.files = transfer.files;
        input.dispatchEvent(new Event('change', { bubbles: true }));
        if (objectUrl) URL.revokeObjectURL(objectUrl);
        objectUrl = URL.createObjectURL(file);
        syncPreview(objectUrl);
    }

    window.handleOrderPreviewFileInput = function (event, index) {
        currentIndex = index;
        const file = event && event.target && event.target.files ? event.target.files[0] : null;
        if (!file) return;
        if (objectUrl) URL.revokeObjectURL(objectUrl);
        objectUrl = URL.createObjectURL(file);
        syncPreview(objectUrl);
    };

    window.openOrderPreviewUploader = function (index) {
        currentIndex = index;
        const m = modal();
        if (!m) return;
        m.classList.remove('hidden');
        m.classList.add('flex');
        syncPreview(currentPreviewUrl(index));
        setTimeout(() => zone()?.focus(), 50);
    };

    window.closeOrderPreviewUploader = function () {
        const m = modal();
        if (!m) return;
        m.classList.add('hidden');
        m.classList.remove('flex');
    };

    document.addEventListener('DOMContentLoaded', function () {
        const choose = function (e) {
            e.preventDefault();
            e.stopPropagation();
            if (currentIndex === null) return;
            getInput(currentIndex)?.click();
        };
        document.getElementById('order-preview-uploader-button')?.addEventListener('click', choose);
        zone()?.addEventListener('click', choose);
        document.getElementById('order-preview-uploader-close')?.addEventListener('click', window.closeOrderPreviewUploader);
        document.getElementById('order-preview-uploader-done')?.addEventListener('click', window.closeOrderPreviewUploader);
        modal()?.addEventListener('click', function (e) { if (e.target === modal()) window.closeOrderPreviewUploader(); });
        zone()?.addEventListener('dragover', function (e) { e.preventDefault(); });
        zone()?.addEventListener('drop', function (e) { e.preventDefault(); assignFile(e.dataTransfer.files[0]); });
        zone()?.addEventListener('paste', function (e) {
            const items = Array.from((e.clipboardData || {}).items || []);
            const imageItem = items.find(item => item.type && item.type.startsWith('image/'));
            if (imageItem) assignFile(imageItem.getAsFile());
        });
        document.addEventListener('keydown', function (e) {
            if (e.key === 'Escape' && !modal()?.classList.contains('hidden')) window.closeOrderPreviewUploader();
        });
        removeBtn()?.addEventListener('click', function (e) {
            e.preventDefault();
            e.stopPropagation();
            const input = getInput(currentIndex);
            if (input) input.value = '';
            syncPreview('');
        });
    });
})();

</script>
@endpush

@push('styles')
<style>
[x-cloak]{display:none!important;}
.marquee-track{
    width:max-content;
    animation: order-input-marquee 28s linear infinite;
}
.marquee-track:hover{
    animation-play-state: paused;
}
@keyframes order-input-marquee{
    0%{ transform: translateX(0); }
    100%{ transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce){
    .marquee-track{ animation: none; }
}
#items-container input,
#items-container select,
#items-container button {
    scroll-margin-top: 110px;
}
@media (max-width: 640px) {
    #items-container [data-row] {
        padding: 1rem;
    }
}
</style>
@endpush
