<template>
    <div class="lj-vant-form-main">
        <div class="lj-vant-form-group" v-for="(group, groupIndex) in groupedFields" :key="groupIndex">
            <van-cell-group :title="group.title">
                <template v-for="(field, fieldIndex) in group.fields">
                    <custom-cell
                        v-if="field.slot"
                        :field="field"
                        :mainObject="mainObject"
                    />
                    <template v-else>
                        <van-field
                            v-if="isInputField(field)"
                            :key="fieldIndex"
                            v-model="mainObject[field.property]"
                            :label="field.label"
                            :type="field.type"
                            :required="field.required"
                            center
                            clearable
                            v-bind="field.extra"
                            @focus="handleFooterInputFocus($event)"
                        >
                            <template v-if="field.button" #button>
                                <van-button type="info" plain size="small" @click="handelClickFieldButton(field)">{{ field.button }}</van-button>
                            </template>
                            <template v-if="field.icon" #icon>
                                <van-icon :name="field.icon" @click="handelClickFieldIcon(field)" />
                            </template>
                            <template v-if="field.append" #extra>
                                {{ mainObject[field.append] }}
                            </template>
                        </van-field>
                        <van-field
                            v-else-if="isDateField(field)"
                            :key="fieldIndex"
                            v-model="mainObject[field.property]"
                            :label="field.label"
                            :required="field.required"
                            readonly
                            :is-link="!field.disabled"
                            @click="openPopup(field)"
                            v-bind="field.extra"
                        />
                        <van-field
                            v-else-if="field.type === 'action'"
                            :key="fieldIndex"
                            :label="field.label"
                            :required="field.required"
                            readonly
                            :value="getDisplayValue(field)"
                            :is-link="!field.disabled"
                            @click="handleClickAction(field)"
                            v-bind="field.extra"
                        />
                        <van-field
                            v-else-if="field.type === 'selection'"
                            :key="fieldIndex"
                            :label="field.label"
                            :required="field.required"
                            readonly
                            :value="getDisplayValue(field)"
                            :is-link="!field.disabled"
                            @click="openPicker(field)"
                            v-bind="field.extra"
                        />
                        <van-field
                            v-else-if="field.type === 'actionsheet'"
                            :key="fieldIndex"
                            :label="field.label"
                            :required="field.required"
                            readonly
                            :value="getDisplayValue(field)"
                            :is-link="!field.disabled"
                            @click="openActionSheet(field)"
                            v-bind="field.extra"
                        />
                    </template>
                </template>
            </van-cell-group>
        </div>
  
        <!-- Date Picker Popup -->
        <van-popup v-model="showDatePopup" position="bottom">
            <van-datetime-picker
                v-model="currentDate"
                :type="currentField ? currentField.type : 'datetime'"
                @confirm="onDateConfirm"
                @cancel="onPopupCancel"
            />
        </van-popup>
  
        <!-- Calendar Popup -->
        <van-popup v-model="showCalendarPopup" position="bottom">
            <van-calendar @confirm="onCalendarConfirm" />
        </van-popup>
  
        <!-- Picker Popup -->
        <van-popup v-model="showPickerPopup" position="bottom">
            <van-picker
                show-toolbar
                :columns="currentOptions"
                @confirm="onPickerConfirm"
                @cancel="onPopupCancel"
            />
        </van-popup>
  
        <!-- Action Sheet -->
        <van-action-sheet
            v-model="showActionSheet"
            :actions="currentActions"
            @select="onActionSelect"
            @cancel="onPopupCancel"
        />
    </div>
