// app/modules/loyalty/static/shared/js/loyalty-pins-list.js
// Shared Alpine.js data factory for loyalty staff PIN listing pages.
// Used by store, merchant, and admin frontends.

const loyaltyPinsListLog = window.LogConfig.loggers.loyaltyPinsList || window.LogConfig.createLogger('loyaltyPinsList');

/**
 * Factory that returns an Alpine.js data object for loyalty PIN management.
 *
 * @param {Object}  config
 * @param {string}  config.apiPrefix       - API path prefix, e.g. '/store/loyalty'
 * @param {boolean} config.showStoreFilter - Whether to show the store/location dropdown filter
 * @param {boolean} config.showCrud        - Whether to show create/edit/delete UI
 * @param {string}  config.currentPage     - Alpine currentPage identifier
 */
function loyaltyPinsList(config) {
    const guardKey = '_loyaltyPinsList_' + config.currentPage + '_initialized';

    return {
        ...data(),
        currentPage: config.currentPage,

        // Data
        pins: [],
        program: null,
        locations: [],
        staffMembers: [],

        // Filters
        filters: {
            store_id: '',
            status: ''
        },

        // Stats (computed from pins array)
        stats: {
            total: 0,
            active: 0,
            locked: 0
        },

        // State
        loading: false,
        error: null,

        // Modal state
        showCreateModal: false,
        showEditModal: false,
        showDeleteModal: false,
        editingPin: null,
        deletingPin: null,

        // Form state
        pinForm: {
            name: '',
            staff_id: '',
            pin: '',
            store_id: ''
        },

        // Staff autocomplete state
        staffSearch: '',
        staffSearchResults: [],
        showStaffDropdown: false,
        searchingStaff: false,
        _selectedStaffName: '',

        searchStaff() {
            // Client-side filter of loaded staff members
            if (!this.staffSearch || this.staffSearch.length < 1) {
                this.staffSearchResults = [];
                this.showStaffDropdown = false;
                return;
            }
            const q = this.staffSearch.toLowerCase();
            this.staffSearchResults = this.staffMembers.filter(m =>
                (m.full_name && m.full_name.toLowerCase().includes(q)) ||
                (m.email && m.email.toLowerCase().includes(q))
            );
            this.showStaffDropdown = this.staffSearchResults.length > 0;

            // If user modified the text away from the selected member, clear staff_id
            if (this._selectedStaffName && this.staffSearch !== this._selectedStaffName) {
                this.pinForm.staff_id = '';
                this._selectedStaffName = '';
            }
            this.pinForm.name = this.staffSearch;
        },

        selectStaffMember(item) {
            this.pinForm.name = item.full_name;
            this.pinForm.staff_id = item.email;
            this.staffSearch = item.full_name;
            this._selectedStaffName = item.full_name;
            this.showStaffDropdown = false;
            this.staffSearchResults = [];
        },

        clearStaffSelection() {
            this.staffSearch = '';
            this.pinForm.name = '';
            this.pinForm.staff_id = '';
            this._selectedStaffName = '';
            this.showStaffDropdown = false;
            this.staffSearchResults = [];
        },

        // Action state
        saving: false,
        deleting: false,

        // Config (exposed for templates)
        _config: config,

        async init() {
            loyaltyPinsListLog.info('=== LOYALTY PINS LIST INITIALIZING ===', config.currentPage);
            if (window[guardKey]) return;
            window[guardKey] = true;

            const parentInit = data().init;
            if (parentInit) {
                await parentInit.call(this);
            }

            await this.loadData();
            loyaltyPinsListLog.info('=== LOYALTY PINS LIST INITIALIZATION COMPLETE ===');
        },

        async loadData() {
            this.loading = true;
            this.error = null;
            try {
                await this.loadProgram();
                if (this.program) {
                    const parallel = [this.loadPins()];
                    if (config.showStoreFilter) {
                        parallel.push(this.loadLocations());
                    }
                    if (config.showCrud && config.staffApiPrefix) {
                        parallel.push(this.loadStaffMembers());
                    }
                    await Promise.all(parallel);
                }
            } catch (error) {
                loyaltyPinsListLog.error('Failed to load data:', error);
                this.error = error.message;
            } finally {
                this.loading = false;
            }
        },

        async loadProgram() {
            try {
                const response = await apiClient.get(config.apiPrefix + '/program');
                if (response) this.program = response;
            } catch (error) {
                if (error.status !== 404) throw error;
            }
        },

        async loadPins() {
            try {
                const params = new URLSearchParams();
                if (this.filters.store_id) params.append('store_id', this.filters.store_id);
                if (this.filters.status) params.append('is_active', this.filters.status === 'active');

                const queryString = params.toString();
                const url = config.apiPrefix + '/pins' + (queryString ? '?' + queryString : '');
                const response = await apiClient.get(url);
                if (response) {
                    this.pins = Array.isArray(response) ? response : (response.pins || []);
                    this.computeStats();
                }
            } catch (error) {
                loyaltyPinsListLog.error('Failed to load pins:', error);
                throw error;
            }
        },

        async loadLocations() {
            try {
                const response = await apiClient.get(config.apiPrefix + '/locations');
                if (response) {
                    this.locations = Array.isArray(response) ? response : (response.locations || []);
                }
            } catch (error) {
                loyaltyPinsListLog.warn('Failed to load locations:', error.message);
            }
        },

        async loadStaffMembers() {
            try {
                const response = await apiClient.get(config.staffApiPrefix + '/team/members');
                if (response && response.members) {
                    this.staffMembers = response.members.filter(m => m.is_active);
                    loyaltyPinsListLog.info('Loaded', this.staffMembers.length, 'staff members');
                }
            } catch (error) {
                loyaltyPinsListLog.warn('Failed to load staff members:', error.message);
            }
        },

        computeStats() {
            this.stats.total = this.pins.length;
            this.stats.active = this.pins.filter(p => p.is_active && !p.is_locked).length;
            this.stats.locked = this.pins.filter(p => p.is_locked).length;
        },

        applyFilter() {
            this.loadPins();
        },

        // ---- CRUD operations (only used when config.showCrud is true) ----

        openCreateModal() {
            this.pinForm = {
                name: '',
                staff_id: '',
                pin: '',
                store_id: ''
            };
            this.staffSearch = '';
            this.showStaffDropdown = false;
            this.showCreateModal = true;
        },

        openEditModal(pin) {
            this.editingPin = pin;
            this.pinForm = {
                name: pin.name || '',
                staff_id: pin.staff_id || '',
                pin: '',
                store_id: pin.store_id || ''
            };
            this.staffSearch = pin.name || '';
            this.showStaffDropdown = false;
            this.showEditModal = true;
        },

        openDeleteModal(pin) {
            this.deletingPin = pin;
            this.showDeleteModal = true;
        },

        async createPin() {
            this.saving = true;
            try {
                const payload = { ...this.pinForm };
                if (!payload.store_id) delete payload.store_id;

                await apiClient.post(config.apiPrefix + '/pins', payload);
                Utils.showToast(I18n.t('loyalty.toasts.pin_created'), 'success');
                this.showCreateModal = false;
                await this.loadPins();
            } catch (error) {
                loyaltyPinsListLog.error('Failed to create pin:', error);
                Utils.showToast(error.message || I18n.t('loyalty.toasts.pin_create_error'), 'error');
            } finally {
                this.saving = false;
            }
        },

        async updatePin() {
            if (!this.editingPin) return;
            this.saving = true;
            try {
                const payload = { ...this.pinForm };
                // Only include pin field if a new pin was entered
                if (!payload.pin) delete payload.pin;
                if (!payload.store_id) delete payload.store_id;

                await apiClient.patch(
                    config.apiPrefix + '/pins/' + this.editingPin.id,
                    payload
                );
                Utils.showToast(I18n.t('loyalty.toasts.pin_updated'), 'success');
                this.showEditModal = false;
                this.editingPin = null;
                await this.loadPins();
            } catch (error) {
                loyaltyPinsListLog.error('Failed to update pin:', error);
                Utils.showToast(error.message || I18n.t('loyalty.toasts.pin_update_error'), 'error');
            } finally {
                this.saving = false;
            }
        },

        async deletePin() {
            if (!this.deletingPin) return;
            this.deleting = true;
            try {
                await apiClient.delete(config.apiPrefix + '/pins/' + this.deletingPin.id);
                Utils.showToast(I18n.t('loyalty.toasts.pin_deleted'), 'success');
                this.showDeleteModal = false;
                this.deletingPin = null;
                await this.loadPins();
            } catch (error) {
                loyaltyPinsListLog.error('Failed to delete pin:', error);
                Utils.showToast(error.message || I18n.t('loyalty.toasts.pin_delete_error'), 'error');
            } finally {
                this.deleting = false;
            }
        },

        async unlockPin(pin) {
            try {
                await apiClient.post(config.apiPrefix + '/pins/' + pin.id + '/unlock');
                Utils.showToast(I18n.t('loyalty.toasts.pin_unlocked'), 'success');
                await this.loadPins();
            } catch (error) {
                loyaltyPinsListLog.error('Failed to unlock pin:', error);
                Utils.showToast(error.message || I18n.t('loyalty.toasts.pin_unlock_error'), 'error');
            }
        },

        // Formatting helpers
        formatDate(dateString) {
            if (!dateString) return 'Never';
            try {
                return new Date(dateString).toLocaleDateString('en-US', {
                    year: 'numeric',
                    month: 'short',
                    day: 'numeric'
                });
            } catch (e) {
                return dateString;
            }
        },

        formatDateTime(dateString) {
            if (!dateString) return 'Never';
            try {
                return new Date(dateString).toLocaleDateString('en-US', {
                    year: 'numeric',
                    month: 'short',
                    day: 'numeric',
                    hour: '2-digit',
                    minute: '2-digit'
                });
            } catch (e) {
                return dateString;
            }
        }
    };
}

if (!window.LogConfig.loggers.loyaltyPinsList) {
    window.LogConfig.loggers.loyaltyPinsList = window.LogConfig.createLogger('loyaltyPinsList');
}
loyaltyPinsListLog.info('Loyalty pins list shared module loaded');
