document.addEventListener('alpine:init', () => {

    Alpine.data('productCardInitializer', () => ({
        code: '',
        copied: false,
        timeout: null,
        copy() {
            $clipboard(this.code);
            this.copied = true;
            clearTimeout(this.timeout);
            this.timeout = setTimeout(() => {
                this.copied = false;
            }, 3000);
        }
    }));

    Alpine.data('shortcutsHeader', () => ({
        // state
        db: null,
        manageOpen: false,
        formOpen: false,
        items: [],
        form: { id: null, title: '', url: '', color: '#0d6efd', order: 0 },

        // utils
        favicon(url) {
            try {
                const u = new URL(url);
                return `https://www.google.com/s2/favicons?sz=32&domain=${u.origin}`;
            } catch { return 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='; }
        },
        validUrl(u) {
            try { const _ = new URL(u); return _.protocol === 'http:' || _.protocol === 'https:'; }
            catch { return false; }
        },

        // lifecycle
        async init() {
            if ('indexedDB' in window) {
                try {
                    this.db = await this.openDB();
                    await this.load();
                    return;
                } catch (e) { console.warn('IndexedDB failed, using localStorage', e); }
            }
            this.db = null;
            this.loadFromLocal();
        },

        // IndexedDB
        openDB() {
            return new Promise((resolve, reject) => {
                const req = indexedDB.open('shortcutsDB', 1);
                req.onupgradeneeded = (ev) => {
                    const db = ev.target.result;
                    if (!db.objectStoreNames.contains('links')) {
                        const store = db.createObjectStore('links', { keyPath: 'id', autoIncrement: true });
                        store.createIndex('order', 'order', { unique: false });
                    }
                };
                req.onsuccess = () => resolve(req.result);
                req.onerror = () => reject(req.error);
            });
        },
        async load() {
            const tx = this.db.transaction('links', 'readonly');
            const store = tx.objectStore('links');
            const index = store.index('order');
            const req = index.getAll();
            this.items = await new Promise((res, rej) => {
                req.onsuccess = () => res(req.result.sort((a, b) => a.order - b.order));
                req.onerror = () => rej(req.error);
            });
        },
        async add(rec) {
            const toAdd = this.toPlain(rec, true); // no id for add
            if (!Number.isFinite(toAdd.order)) {
                toAdd.order = this.items.length ? Math.max(...this.items.map(i => i.order)) + 1 : 0;
            }
            const tx = this.db.transaction('links', 'readwrite');
            const id = await new Promise((res, rej) => {
                const r = tx.objectStore('links').add(toAdd);
                r.onsuccess = () => res(r.result);
                r.onerror = () => rej(r.error);
            });
            toAdd.id = id;
            this.items.push(toAdd);
            this.items.sort((a, b) => a.order - b.order);
        },

        async put(rec) {
            const toPut = this.toPlain(rec, false);
            const tx = this.db.transaction('links', 'readwrite');
            await new Promise((res, rej) => {
                const r = tx.objectStore('links').put(toPut);
                r.onsuccess = () => res();
                r.onerror = () => rej(r.error);
            });
        },
        async delete(id) {
            const tx = this.db.transaction('links', 'readwrite');
            await new Promise((res, rej) => {
                const r = tx.objectStore('links').delete(id);
                r.onsuccess = () => res();
                r.onerror = () => rej(r.error);
            });
        },
        async clearDB() {
            const tx = this.db.transaction('links', 'readwrite');
            await new Promise((res, rej) => {
                const r = tx.objectStore('links').clear();
                r.onsuccess = () => res();
                r.onerror = () => rej(r.error);
            });
        },

        // localStorage fallback
        loadFromLocal() {
            const raw = localStorage.getItem('shortcuts_links') || '[]';
            this.items = JSON.parse(raw).sort((a, b) => a.order - b.order);
        },
        saveToLocal() {
            localStorage.setItem('shortcuts_links', JSON.stringify(this.items));
        },

        // CRUD (uses DB if available)
        openForm(item) {
            this.form = item ? { ...item } : { id: null, title: '', url: '', color: '#0d6efd', order: 0 };
            this.formOpen = true;
        },
        closeForm() { this.formOpen = false; },

        async save() {
            if (!this.form.title.trim()) return alert('Title is required.');
            if (!this.validUrl(this.form.url)) return alert('Please enter a valid URL (http/https).');

            if (this.db) {
                if (this.form.id) {
                    const clean = this.toPlain(this.form, false);
                    await this.put(clean);
                    const i = this.items.findIndex(x => x.id === clean.id);
                    this.items.splice(i, 1, clean);
                } else {
                    const rec = this.toPlain(this.form, true);
                    rec.order = this.items.length ? Math.max(...this.items.map(i => i.order)) + 1 : 0;
                    await this.add(rec); // add() pushes to items
                }
            } else {
                if (this.form.id) {
                    const clean = this.toPlain(this.form, false);
                    const i = this.items.findIndex(x => x.id === clean.id);
                    this.items.splice(i, 1, clean);
                    this.saveToLocal();
                } else {
                    const clean = this.toPlain(this.form, true);
                    clean.id = Date.now();
                    clean.order = this.items.length ? Math.max(...this.items.map(i => i.order)) + 1 : 0;
                    this.items.push(clean);
                    this.saveToLocal();
                }
            }
            this.items.sort((a, b) => a.order - b.order);
            this.closeForm();
        },

        async move(id, delta) {
            const idx = this.items.findIndex(x => x.id === id);
            const j = idx + delta;
            if (j < 0 || j >= this.items.length) return;

            // swap orders
            const a = this.items[idx], b = this.items[j];
            const t = a.order; a.order = b.order; b.order = t;
            this.items.sort((x, y) => x.order - y.order);

            if (this.db) {
                await this.put(this.toPlain(a, false));
                await this.put(this.toPlain(b, false));
            } else {
                this.saveToLocal();
            }
        },
        async remove(id) {
            if (!confirm('Remove this shortcut?')) return;
            if (this.db) { await this.delete(id); }
            this.items = this.items.filter(x => x.id !== id);
            if (!this.db) this.saveToLocal();
            // re-normalize order
            this.items.forEach((it, idx) => it.order = idx);
            if (this.db) for (const it of this.items) await this.put(it); else this.saveToLocal();
        },


        async update(item) {
            if (this.db) await this.put(item); else this.saveToLocal();
        },

        async clearAll() {
            if (this.db) await this.clearDB();
            this.items = [];
            if (!this.db) this.saveToLocal();
        },

        toPlain(obj, forAdd = false) {
            // Build exactly the fields we persist (no proxies/functions/refs)
            const plain = {
                title: String(obj?.title ?? ''),
                url: String(obj?.url ?? ''),
                color: String(obj?.color ?? '#0d6efd'),
                order: Number.isFinite(+obj?.order) ? +obj.order : 0,
            };
            if (!forAdd) plain.id = obj?.id; // keep id on updates only
            return plain;
        }
    }));

});