</template>
<script>
export default {
    name: 'lj-vant-form',
    components: {
        'custom-cell': {
            props: {
                field: Object,
                mainObject: Object
            },
            render(h) {
                if (this.field.slot) {
                    return this.field.slot(h, {mainObject: this.mainObject,field: this.field});
                } 
            }
        }
    },
    props: {
        fields: {
            type: Array,
            required: true,
        },
        mainObject: {
            type: Object,
            required: true,
        },
    },
    data() {
        return {
            showDatePopup: false,
            showCalendarPopup: false,
            showPickerPopup: false,
            showActionSheet: false,
            currentDate: new Date(),
            currentOptions: [],
            currentActions: [],
            currentField: null,
            cachedData: {}
        };
    },
    created() {
        this.cachedData = {};
        this.prefetchOptions();
    },
    computed: {
        groupedFields() {
            const groups = {};
            this.fields.forEach((field) => {
                if (!groups[field.title]) {
                    groups[field.title] = {
                        title: field.title,
                        fields: [],
                    };
                }
                groups[field.title].fields.push(field);
            });
            return Object.values(groups);
        },
    },
    methods: {
        isInputField(field) {
            const inputTypes = ['text', 'number', 'textarea'];
            return inputTypes.includes(field.type) || !field.type;
        },
        isDateField(field) {
            const dateTypes = ['date', 'datetime', 'calendar','year-month'];
            return dateTypes.includes(field.type);
        },
        openPopup(field) {
            this.currentField = field;
            if(field.disabled) return;
            if (field.type === 'date' || field.type === 'datetime' || field.type === 'year-month') {
                this.showDatePopup = true;
            } else if (field.type === 'calendar') {
                this.showCalendarPopup = true;
            }
        },
        getReqApi(field) {
            if (field.type === 'selection') {
                return field.options.reqApi;
            } else if (field.type === 'actionsheet') {
                return field.actions.reqApi;
            }
            return "";
        },
        getCacheData(field) {
            const reqApi = this.getReqApi(field);
            if (!reqApi) {
                return null;
            }
            let key = reqApi;
            if(reqApi === "CommonDynamicSelect") {
                key = field.options.reqParm.dsname;
                for(let item in field.options.reqParm.queryparams) {
                    key += "_";
                    key += item;
                    key += "_";
                    key += field.options.reqParm.queryparams[item];
                }
            }
            return this.cachedData[key];
        },
        setCacheData(field, data) {
            const reqApi = this.getReqApi(field);
            if (reqApi) {
                let key = reqApi;
                if(reqApi === "CommonDynamicSelect") {
                    key = field.options.reqParm.dsname;
                    for(let item in field.options.reqParm.queryparams) {
                        key += "_";
                        key += item;
                        key += "_";
                        key += field.options.reqParm.queryparams[item];
                    }
                }
                this.cachedData[key] = data;
            }
        },
        onDateConfirm(value) {
            this.$set(this.mainObject, this.currentField.property, $lj.dateformat(value,this.currentField.format));
            this.showDatePopup = false;
        },
        onCalendarConfirm(value) {
            this.$set(this.mainObject, this.currentField.property, value);
            this.showCalendarPopup = false;
        },
        async openPicker(field) {
            try {
                this.currentField = field;
                if(field.disabled) return;
                if (field.options) {
                    if(field.options.values) {
                        this.currentOptions = this.formatOptions(field.options.values,field.options.valueMap);
                    } else if (field.options.reqApi) {
                        if (!this.getCacheData(field)) {
                            await this.fetchOptions(field,field.options.reqApi, field.options.reqParm, field.options.resParm, field.options.valueMap);
                        }
                        this.currentOptions = this.getCacheData(field);
                    }
                    this.showPickerPopup = true;
                } else {
                    throw new Error("没有设置options,请检查!");
                }
            } catch(e) {
                $lj.toast(e);
            }
        },
        onPickerConfirm(value) {
            this.$set(this.mainObject, this.currentField.property, value.value);
            this.showPickerPopup = false;
            this.$emit("picker-callback",this.currentField)
        },
        async openActionSheet(field) {
            try {
                this.currentField = field;
                if(field.disabled) return;
                if (field.actions) {
                    if(field.actions.values) {
                        this.currentActions = this.formatActions(field.actions.values,field.actions.valueMap);
                    } else if (field.actions.reqApi) {
                        if (!this.getCacheData(field)) {
                            await this.fetchOptions(field,field.actions.reqApi, field.actions.reqParm, field.actions.resParm, field.actions.valueMap);
                        }
                        this.currentActions = this.getCacheData(field);
                    }
                    this.showActionSheet = true;
                } else {
                    throw new Error("没有设置actions,请检查!");
                }
            } catch(e) {
                $lj.toast(e);
            }
        },
        onActionSelect(action) {
            this.$set(this.mainObject, this.currentField.property, action.value);
            this.showActionSheet = false;
            this.$emit("picker-callback",this.currentField)
        },
        onPopupCancel() {
            this.showDatePopup = false;
            this.showCalendarPopup = false;
            this.showPickerPopup = false;
            this.showActionSheet = false;
        },
        fetchOptions(field, api, reqParams, resParm, valueMap) {
            return new Promise((resolve, reject) => {
                let requestBody = reqParams || {};
                requestBody.token = $lj.getStorage("token");
                $lj.postLJRequest(api, requestBody, (ret) => {
                    if (ret) {
                        const data = ret[resParm];
                        let formattedData;
                        if(field.type === "selection") {
                            formattedData = this.formatOptions(data, valueMap);
                        } else if(field.type === "actionsheet") {
                            formattedData = this.formatActions(data, valueMap);
                        }

                        if(data.length === 1) {
                            this.$set(this.mainObject,field.property,formattedData[0].value);
                        }

                        this.setCacheData(field,formattedData);
                        resolve(formattedData);
                    } else {
                        reject(new Error("Failed to fetch options"));
                    }
                });
            });
        },
        formatOptions(options, valueMap = { text: 'text', value: 'value' }) {
            return options.map(option => ({
                text: option[valueMap.text],
                value: option[valueMap.value]
            }));
        },
        formatActions(actions, valueMap = { text: 'text', value: 'value' }) {
            return actions.map(action => ({
                name: action[valueMap.text],
                value: action[valueMap.value]
            }));
        },
        prefetchOptions() {
            this.fields.forEach(field => {
                if (field.options && field.options.reqApi) {
                    !this.getCacheData(field) && this.fetchOptions(field,field.options.reqApi, field.options.reqParm, field.options.resParm, field.options.valueMap);
                } else if (field.actions && field.actions.reqApi) {
                    !this.getCacheData(field) && this.fetchOptions(field,field.actions.reqApi, field.actions.reqParm, field.actions.resParm, field.actions.valueMap);
                }
            });
        },
        getDisplayValue(field) {
            const value = this.mainObject[field.property];
            let options, valueKey, textKey;

            if (field.options) {
                valueKey = field.options.reqApi ? "value" : field.options.valueMap.value;
                textKey = field.options.reqApi ? "text" : field.options.valueMap.text;
                options = this.getCacheData(field) || field.options.values;
            } else if (field.actions) {
                valueKey = field.actions.reqApi ? "value" : field.actions.valueMap.value;
                textKey = field.actions.reqApi ? "text" : field.actions.valueMap.text;
                options = this.getCacheData(field) || field.actions.values;
            }
            
            const option = options ? options.find(opt => opt[valueKey] === value) : null;

            return option ? option[textKey] : value;
        },
        handleClickAction(field) {
            this.$emit("action-click",field);
        },
        handleFieldFocus(ev) {
            ev.currentTarget && ev.currentTarget.select();
        },
        handelClickFieldButton(field) {
            this.$emit("button-click",field);
        },
        handleFooterInputFocus(ev) {
            ev.currentTarget && ev.currentTarget.select();
        }
    }
};
</script>

<style scoped>
/* 可根据需要自定义样式 */
</style>
  