/**
 * Pacific Logistics · Data Import (Vue 3 Options API + SheetJS)
 *
 * Flow:
 *   1. User picks entity (trucks/drivers/customers)
 *   2. Optionally downloads generated template (headers only, xlsx)
 *   3. Uploads a filled .xlsx → SheetJS parses to array of objects
 *   4. Preview table shown with row-level validation flags
 *   5. Click "Import N rows" → POST rows[] as JSON via FormData → server
 *      validates + inserts + returns per-row results
 *   6. Results table shown; user can retry failed rows after fixing them in
 *      Excel and re-uploading
 *
 * No file bytes leave the browser until Vue POSTs the parsed JSON — SheetJS
 * runs entirely client-side.
 */
(function () {
    const boot = window.__pacificImport || {};

    Vue.createApp({
        data() {
            return {
                proot:    boot.proot,
                csrf:     boot.csrf,
                entity:   boot.entity,             // 'trucks' | 'drivers' | 'customers'
                columns:  boot.columns || [],
                fileName: '',
                rows:     [],                       // parsed rows (array of objects)
                importing: false,
                result:   null,                     // POST result once submitted
                error:    '',
            };
        },
        computed: {
            requiredCols() { return this.columns.filter(c => c.label.endsWith('*')); },
            previewRows()  { return this.rows.slice(0, 20); },
            hasMoreRows()  { return this.rows.length > 20; },
            entityLabel()  {
                return { trucks: 'trucks', drivers: 'drivers', customers: 'customers' }[this.entity] || this.entity;
            },
            postEndpoint() {
                return this.proot + 'Import/' + ({
                    trucks:    'trucksAj',
                    drivers:   'driversAj',
                    customers: 'customersAj'
                }[this.entity]);
            },
        },
        methods: {
            /* ── Template download (headers-only workbook, generated on the fly) ── */
            downloadTemplate() {
                if (typeof XLSX === 'undefined') { alert('SheetJS not loaded.'); return; }
                const headers = this.columns.map(c => c.label.replace(/\*$/, ''));
                const sample  = this.columns.map(c => c.sample);
                const aoa = [headers, sample];      // headers row + one sample data row
                const ws  = XLSX.utils.aoa_to_sheet(aoa);
                // Column widths for readability
                ws['!cols'] = headers.map(h => ({ wch: Math.max(14, h.length + 2) }));
                const wb  = XLSX.utils.book_new();
                XLSX.utils.book_append_sheet(wb, ws, this.entity);
                XLSX.writeFile(wb, 'pacific_' + this.entity + '_template.xlsx');
            },

            /* ── File selection → parse client-side with SheetJS ── */
            onFile(e) {
                const f = e.target.files[0];
                if (!f) return;
                this.error = '';
                this.result = null;
                this.fileName = f.name;

                const reader = new FileReader();
                reader.onload = (ev) => {
                    try {
                        const wb = XLSX.read(new Uint8Array(ev.target.result), { type: 'array' });
                        const first = wb.SheetNames[0];
                        const ws = wb.Sheets[first];
                        // Read as objects using the header row. defval: '' avoids undefined gaps.
                        const raw = XLSX.utils.sheet_to_json(ws, { defval: '', raw: false });
                        // Re-key each row from the label-based header to our internal field names
                        this.rows = raw.map(r => this.mapRow(r));
                    } catch (err) {
                        this.error = 'Failed to parse file: ' + err.message;
                    }
                };
                reader.readAsArrayBuffer(f);
            },

            /**
             * Map a row keyed by user-facing labels (e.g. "Reg No*") back to
             * our internal field names (reg_no). Case-insensitive, ignores
             * trailing '*'.
             */
            mapRow(rawRow) {
                const out = {};
                const norm = (s) => String(s).trim().toLowerCase().replace(/\s*\*\s*$/, '').replace(/[^a-z0-9]+/g, ' ').trim();
                const wantByNorm = {};
                this.columns.forEach(c => { wantByNorm[norm(c.label)] = c.field; });
                for (const [k, v] of Object.entries(rawRow)) {
                    const key = wantByNorm[norm(k)];
                    if (key) out[key] = (v === null || v === undefined) ? '' : String(v).trim();
                }
                return out;
            },

            /** Row-level validation flags for the preview (does not block import). */
            rowIssues(row) {
                const issues = [];
                for (const c of this.requiredCols) {
                    if (!row[c.field]) issues.push('Missing ' + c.label.replace(/\*$/, ''));
                }
                return issues;
            },

            clearFile() {
                this.rows = [];
                this.fileName = '';
                this.result = null;
                this.error = '';
                const el = document.getElementById('importFile');
                if (el) el.value = '';
            },

            async submitImport() {
                if (this.rows.length === 0) return;
                this.importing = true;
                this.error = '';
                this.result = null;
                try {
                    const fd = new FormData();
                    fd.append('csrf_token', this.csrf);
                    fd.append('rows', JSON.stringify(this.rows));
                    const res = await fetch(this.postEndpoint, {
                        method: 'POST',
                        headers: { 'Accept': 'application/json' },
                        credentials: 'same-origin',
                        body: fd
                    });
                    const j = await res.json();
                    if (j.ok) {
                        this.result = j;
                        if (window.rsToast) rsToast.success(j.msg);
                    } else {
                        this.error = j.msg || 'Import failed.';
                    }
                } catch (e) {
                    this.error = 'Network error: ' + e.message;
                } finally {
                    this.importing = false;
                }
            },
        },
    }).mount('#dataImport');
})();
