import { IPSDEGrid, IPSDEGridEditItem } from '@ibiz/dynamic-model-api';
import { ControlServiceBase, ModelTool, Util } from 'ibiz-core';
import { GlobalService } from 'ibiz-service';
import { AppGridModel } from 'ibiz-vue';


/**
 * 表格部件服务对象
 *
 * @export
 * @class AppGridService
 */
export class AppGridService extends ControlServiceBase {

    /**
    * 表格实例对象
    *
    * @memberof AppGridService
    */
    public controlInstance!: IPSDEGrid;

    /**
     * 数据服务对象
     *
     * @type {any}
     * @memberof AppGridService
     */
    public appEntityService!: any;

    /**
     * 备份原生数据
     *
     * @type {*}
     * @memberof AppGridService
     */
    private copynativeData:any;

    /**
     * 远端数据
     *
     * @type {*}
     * @memberof AppGridService
     */
    private remoteCopyData: any = {};

    /**
     * 初始化服务参数
     *
     * @type {boolean}
     * @memberof AppGridService
     */
    public async initServiceParam() {
        if (this.appDeCodeName) {
            this.appEntityService = await new GlobalService().getService(this.appDeCodeName, this.context);
        }
        this.model = new AppGridModel(this.controlInstance);
    }

    /**
     * Creates an instance of AppGridService.
     * 
     * @param {*} [opts={}]
     * @memberof AppGridService
     */
    constructor(opts: any = {}, context?: any) {
        super(opts, context);
        this.controlInstance = opts;
    }


    /**
     * @description 加载
     * @memberof AppGridService
     */
    public async loaded() {
      await this.initServiceParam();
    }

    /**
     * 处理数据
     *
     * @private
     * @param {Promise<any>} promise
     * @returns {Promise<any>}
     * @memberof AppGridService
     */
    private doItems(promise: Promise<any>, deKeyField: string, deName: string): Promise<any> {
        return new Promise((resolve, reject) => {
            promise.then((response: any) => {
                if (response && response.status === 200) {
                    const data = response.data;
                    data.forEach((item: any, index: number) => {
                        item[deName] = item[deKeyField];
                        data[index] = item;
                    });
                    resolve(data);
                } else {
                    reject([])
                }
            }).catch((response: any) => {
                reject([])
            });
        });
    }

    /**
     * 获取跨实体数据集合
     *
     * @param {string} serviceName 服务名称
     * @param {string} interfaceName 接口名称
     * @param {*} data
     * @param {boolean} [isloading]
     * @returns {Promise<any[]>}
     * @memberof  AppGridService
     */
    public async getItems(serviceName: string, interfaceName: string, context: any = {}, data: any, isloading?: boolean): Promise<any[]> {
        data.page = data.page ? data.page : 0;
        data.size = data.size ? data.size : 1000;
        const editItems: Array<IPSDEGridEditItem> = this.controlInstance.getPSDEGridEditItems() || [];
        if(editItems.length>0) {
            let item: any = editItems.find((item: any) => {
                let flag: boolean = false;
                const editor: any = item.getPSEditor();
                if(editor && 
                    editor?.getPSAppDataEntity && 
                    editor?.getPSAppDEDataSet && 
                    serviceName &&
                    Object.is(editor.getPSAppDataEntity()?.codeName, serviceName) &&
                    interfaceName &&
                    Object.is(editor.getPSAppDEDataSet()?.codeName, interfaceName)) {
                        flag = true;
                }
                return flag;
            })
            if(item) {
                const service: any = await new GlobalService().getService(serviceName);
                if(service && service[interfaceName] && Util.isFunction(service[interfaceName])) {
                    const appDeKeyCodeName:any = ModelTool.getAppEntityKeyField(item.getPSEditor()?.getPSAppDataEntity())?.codeName?.toLowerCase();
                    return this.doItems(service[interfaceName](JSON.parse(JSON.stringify(context)),data, isloading), appDeKeyCodeName, item.getPSEditor()?.getPSAppDataEntity()?.codeName?.toLowerCase())
                }
            }
        }
        return Promise.reject([])
    }

