<template>
    <div class="card">
        <div class="card-body">
            <h5 class="card-title">Preferences</h5>

            <div v-if="!preferencesLoaded" class="text-center py-4 text-muted">
                Loading preferences...
            </div>

            <div v-else>
                <div class="table-responsive">
                    <table class="table table-sm align-middle mb-0">
                        <thead>
                        <tr>
                            <th style="width: 26%">Preference</th>
                            <th style="width: 17%">Device</th>
                            <th style="width: 17%">Account</th>
                            <th style="width: 17%">Default</th>
                            <th style="width: 23%">Effective</th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr v-for="schema in schemas" :key="schema.key">
                            <td>
                                <div class="font-weight-bold">{{ schema.label }}</div>
                                <small v-if="schema.description" class="text-muted">{{ schema.description }}</small>
                            </td>
                            <td>
                                <PreferenceInput
                                    :id="`device-${schema.key}`"
                                    :schema="schema"
                                    :value="effectiveDeviceValues[schema.key]"
                                    @input="updateDevicePreference(schema.key, $event)"
                                    @clear="clearDevicePreference(schema.key)"
                                />
                            </td>
                            <td>
                                <PreferenceInput
                                    :id="`account-${schema.key}`"
                                    :schema="schema"
                                    :value="effectiveAccountValues[schema.key]"
                                    @input="updateAccountPreference(schema.key, $event)"
                                    @clear="clearAccountPreference(schema.key)"
                                />
                            </td>
                            <td>
                                <PreferenceInput
                                    :id="`default-${schema.key}`"
                                    :schema="schema"
                                    :value="schema.default"
                                    :disabled="true"
                                />
                            </td>
                            <td>
                                <div class="font-weight-bold">
                                    {{ formatEffectiveValue(schema, getPreference(schema.key)) }}
                                    <span
                                        v-if="hasChanges && formatEffectiveValue(schema, getEffectiveValueWithPendingChanges(schema.key)) !== formatEffectiveValue(schema, getPreference(schema.key))"
                                        class="text-warning ml-1"
                                    >
                                        -> {{ formatEffectiveValue(schema, getEffectiveValueWithPendingChanges(schema.key)) }}
                                    </span>
                                </div>
                                <small class="text-muted">Source: {{ getPreferenceSource(schema.key) }}</small>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>

                <div class="d-flex pt-3 border-top mt-3">
                    <button @click="savePreferences" :disabled="!hasChanges || saving" class="btn btn-primary mr-2">
                        {{ saving ? 'Saving...' : 'Save changes' }}
                    </button>
                    <button @click="reloadPreferences" :disabled="!hasChanges || saving" class="btn btn-secondary">
                        Discard changes
                    </button>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import {mapActions, mapGetters, mapState} from 'vuex'
import PreferenceInput from '@/components/inputs/PreferenceInput.vue'

export default {
    name: 'Preferences',
    components: {PreferenceInput},
    data() {
        return {
            saving: false,
            accountChanges: {},
            deviceChanges: {},
        }
    },
    computed: {
        ...mapState(['preferencesLoaded', 'preferenceDefinitions', 'devicePreferences', 'accountPreferences']),
        ...mapGetters(['getPreference']),
        schemas() {
            return this.preferenceDefinitions.map((pref) => ({
                ...pref,
                label: pref.label || this.formatLabel(pref.key),
                description: pref.description || '',
            }))
        },
        hasChanges() {
            return Object.keys(this.accountChanges).length > 0 || Object.keys(this.deviceChanges).length > 0
        },
        effectiveDeviceValues() {
            return {...this.devicePreferences, ...this.deviceChanges}
        },
        effectiveAccountValues() {
            return {...this.accountPreferences, ...this.accountChanges}
        },
    },
    methods: {
        ...mapActions([
            'loadUserPreferences',
            'setAccountPreference',
            'resetAccountPreference',
            'setDevicePreference',
            'resetDevicePreference',
        ]),
        formatLabel(key) {
            const parts = key.split('.')
            const name = parts[parts.length - 1] || ''
            return name
                .split('_')
                .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
                .join(' ')
        },
        getEffectiveValueWithPendingChanges(key) {
            if (Object.prototype.hasOwnProperty.call(this.deviceChanges, key)) {
                if (this.deviceChanges[key] !== null) {
                    return this.deviceChanges[key]
                }
                if (Object.prototype.hasOwnProperty.call(this.accountChanges, key) && this.accountChanges[key] !== null) {
                    return this.accountChanges[key]
                }
                if (Object.prototype.hasOwnProperty.call(this.accountPreferences, key) && this.accountPreferences[key] !== null) {
                    return this.accountPreferences[key]
                }
            } else if (Object.prototype.hasOwnProperty.call(this.accountChanges, key)) {
                if (this.accountChanges[key] !== null) {
                    return this.accountChanges[key]
                }
            } else {
                return this.getPreference(key)
            }

            const definition = this.preferenceDefinitions.find((p) => p.key === key)
            return definition ? definition.default : null
        },
        getPreferenceSource(key) {
            if (Object.prototype.hasOwnProperty.call(this.deviceChanges, key)) {
                return this.deviceChanges[key] !== null
                    ? 'Device'
                    : Object.prototype.hasOwnProperty.call(this.accountPreferences, key) && this.accountPreferences[key] !== null
                        ? 'Account'
                        : 'Default'
            }
            if (Object.prototype.hasOwnProperty.call(this.accountChanges, key)) {
                return this.accountChanges[key] !== null ? 'Account' : 'Default'
            }
            if (Object.prototype.hasOwnProperty.call(this.devicePreferences, key) && this.devicePreferences[key] !== null) {
                return 'Device'
            }
            if (Object.prototype.hasOwnProperty.call(this.accountPreferences, key) && this.accountPreferences[key] !== null) {
                return 'Account'
            }
            return 'Default'
        },
        updateDevicePreference(key, value) {
            this.deviceChanges = {...this.deviceChanges, [key]: value}
        },
        updateAccountPreference(key, value) {
            this.accountChanges = {...this.accountChanges, [key]: value}
        },
        clearDevicePreference(key) {
            this.deviceChanges = {...this.deviceChanges, [key]: null}
        },
        clearAccountPreference(key) {
            this.accountChanges = {...this.accountChanges, [key]: null}
        },
        reloadPreferences() {
            this.accountChanges = {}
            this.deviceChanges = {}
        },
        formatEffectiveValue(schema, value) {
            if (value === null || value === undefined) {
                return '(not set)'
            }
            if (schema.type === 'boolean') {
                return value ? 'Yes' : 'No'
            }
            if (schema.type === 'json') {
                return typeof value === 'object' ? JSON.stringify(value) : String(value)
            }
            return String(value)
        },
        async savePreferences() {
            this.saving = true
            try {
                for (const [key, value] of Object.entries(this.accountChanges)) {
                    if (value === null) {
                        await this.resetAccountPreference(key)
                    } else {
                        await this.setAccountPreference({key, value})
                    }
                }
                for (const [key, value] of Object.entries(this.deviceChanges)) {
                    if (value === null) {
                        await this.resetDevicePreference(key)
                    } else {
                        await this.setDevicePreference({key, value})
                    }
                }
                this.accountChanges = {}
                this.deviceChanges = {}
            } catch (error) {
                console.error('Error saving preferences:', error)
            } finally {
                this.saving = false
            }
        },
    },
    mounted() {
        this.loadUserPreferences()
    },
}
</script>

