Vue.component('patientAttributes', {
    props: ['attributes','routes','initialValues'],

    data() {
        return {
            values: {},
            errors: {},
            loading: false,
            success: false,
            edit: false,
            initialSnapshot: {} // <-- internal snapshot; do NOT mutate the prop
        };
    },

    mounted() {
        this.init();
    },

    watch: {
        initialValues: {
            deep: false,
            immediate: true,
            handler(val) {
                if (!val || typeof val !== 'object') {
                    return;
                }

                // If we're not editing, rehydrate the display state.
                if (!this.edit) {
                    try {
                        this.initialSnapshot = JSON.parse(JSON.stringify(val));
                    } catch (e) {
                        this.initialSnapshot = { ...val };
                    }
                    try {
                        this.values = JSON.parse(JSON.stringify(this.initialSnapshot));
                    } catch (e) {
                        this.values = { ...this.initialSnapshot };
                    }

                    const schemaKeys = (this.attributes && typeof this.attributes === 'object')
                        ? Object.keys(this.attributes)
                        : [];
                    schemaKeys.forEach((key) => {
                        const attribute = this.attributes[key];
                        if (!(key in this.values)) {
                            if (attribute.type === 'checkbox' && attribute.variations) {
                                this.$set(this.values, key, []);
                            } else {
                                this.$set(this.values, key, null);
                            }
                        }
                        if (attribute.type === 'datetime' && !(key + '_time' in this.values)) {
                            this.$set(this.values, key + '_time', null);
                        }
                    });
                    this.setMarkupValues();
                }
            }
        }
    },

    methods: {
        init() {
            const hasInitial =
                this.initialValues !== null &&
                this.initialValues !== undefined &&
                typeof this.initialValues === 'object' &&
                !Array.isArray(this.initialValues);

            // If parent provided initialValues, use them (do NOT mutate the prop!)
            if (hasInitial) {
                try {
                    this.initialSnapshot = JSON.parse(JSON.stringify(this.initialValues));
                } catch (e) {
                    this.initialSnapshot = { ...this.initialValues };
                }
                try {
                    this.values = JSON.parse(JSON.stringify(this.initialSnapshot));
                } catch (e) {
                    this.values = { ...this.initialSnapshot };
                }

                // ensure keys exist for all schema attributes
                const schemaKeys = (this.attributes && typeof this.attributes === 'object')
                    ? Object.keys(this.attributes) : [];
                schemaKeys.forEach((key) => {
                    const attribute = this.attributes[key];
                    if (!(key in this.values)) {
                        if (attribute.type === 'checkbox' && attribute.variations) {
                            this.$set(this.values, key, []);
                        } else {
                            this.$set(this.values, key, null);
                        }
                    }
                    if (attribute.type === 'datetime' && !(key + '_time' in this.values)) {
                        this.$set(this.values, key + '_time', null);
                    }
                });

                this.setMarkupValues();
                return; // skip first AJAX
            }

            // Fallback: load from server
            this.loading = true;
            const vm = this;

            this.$http.post(this.routes['admin-member-attributes-load'], {})
                .then((response) => {
                    let payload = response.data;
                    if (typeof payload === 'string') {
                        try { payload = JSON.parse(payload); } catch (e) { payload = {}; }
                    }

                    const incoming = (payload && typeof payload.attributes === 'object' && !Array.isArray(payload.attributes))
                        ? payload.attributes
                        : {};

                    vm.values = { ...incoming };

                    // Snapshot (into internal state, not the prop)
                    try { vm.initialSnapshot = JSON.parse(JSON.stringify(vm.values)); }
                    catch (e) { vm.initialSnapshot = { ...vm.values }; }

                    // Ensure keys exist for all schema attributes
                    const schemaKeys = (vm.attributes && typeof vm.attributes === 'object') ? Object.keys(vm.attributes) : [];
                    schemaKeys.forEach((key) => {
                        const attribute = vm.attributes[key];

                        if (!(key in vm.values)) {
                            if (attribute.type === 'checkbox' && attribute.variations) {
                                vm.$set(vm.values, key, []);
                            } else {
                                vm.$set(vm.values, key, null);
                            }
                        }

                        if (attribute.type === 'datetime' && !(key + '_time' in vm.values)) {
                            vm.$set(vm.values, key + '_time', null);
                        }
                    });

                    vm.setMarkupValues();
                    vm.loading = false;
                })
                .catch(() => {
                    this.loading = false;
                    this.values = {};
                });
        },

        // ---------- helpers to (re)init/destroy widgets ----------
        initEditorsAndPickers() {
            // keep what you already have…
            this.setMarkupValues();

            // TinyMCE init (unchanged) …
            $('.patientAttributesTextarea').each((i, el) => {
                const $el = $(el);
                const id  = $el.attr('id');
                if (!id) return;
                if (window.tinyMCE) {
                    const existing = tinyMCE.get(id);
                    if (!existing) {
                        if (typeof window.simpleTinymceNew === 'function') {
                            window.simpleTinymceNew($el);
                        }
                    } else {
                        const key = id.replace(/^attribute_/, '');
                        existing.setContent(this.values[key] || '');
                    }
                }
            });

            // DATE pickers (unchanged) …
            $('.datepicker').each((i, el) => {
                const $el = $(el);
                try { $el.datepicker('destroy'); } catch (e) {}
                let done = false;
                try {
                    if ($.ui && $.ui.datepicker) {
                        $el.datepicker({ dateFormat: 'dd/mm/yy' });
                        done = true;
                    }
                } catch (e) {}
                if (!done) {
                    try {
                        $el.datepicker({ format: 'dd/mm/yyyy', autoclose: true, todayHighlight: true });
                        done = true;
                    } catch (e) {}
                }
                if (!done) { $el.attr('type', 'date'); }
            });

            // NEW: TIME pickers for inputs with id ending in _time
            // Ensure any previous handlers are removed first to avoid duplicate bindings.
            $('input[id$="_time"]').off('.patientAttrs');
            $('input[id$="_time"]').each((i, el) => {
                const $el = $(el);

                // try to remove a previous instance if any
                try { $el.timepicker('remove'); } catch (e) {}
                try { $el.timepicker('destroy'); } catch (e) {}

                let inited = false;

                // jquery-timepicker (jonthornton) — $.fn.timepicker
                if ($.fn && $.fn.timepicker && typeof $.fn.timepicker === 'function') {
                    try {
                        $el.timepicker({ timeFormat: 'HH:mm', step: 5, scrollDefault: 'now' });
                        inited = true;
                    } catch (e) {}
                }

                // jQuery UI timepicker addon — $.timepicker
                if (!inited && $.timepicker) {
                    try {
                        $el.timepicker({ timeFormat: 'HH:mm', stepMinute: 5 });
                        inited = true;
                    } catch (e) {}
                }

                // fallback to HTML5
                if (!inited) {
                    $el.attr({ type: 'time', step: '300' }); // 5-min steps
                }
                // IMPORTANT: keep Vue state in sync whenever time changes.
                // Different plugins fire different events; listen to both.
                const syncFromInput = (ev) => {
                    const id  = ev.target && ev.target.id ? ev.target.id : '';
                    // id looks like "attribute_<key>_time"
                    const key = id.replace(/^attribute_/, '').replace(/_time$/, '');
                    if (!key) return;
                    const val = $(ev.target).val() || '';
                    // write through to Vue state so subsequent re-renders keep the chosen time
                    this.$set(this.values, key + '_time', val);
                };
                // Namespaced so we can reliably unbind later.
                $el.on('change.patientAttrs', syncFromInput);
                // jonthornton timepicker uses changeTime.*
                $el.on('changeTime.patientAttrs', syncFromInput);
                // jQuery UI timepicker addon sometimes triggers "timepicker:select"
                $el.on('timepicker:select.patientAttrs', syncFromInput);
                // If a value already exists in Vue state, mirror it into the control
                // (this also covers the case where setMarkupValues didn't run yet).
                const existing = (this.values && this.values[($el.attr('id') || '').replace(/^attribute_/, '')]) || null;

            });
        },

        destroyEditors() {
            if (window.tinyMCE) {
                $('.patientAttributesTextarea').each((i, el) => {
                    const id = el.id;
                    if (!id) return;
                    const ed = tinyMCE.get(id);
                    if (ed) { try { ed.remove(); } catch (_) {} }
                });
            }
            // cleanup time pickers if plugin supports it
            $('input[id$="_time"]').each((i, el) => {
                const $el = $(el);
                // remove our event handlers first
                $el.off('.patientAttrs');
                try { $el.timepicker('remove'); } catch (e) {}
                try { $el.timepicker('destroy'); } catch (e) {}
            });
        },

        // Build FormData as attributes[field] / attributes[field][] so Laravel sees an array
        buildAttributesFormData() {
            const fd = new FormData();
            const attrs  = this.values || {};
            const schema = this.attributes || {};

            Object.keys(schema).forEach((key) => {
                const def = schema[key] || {};
                const val = attrs[key];

                if (def.type === 'checkbox' && def.variations) {
                    (Array.isArray(val) ? val : []).forEach(v => {
                        fd.append(`attributes[${key}][]`, v);
                    });
                } else {
                    fd.append(`attributes[${key}]`, val == null ? '' : val);
                }

                if (def.type === 'datetime') {
                    const t = attrs[`${key}_time`] == null ? '' : attrs[`${key}_time`];
                    fd.append(`attributes[${key}_time]`, t);
                }
            });

            return fd;
        },

        store() {
            if (this.loading) return;

            this.errors = {};
            this.success = false;
            this.loading = true;

            // Pull values from non-v-model inputs (date/datetime & tinyMCE)
            this.getMarkupValues();

            const fd = this.buildAttributesFormData();

            this.$http.post(this.routes['admin-member-attributes-store'], fd, {
                emulateJSON: false,
                headers: {} // let browser set multipart boundary
            })
                .then(({ data }) => {
                    if (data && data.errors) {
                        this.errors = data.errors;
                        this.loading = false;
                        return;
                    }

                    if (data && data.success) {
                        this.success = data.success;
                    }

                    // snapshot current values (INTERNAL COPY)
                    try { this.initialSnapshot = JSON.parse(JSON.stringify(this.values || {})); }
                    catch (e) { this.initialSnapshot = { ...(this.values || {}) }; }

                    this.loading = false;

                    // close panel and destroy editors (v-if removes DOM)
                    this.destroyEditors();
                    this.edit = false;
                })
                .catch((err) => {
                    console.error('Attributes store failed:', err);
                    this.loading = false;
                    this.errors.general = 'Unable to save. Please try again.';
                });
        },

        getMarkupValues() {
            if (!this.attributes || typeof this.attributes !== 'object') return;

            Object.keys(this.attributes).forEach((key) => {
                const attribute = this.attributes[key];

                if (['date', 'datetime'].includes(attribute.type)) {
                    this.values = this.values || {};
                    this.values[key] = $('#attribute_' + key).val();
                }

                // also read the companion time input for datetime
                if (attribute.type === 'datetime') {
                    this.values[key + '_time'] = $('#attribute_' + key + '_time').val() || this.values[key + '_time'] || '';
                }

                if (attribute.type === 'textarea') {
                    this.values = this.values || {};
                    const editor = (window.tinyMCE && tinyMCE.get('attribute_' + key)) || null;
                    this.values[key] = editor ? editor.getContent() : ($('#attribute_' + key).val() || '');
                }
            });
        },

        setMarkupValues() {
            if (!this.attributes || typeof this.attributes !== 'object') return;

            Object.keys(this.attributes).forEach((key) => {
                const attribute = this.attributes[key];

                if (['date', 'textarea', 'datetime'].includes(attribute.type)) {
                    const v = (this.values && Object.prototype.hasOwnProperty.call(this.values, key)) ? this.values[key] : '';
                    $('#attribute_' + key).val(v);
                }

                // set companion time input for datetime
                if (attribute.type === 'datetime') {
                    const t = (this.values && Object.prototype.hasOwnProperty.call(this.values, key + '_time'))
                        ? (this.values[key + '_time'] || '')
                        : '';
                    $('#attribute_' + key + '_time').val(t);
                }
            });
        },

        toggleEdit(editMode) {
            if (editMode) {
                // Open: render first, then init widgets
                this.edit = true;
                this.$nextTick(() => {
                    this.initEditorsAndPickers();
                });
            } else {
                // Close/cancel: collect values, destroy editors, reset to snapshot
                this.getMarkupValues();
                this.destroyEditors();
                this.edit = false;

                try { this.values = JSON.parse(JSON.stringify(this.initialSnapshot || {})); }
                catch (e) { this.values = { ...(this.initialSnapshot || {}) }; }
            }
        },

        getValue(key) {
            const vals = (this.values && typeof this.values === 'object') ? this.values : {};
            if (typeof vals[key] === 'undefined' || vals[key] === null) return '';

            const schema = this.attributes && this.attributes[key] ? this.attributes[key] : null;

            if (schema && schema.type === 'datetime') {
                const t = vals[key + '_time'] ?? '';
                return (vals[key] ?? '') + (t ? (' ' + t) : '');
            }

            if (schema && schema.type === 'checkbox' && schema.variations && Array.isArray(vals[key])) {
                return vals[key].join(',<br />');
            }
            return vals[key];
        },
    },
});