    /**
     * 启动工作流
     *
     * @param {string} action
     * @param {*} [context={}]
     * @param {*} [data={}]
     * @param {boolean} [isloading]
     * @param {*} [localdata]
     * @returns {Promise<any>}
     * @memberof AppGridService
     */
    public wfstart(action: string, context: any = {}, data: any = {}, isloading?: boolean, localdata?: any): Promise<any> {
        data = this.handleWFData(data, true);
        context = this.handleRequestData(action, context, data).context;
        return new Promise((resolve: any, reject: any) => {
            let result: Promise<any>;
            const _appEntityService: any = this.appEntityService;
            if (_appEntityService[action] && _appEntityService[action] instanceof Function) {
                result = _appEntityService[action](context, data, localdata);
            } else {
                result = this.appEntityService.WFStart(context, data, localdata);
            }
            result.then((response) => {
                this.handleResponse(action, response);
                resolve(response);
            }).catch(response => {
                reject(response);
            });
        });
    }

    /**
     * 提交工作流
     *
     * @param {string} action
     * @param {*} [context={}]
     * @param {*} [data={}]
     * @param {boolean} [isloading]
     * @param {*} [localdata]
     * @returns {Promise<any>}
     * @memberof AppGridService
     */
    public wfsubmit(action: string, context: any = {}, data: any = {}, isloading?: boolean, localdata?: any): Promise<any> {
        data = this.handleWFData(data, true);
        context = this.handleRequestData(action, context, data, true).context;
        return new Promise((resolve: any, reject: any) => {
            let result: Promise<any>;
            const _appEntityService: any = this.appEntityService;
            if (_appEntityService[action] && _appEntityService[action] instanceof Function) {
                result = _appEntityService[action](context, data, localdata);
            } else {
                result = this.appEntityService.WFSubmit(context, data, localdata);
            }
            result.then((response) => {
                this.handleResponse(action, response);
                resolve(response);
            }).catch(response => {
                reject(response);
            });
        });
    }

    /**
     * 添加数据
     *
     * @param {string} action
     * @param {*} [context={}]
     * @param {*} [data={}]
     * @param {boolean} [isloading]
     * @param {boolean} [isWorkflow] 是否在工作流中添加数据
     * @returns {Promise<any>}
     * @memberof AppGridService
     */
    public add(action: string, context: any = {}, data: any = {}, isloading?: boolean, isWorkflow?: boolean): Promise<any> {
        const { data: Data, context: Context } = this.handleRequestDataWithUpdate(action, context, data);
        const editItems: Array<IPSDEGridEditItem> = this.controlInstance.getPSDEGridEditItems() || [];
        const keyField: any = this.appDeKeyFieldName.toLowerCase();
        if(editItems.length>0) {
            editItems.forEach((item: any) => {
                if(Object.is(item.codeName.toLowerCase(), keyField) && !Object.is(item.codeName.toLowerCase(), "srfkey")) {
                    Object.assign(Data, { [keyField]: data[item.name], srffrontuf: '1' });
                }
            })
        }
        return new Promise((resolve: any, reject: any) => {
            let result: Promise<any>;
            const _appEntityService: any = this.appEntityService;
            if (_appEntityService[action] && _appEntityService[action] instanceof Function) {
                result = _appEntityService[action](Context, Data);
            } else {
                result = this.appEntityService.Create(Context, Data);
            }
            result.then((response) => {
                if (isWorkflow) {
                    resolve(response);
                } else {
                    this.handleResponse(action, response);
                    resolve(response);
                }
            }).catch(response => {
                reject(response);
            });
        });
    }

    /**
     * 删除数据
     *
     * @param {string} action
     * @param {*} [context={}]
     * @param {*} [data={}]
     * @param {boolean} [isloading]
     * @returns {Promise<any>}
     * @memberof AppGridService
     */
    public delete(action: string, context: any = {}, data: any = {}, isloading?: boolean): Promise<any> {
        const { data: Data, context: Context } = this.handleRequestData(action, context, data, true);
        return new Promise((resolve: any, reject: any) => {
            let result: Promise<any>;
            const _appEntityService: any = this.appEntityService;
            if (_appEntityService[action] && _appEntityService[action] instanceof Function) {
                result = _appEntityService[action](Context, Data);
            } else {
                result = this.appEntityService.Remove(Context, Data);
            }
            result.then((response) => {
                resolve(response);
            }).catch(response => {
                reject(response);
            });
        });
    }

    /**
     * 修改数据
     *
     * @param {string} action
     * @param {*} [context={}]
     * @param {*} [data={}]
     * @param {boolean} [isloading]
     * @param {boolean} [isWorkflow] 是否在工作流中修改数据
     * @returns {Promise<any>}
     * @memberof AppGridService
     */
    public update(action: string, context: any = {}, data: any = {}, isloading?: boolean, isWorkflow?: boolean): Promise<any> {
        const { data: Data, context: Context } = this.handleRequestDataWithUpdate(action, context, data);
        return new Promise((resolve: any, reject: any) => {
            let result: Promise<any>;
            const _appEntityService: any = this.appEntityService;
            if (_appEntityService[action] && _appEntityService[action] instanceof Function) {
                result = _appEntityService[action](Context, Data);
            } else {
                result = this.appEntityService.Update(Context, Data);
            }
            result.then((response) => {
                if (isWorkflow) {
                    resolve(response);
                } else {
                    this.handleResponse(action, response);
                    resolve(response);
                }
            }).catch(response => {
                reject(response);
            });
        });
    }

    /**
     * 查询数据
     *
     * @param {string} action
     * @param {*} [context={}]
     * @param {*} [data={}]
     * @param {boolean} [isloading]
     * @returns {Promise<any>}
     * @memberof AppGridService
     */
    public get(action: string, context: any = {}, data: any = {}, isloading?: boolean): Promise<any> {
        const { data: Data, context: Context } = this.handleRequestData(action, context, data);
        return new Promise((resolve: any, reject: any) => {
            let result: Promise<any>;
            const _appEntityService: any = this.appEntityService;
            if (_appEntityService[action] && _appEntityService[action] instanceof Function) {
                result = _appEntityService[action](Context, Data);
            } else {
                result = this.appEntityService.Get(Context, Data);
            }
            result.then((response) => {
                this.setRemoteCopyData(response);
                this.handleResponse(action, response);
                resolve(response);
            }).catch(response => {
                reject(response);
            });
        });
    }

    /**
     * 加载草稿
     *
     * @param {string} action
     * @param {*} [context={}]
     * @param {*} [data={}]
     * @param {boolean} [isloading]
     * @returns {Promise<any>}
     * @memberof AppGridService
     */
    public loadDraft(action: string, context: any = {}, data: any = {}, isloading?: boolean): Promise<any> {
        const { data: Data, context: Context } = this.handleRequestData(action, context, data, true);
        return new Promise((resolve: any, reject: any) => {
            let result: Promise<any>;
            const _appEntityService: any = this.appEntityService;
            if (_appEntityService[action] && _appEntityService[action] instanceof Function) {
                result = _appEntityService[action](Context, Data);
            } else {
                result = this.appEntityService.GetDraft(Context, Data);
            }
            result.then((response) => {
                if(response.data) {
                    Object.assign(response.data, { srfuf: '0' });
                    const keyField = this.appDeKeyFieldName.toLowerCase();
                    const editItems: Array<IPSDEGridEditItem> = this.controlInstance.getPSDEGridEditItems() || [];
                    if(editItems.length>0) {
                        const editItem: any = editItems.find((item: any) => {
                            return Object.is(item.name.toLowerCase(), keyField) && !Object.is(item.name.toLowerCase(), "srfkey");
                        })
                        if(editItem) {
                            response.data[keyField] = Util.createUUID();
                        }
                    }
                }
                this.setRemoteCopyData(response);
                this.handleResponse(action, response, true);
                resolve(response);
            }).catch(response => {
                reject(response);
            });
        });
    }

    /**
    * 前台逻辑
    * @param {string} action
    * @param {*} [context={}]
    * @param {*} [data={}]
    * @param {boolean} [isloading]
    * @returns {Promise<any>}
    * @memberof AppGridService
    */
    public frontLogic(action: string, context: any = {}, data: any = {}, isloading?: boolean): Promise<any> {
        const { data: Data, context: Context } = this.handleRequestData(action, context, data);
        return new Promise((resolve: any, reject: any) => {
            let result: Promise<any>;
            const _appEntityService: any = this.appEntityService;
            if (_appEntityService[action] && _appEntityService[action] instanceof Function) {
                result = _appEntityService[action](Context, Data);
            } else {
                return Promise.reject({ status: 500, data: { title: '失败', message: '系统异常' } });
            }
            result.then((response) => {
                this.handleResponse(action, response, true);
                resolve(response);
            }).catch(response => {
                reject(response);
            });
        })
    }

    /**
     * 表格聚合加载数据
     *
     * @param {string} action
     * @param {*} [context={}]
     * @param {*} [data={}]
     * @param {boolean} [isloading]
     * @returns {Promise<any>}
     * @memberof AppGridService
     */
    public getAggData(action: string,context: any = {},data: any = {}, isloading?: boolean): Promise<any> {
        const {data:Data,context:Context} = this.handleRequestData(action,context,data,true);
        return new Promise((resolve: any, reject: any) => {
            const _appEntityService: any = this.appEntityService;
            let result: Promise<any>;
            if (_appEntityService[action] && _appEntityService[action] instanceof Function) {
                result = _appEntityService[action](Context,Data, isloading);
            }else{
                result = Promise.reject({});
            }
            result.then((response) => {
                this.handleResponse(action, response);
                resolve(response);
            }).catch(response => {
                reject(response);
            });      
        });
    }

    /**
     * 处理请求数据
     * 
     * @param action 行为 
     * @param data 数据
     * @memberof AppGridService
     */
    public handleRequestData(action: string, context: any, data: any = {}, isMerge: boolean = false) {
        let mode: any = this.getMode();
        if (!mode && mode.getDataItems instanceof Function) {
            return data;
        }
        let dataItems: any[] = mode.getDataItems();
        let requestData: any = {};
        if (isMerge && (data && data.viewparams)) {
            Object.assign(requestData, data.viewparams);
        }
        dataItems.forEach((item: any) => {
            if (item && item.dataType && Object.is(item.dataType, 'FRONTKEY')) {
                if (item && item.prop) {
                    requestData[item.prop] = context[item.name];
                }
            } else {
                if (item && item.prop && item.name && (data[item.name] || Object.is(data[item.name], 0))) {
                    requestData[item.prop] = data[item.name];
                } else {
                    if (item.dataType && Object.is(item.dataType, "FORMPART")) {
                        Object.assign(requestData, data[item.name]);
                    }
                }
            }
        });
        let tempContext: any = JSON.parse(JSON.stringify(context));
        if (tempContext && tempContext.srfsessionid) {
            tempContext.srfsessionkey = tempContext.srfsessionid;
            delete tempContext.srfsessionid;
        }
        return { context: tempContext, data: requestData };
    }

    /**
     * 通过属性名称获取表单项名称
     * 
     * @param name 实体属性名称 
     * @memberof AppGridService
     */
    public getItemNameByDeName(name: string): string {
        let itemName = name;
        let mode: any = this.getMode();
        if (!mode && mode.getDataItems instanceof Function) {
            return name;
        }
        let dataItems: any[] = mode.getDataItems();
        dataItems.forEach((item: any) => {
            if (item.prop === name) {
                itemName = item.name;
            }
        });
        return itemName.trim();
    }

    /**
     * 设置远端数据
     * 
     * @param result 远端请求结果 
     * @memberof AppGridService
     */
    public setRemoteCopyData(result: any) {
        if (result && result.status === 200) {
            this.remoteCopyData = Util.deepCopy(result.data);
        }
    }

    /**
     * 获取远端数据
     * 
     * @memberof AppGridService
     */
    public getRemoteCopyData() {
        return this.remoteCopyData;
    }

    /**
     * 查询数据
     *
     * @param {string} action
     * @param {*} [context={}]
     * @param {*} [data={}]
     * @param {boolean} [isloading]
     * @returns {Promise<any>}
     * @memberof AppGridService
     */
    public search(action: string,context: any = {},data: any = {}, isloading?: boolean): Promise<any> {
        const {data:Data,context:Context} = this.handleRequestData(action,context,data,true);
        return new Promise((resolve: any, reject: any) => {
            const _appEntityService: any = this.appEntityService;
            let result: Promise<any>;
            if (_appEntityService[action] && _appEntityService[action] instanceof Function) {
                result = _appEntityService[action](Context,Data, isloading);
            }else{
                result =_appEntityService.FetchDefault(Context,Data, isloading);
            }
            result.then((response) => {
                this.setCopynativeData(response.data);
                this.handleResponse(action, response);
                resolve(response);
            }).catch(response => {
                reject(response);
            });      
        });
    }

    /**
     * 查询实体导出数据
     *
     * @param {string} action
     * @param {*} [context={}]
     * @param {*} [data={}]
     * @param {boolean} [isloading]
     * @returns {Promise<any>}
     * @memberof AppGridService
     */
    public searchDEExportData(action: string,context: any = {},data: any = {}, isloading?: boolean): Promise<any> {
        const {data:Data,context:Context} = this.handleRequestData(action,context,data,true);
        return new Promise((resolve: any, reject: any) => {
            const _appEntityService: any = this.appEntityService;
            let result: Promise<any>;
            if (_appEntityService[action] && _appEntityService[action] instanceof Function) {
                result = _appEntityService[action](Context,Data, isloading);
            }else{
                result =_appEntityService.FetchDefault(Context,Data, isloading);
            }
            result.then((response) => {
                let model: any = this.getMode();
                model.isDEExport = true;
                this.handleResponse(action, response);
                model.isDEExport = false;
                resolve(response);
            }).catch(response => {
                reject(response);
            });      
        });
    }

        /**
     * 处理请求数据(修改或增加数据)
     * 
     * @param action 行为 
     * @param data 数据
     * @memberof AppGridService
     */
    public handleRequestDataWithUpdate(action: string,context:any ={},data: any = {},isMerge:boolean = false){
        let model: any = this.getMode();
        if (!model && model.getDataItems instanceof Function) {
            return data;
        }
        let dataItems: any[] = model.getDataItems();
        let requestData:any = {};
        if(isMerge && (data && data.viewparams)){
            Object.assign(requestData,data.viewparams);
        }
        dataItems.forEach((item:any) =>{
            if(item && item.dataType && Object.is(item.dataType,'FRONTKEY')){
                if(item && item.prop && item.name ){
                    requestData[item.prop] = context[item.name];
                }
            }else{
                if(item && item.isEditable && item.prop && item.name && data.hasOwnProperty(item.name)){
                    requestData[item.prop] = data[item.name];
                }
            }
        });
        let tempContext:any = JSON.parse(JSON.stringify(context));
        if(tempContext && tempContext.srfsessionid){
            tempContext.srfsessionkey = tempContext.srfsessionid;
            delete tempContext.srfsessionid;
        }
        return {context:tempContext,data:requestData};
    }

    /**
     * 处理工作流数据
     * 
     * @param data 传入数据
     *  @memberof AppGridService
     */
    public handleWFData(data:any, isMerge:boolean = false){
        let model: any = this.getMode();
        if (!model && model.getDataItems instanceof Function) {
            return data;
        }
        let dataItems: any[] = model.getDataItems();
        let requestData:any = {};
        dataItems.forEach((item:any) =>{
            if(item && item.prop){
                if(item.dataType){
                    if(!Object.is(item.dataType,'QUERYPARAM')){
                        requestData[item.prop] = data[item.name];
                    }
                }else{
                    requestData[item.prop] = data[item.name];
                }  
            }
        });
        if(isMerge && (data.viewparams && Object.keys(data.viewparams).length > 0)){
            Object.assign(requestData,data.viewparams);
        }
        // 删除前端srffrontuf标识
        if(requestData.hasOwnProperty('srffrontuf')){
            delete requestData.srffrontuf;
        }
        //补充工作流所需主键
        requestData.srfkey = data[this.appDeCodeName.toLowerCase()];
        //补充全量数据
        requestData = this.fillNativeData(requestData);
        return requestData;
    }

    /**
     * 补充全量数据
     *
     * @param {*} [data]
     * @memberof AppGridService
     */
    public fillNativeData(data:any){
        if(this.copynativeData && this.copynativeData.length >0){
            const keyField = this.appDeKeyFieldName.toLowerCase();
            let targetData:any = this.copynativeData.find((item:any) =>{
                return item[keyField] === data.srfkey;
            })
            data = Object.assign(targetData,data);
            return data;
        }
    }

    /**
     * 提交工作流
     *
     * @param {string} action
     * @param {*} [context={}]
     * @param {*} [data={}]
     * @param {boolean} [isloading]
     * @param {*} [localdata]
     * @returns {Promise<any>}
     * @memberof AppGridService
     */
    public submitbatch(action: string,context: any = {}, data: any,localdata:any,isloading?: boolean): Promise<any> {
        let tempData:any = [];
        if(data && data.length > 0){
            data.forEach((item:any) => {
                let data:any = this.handleWFData(item,true);
                tempData.push(data);
            });
        }
        context = this.handleRequestData(action,context,data,true).context;
        return new Promise((resolve: any, reject: any) => {
            let result: Promise<any>;
            const _appEntityService: any = this.appEntityService;
            if (_appEntityService[action] && _appEntityService[action] instanceof Function) {
                result = _appEntityService[action](context,tempData, localdata,isloading);
            } else {
                result = this.appEntityService.wfSubmitBatch(context,tempData,localdata,isloading);
            }
            result.then((response) => {
                this.handleResponse(action, response);
                resolve(response);
            }).catch(response => {
                reject(response);
            });
        });
    }

    /**
     * 设置备份原生数据
     * 
     * @param data 远端请求结果 
     * @memberof AppGridService
     */
    public setCopynativeData(data:any){
        this.copynativeData = Util.deepCopy(data);
    }    
    
    /**
    * 获取备份原生数据
    * 
    * @memberof AppGridService
    */
   public getCopynativeData(){
       return this.copynativeData;
   } 
}