import { message } from 'antd'
import * as service from '../services/index'
import URLS from '../constants/url'

// const generateShareCode = () => {
//     return Math.random().toString(36).substr(2).toUpperCase();
// }

export default {
    namespace: 'dashboard',
    state: {
        originData: {
            listLoading: false,
            list: [],
            newOne: {
                defaultSelectedGroups: [],
                defaultSelectedUsers: []
            },
            menuLoading: false,
            menuList: [],
            menuTree: [],
            menuExpandedKeys: ['-1'],
            menuSelectedKeys: [],
            menuFilterLabel: '',
            menuAutoExpandParent: true,
            currentMenu: null,
            currentMenuParents: [],
            filterLabel: '',
            filterItems: [ // 可选过滤字段
                { name: 'name', label: '报表名称', type: 'string' },
                // { name: 'description', label: '备注', type: 'string' },
                { name: 'creatorName', label: '创建人', type: 'string' },
                { name: 'createTime', label: '创建时间', type: 'date' },
            ],
            filterItem: { name: 'name', label: '报表名称', type: 'string' }, // 已选过滤字段
            listScrollTop: 0, // 记录滚动条位置
        }
    },
    reducers: {
        list(state, action) {
            let list = action.list;
            return Object.assign({}, state, {list});
        },
        setFilterItem(state, action) {
            const { item } = action;
            return Object.assign({}, state, {filterItem: item, filterLabel: ''});
        },
        setFilterLabel(state, action) {
            let { label } = action;
            return Object.assign({}, state, {filterLabel: label});
        },
        setField(state, action) {
            const { name, value } = action;
            let obj = {};
            obj[name] = value;
            return Object.assign({}, state, obj);
        },
        setFields(state, action) {
            const { fields } = action;
            let obj = {};
            fields.map(f => (obj[f.name] = f.value));
            return Object.assign({}, state, obj);
        },
        reset(state, action) {
            let newState = Object.assign({}, state, state.originData);
            return Object.assign({}, newState);
        },
    },
    effects: {
        *fetchList(action, {select, call, put}) {
            const { pageNum, pageSize } = action;
            const body = {
                pageNum: pageNum || 1,
                pageSize: pageSize || 999999999
            }
            try {
                const dashboard = yield select(state => state.dashboard);
                if(!action.mandatory && dashboard.list.length > 0) {
                    return;
                }
                if(!action.silent) {
                    yield put({ type: 'setField', name: 'listLoading', value: true });
                }
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_LIST,
                    method: 'GET',
                    body
                });
                if(res.code > 0) {
                    const resData = res.data.list;
                    let list = resData.map(d => {
                        let items = d.bdConfiguration ? JSON.parse(d.bdConfiguration) : [];

                        const dataSources = [];
                        const dataConnects = [];
                        items.forEach(item => {
                            if(item.viewType === 'chart') {
                                if(!dataSources.find(ad => ad.code === item.dataSourceCode)) {
                                    dataSources.push({
                                        code: item.dataSourceCode,
                                        name: item.dataSourceName
                                    })
                                }
                                if(!dataConnects.find(ad => ad.code === item.dataSourceCode)) {
                                    dataConnects.push({
                                        code: item.dataConnectCode,
                                        name: item.dataConnectName
                                    })
                                }
                            }
                        })
    
                        return {
                            key: d.id + '',
                            code:  d.id+'',
                            menuCode: d.menuId + '',
                            name: d.bdName,
                            items: items,
                            description: d.bdNote || '',
                            creatorCode: d.createId + '',
                            creatorName: d.createBy,
                            createTime: d.createDate,
                            shareCode: d.bdCode,
                            dataSources: dataSources,
                            dataConnects: dataConnects,
                            chartCodes: d.chartIds ? d.chartIds.split(',') : [],
                            demo: d.demo
                        }
                    })
                    yield put({ type: 'list', list: list });
                }else {
                    message.error('请求报表列表失败: ' + res.msg);
                }
            }catch(e) {
                message.error('请求报表列表失败: ' + e.message)
            }finally {
                yield put({ type: 'setField', name: 'listLoading', value: false });
            }
        },
        *remoteDetail(action, { select, call, put }) {
            const code = action.code;
            if(!code){
                return
            }
            try {
                yield put({ type: 'dashboardDesigner/silentSetField', name: 'loading', value: true });
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_DETAIL,
                    method: 'GET',
                    body: {
                        id: code
                    }
                });
                if(res.code > 0) {
                    const resData = res.data;
                    let items = resData.bdConfiguration ? JSON.parse(resData.bdConfiguration) : [];
                    let relationColumns = resData.relationColumns ? JSON.parse(resData.relationColumns) : [];
                    let chartCodes = resData.chartIds ? resData.chartIds.split(',') : [];
                    const main = yield select(state => state.main);
                    const { currentUser } = main;

                    const allDataSources = items.map(item => {
                        if(item.viewType === 'chart') {
                            return {
                                code: item.dataSourceCode + '',
                                name: item.dataSourceName
                            }
                        }else {
                            return null
                        }
                    }).filter(item => !!item);

                    const dataSources = [];
                    allDataSources.forEach(ad => {
                        if(!dataSources.find(d => d.code === ad.code)) {
                            dataSources.push(ad);
                        }
                    });

                    let data = {
                        code:  resData.id+'',
                        name: resData.bdName,
                        menuCode: resData.menuId + '',
                        items: items,
                        description: resData.bdNote || '',
                        creatorCode: resData.createId + '',
                        creatorName: resData.createBy,
                        createTime: resData.createDate,
                        dataSources: dataSources,
                        relationColumns: relationColumns,
                        editMode: currentUser.code === resData.createId + '',
                        filters: JSON.parse((resData.filters|| "[]")),
                        shareCode: resData.bdCode,
                        chartCodes: chartCodes,
                        demo: resData.demo,
                        theme: resData.theme
                    }

                    let fields = [];
                    for(let key in data) {
                        fields.push({
                            name: key,
                            value: data[key]
                        })
                    }
                    yield put({ type: 'dashboardDesigner/silentSetFields', fields: fields });
                    return data;
                }else {
                    message.error('解析报表错误: ' + res.msg);
                    return false;
                }
            }catch(e) {
                message.error('解析报表错误: ' + e.message);
                return false;
            }finally {
                yield put({ type: 'dashboardDesigner/silentSetField', name: 'loading', value: false });
            }
        },
        *remoteAdd(action, { select, call, put }) {
            yield message.error('未指定目录');
        },
        *remoteQucikAdd(action, { select, call, put }) {
            const { menuCode } = action;
            try {
                const dashboardDesigner = yield select(state => state.dashboardDesigner);
                const { name, items, description, relationColumns, filters } = dashboardDesigner;
                let body = {
                    bdName: name,
                    bdNote: description,
                    bdConfiguration: JSON.stringify(items),
                    relationColumns: JSON.stringify(relationColumns),
                    filters: JSON.stringify(filters) || "",
                    // bdCode: generateShareCode(),
                    thumbnail: '',
                    chartIds: '',
                    menuId: menuCode,
                }
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_ADD,
                    body: body
                });
                if(res.code > 0) {
                    yield put({ type: 'remoteMenuDashboardList', menuCode });
                    yield put({ type: 'main/redirect', path: '/dashboard/' + res.data });
                }else {
                    message.error('保存失败: ' + res.msg);
                } 
            }catch(e) {
                message.error('保存失败: ' + e.message);
            }
        },
        *remoteModify(action, { select, call, put }) {
            const { hideMessage } = action
            try {
                const dashboardDesigner = yield select(state => state.dashboardDesigner);
                const dashboard = yield select(state => state.dashboard);
                const { code, name, items, description, relationColumns, filters, chartCodes, shareCode, theme } = dashboardDesigner;
                let body = {
                    id: code,
                    bdName: name,
                    bdNote: description,
                    bdConfiguration: JSON.stringify(items.sort((a, b) => {
                        return a.layout.y - b.layout.y || a.layout.x - b.layout.x
                    }).map(item => {
                        if(item.chartType === 'dataView') {
                            return {
                                ...item,
                                chartOption: {
                                    total: 0,
                                    page: 1,
                                    pageSize: 0, // 保存为0以保证在tableView组件渲染时getTableLayout方法中总能触发取数
                                    columns: [],
                                    dataSource: []
                                }
                            }
                        }else {
                            return { ...item, chartOption: null }
                        }
                    })),
                    relationColumns: JSON.stringify(relationColumns),
                    filters: JSON.stringify(filters) || "",
                    chartIds: chartCodes.join(','),
                    bdCode: shareCode,
                    theme: theme
                }
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_UPDATE,
                    body: body
                });
                if(res.code > 0) {
                    yield put({ type: 'fetchList', mandatory: true });
                    yield put({ type: 'dashboardDesigner/silentSetField', name: 'dirty', value: false });
                    let menu = dashboard.menuList.find(l => l.code === dashboardDesigner.menuCode);
                    yield put({ type: 'remoteSetMenu', dashboard: { code }, menu })
                    !hideMessage && message.success('保存成功');
                }else {
                    !hideMessage && message.error('保存失败: ' + res.msg);
                } 
            }catch(e) {
                !hideMessage && message.error('保存失败: ' + e.message);
            }
        },
        *remoteDelete(action, { select, call, put }) {
            const dashboard = yield select(state => state.dashboard);
            const code = action.code;
            let list = dashboard.list;
            try {
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_DELETE,
                    body: code
                });
                if(res.code > 0) {
                    for(let i = 0; i < list.length; i++) {
                        if(list[i].code === code) {
                            list.splice(i, 1);
                            break;
                        }
                    }
                    yield put({ type: 'list', list: list });
                    message.success('删除成功');
                }else {
                    message.error('删除失败: ' + res.msg);
                }
            }catch(e) {
                message.error('删除失败: ' + e.message);
            }
        },
        *remoteMenuTree(action, { put, call, select }) {
            const dashboard = yield select(state => state.dashboard);
            if(!action.mandatory && dashboard.menuTree.length > 0) {
                return {menuList: dashboard.menuList, menuTree: dashboard.menuTree};
            }
            try{
                if(!action.silent) {
                    yield put({ type: 'setField', name: 'menuLoading', value: true });
                }
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_MENU_TREE,
                    method: 'GET'
                })
                if(res.code > 0) {
                    const resTree = res.data;
                    const list = [];
                    let fun = (tree, pcode) => {
                        let newTree = tree.map((t, i) => {
                            let ch = [];
                            if(t.children && t.children.length > 0) {
                                ch = fun(t.children, t.id);
                            }
                            let obj = {
                                key: t.id + '-' + i,
                                code: t.id + '',
                                pcode: pcode + '',
                                name: t.name,
                                type: t.type,
                                index: i,
                                children: ch,
                                childrenCount: ch.length
                            }
                            list.push(obj);
                            return obj
                        });
                        return newTree;
                    }
                    let menuList = list;
                    let menuTree = fun(resTree, '-1');
                    yield put({ type: 'setFields', fields: [
                        { name: 'menuList', value: menuList },
                        { name: 'menuTree', value: menuTree }
                    ] });
                    return {menuList, menuTree};
                }else {
                    message.error('获取报表目录失败: ' + res.msg);
                    return false;
                }
            }catch(e) {
                message.error('获取报表目录失败: ' + e.message);
                return false;
            }finally {
                yield put({ type: 'setField', name: 'menuLoading', value: false });
            }
        },
        *remoteAddMenu(action, { put, call, select }) {
            const { menu } = action;
            try {
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_MENU_ADD,
                    method: 'POST',
                    body: {
                        id: menu.code,
                        index: menu.index,
                        name: menu.name,
                        parentId: menu.pcode === '-1' ? 0 : menu.pcode
                    }
                })
                if(res.code > 0) {
                    let menuCode = res.data + '';
                    return menuCode;
                }else {
                    message.error('添加报表目录失败: ' + res.msg);
                    return false;
                }
            }catch(e) {
                message.error('添加报表目录失败: ' + e.message);
            }
        },
        *remoteModifyMenu(action, { put, call, select }) {
            const { menu } = action;
            const res = yield call(service.fetch, {
                url: URLS.DASHBOARD_MENU_UPDATE,
                body: {
                    id: menu.code,
                    index: menu.index,
                    name: menu.name,
                    parentId: menu.pcode === '-1' ? '0' : menu.pcode
                }
            });
            if(res.code > 0) {
                yield put({ type: 'remoteMenuTree', mandatory: true });
                return menu;
            }else {
                message.error('修改报表目录失败: ' + res.msg);
                return false;
            }
        },
        *transferMenu(action, { put, call, select }) {
            const { dropKey, dragKey } = action;
            const dashboard = yield select(state => state.dashboard);
            const { menuList } = dashboard;
            let menu = menuList.find(l => l.code === dragKey);
            menu.pcode = dropKey;
            yield put({ type: 'remoteModifyMenu', menu });
        },
        *remoteDeleteMenu(action, { put, call, select }) {
            const { menu } = action;
            const res = yield call(service.fetch, {
                url: URLS.DASHBOARD_MENU_DELETE + '/' + menu.code,
            });
            if(res.code > 0) {
                yield put({ type: 'remoteMenuTree', mandatory: true });
                return true;
            }else {
                message.error('删除报表目录失败: ' + res.msg);
                return false;
            }
        },
        *remoteSetMenu(action, { put, call, select }) {
            const { dashboard: currentDashboard, menu } = action;
            try {
                const dashboard = yield select(state => state.dashboard);
                const getParens = (menu) => {
                    const { menuList } = dashboard;
                    let pmenus = [menu];
                    let fmenu = [{ code: '-1', name: '报表目录' }].concat(menuList).find(l => l.code === menu.pcode);
                    if(fmenu) {
                        pmenus = pmenus.concat(getParens(fmenu));
                    }
                    return pmenus;
                }

                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_SET_MENU,
                    body: {
                        dashBoardId: currentDashboard.code,
                        menuId: menu.code
                    },
                })
                if(res.code > 0) {
                    yield put({ type: 'remoteMenuDashboardList', menuCode: menu.code });
                    yield put({ type: 'setFields', fields: [
                        { name: 'currentMenu', value: menu },
                        { name: 'currentMenuParents', value: getParens(menu) },
                        { name: 'menuSelectedKeys', value: [menu.code] },
                        { name: 'menuExpandedKeys', value: [menu.code] },
                        { name: 'menuAutoExpandParent', value: true },
                    ] })
                }else {
                    message.error('移动到目录失败: ' + res.msg);
                }
            }catch(e) {
                message.error('移动到目录失败: ' + e.message);
            }
        },
        *remoteMenuDashboardList(action, { put, call, select }) {
            const { menuCode } = action;
            try {
                if(!action.silent) {
                    yield put({ type: 'setField', name: 'listLoading', value: true });
                }
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_MENU_DASHBOARD_LIST + '/' + menuCode,
                    method: 'GET',
                })
                if(res.code > 0) {
                    const resData = res.data;
                    let list = resData.map(d => {
                        let items = d.bdConfiguration ? JSON.parse(d.bdConfiguration) : [];

                        const dataSources = [];
                        const dataConnects = [];
                        items.forEach(item => {
                            if(item.viewType === 'chart') {
                                if(!dataSources.find(ad => ad.code === item.dataSourceCode)) {
                                    dataSources.push({
                                        code: item.dataSourceCode,
                                        name: item.dataSourceName
                                    })
                                }
                                if(!dataConnects.find(ad => ad.code === item.dataSourceCode)) {
                                    dataConnects.push({
                                        code: item.dataConnectCode,
                                        name: item.dataConnectName
                                    })
                                }
                            }
                        })
    
                        return {
                            key: d.id + '',
                            code:  d.id+'',
                            name: d.bdName,
                            menuCode: d.menuId + '',
                            items: items,
                            description: d.bdNote || '',
                            creatorCode: d.createId + '',
                            creatorName: d.createBy,
                            createTime: d.createDate,
                            shareCode: d.bdCode,
                            dataSources: dataSources,
                            dataConnects: dataConnects,
                            chartCodes: d.chartIds ? d.chartIds.split(',') : [],
                            demo: d.demo
                        }
                    })
                    yield put({ type: 'list', list: list });
                }else {
                    message.error('获取报表列表失败: ' + res.msg);
                }
            }catch(e) {
                message.error('获取报表列表失败: ' + e.message);
            }finally {
                yield put({ type: 'setField', name: 'listLoading', value: false });
            }
        },
        *share(action, { put, call, select }) {
            const { code, targets } = action;
            const body = {
                stId: code+'',
                type: 'dashboard',
                obj: targets.map(t => ({
                    obId: t.code,
                    objectType: t.isGroup ? '0' : '1'
                }))
            };
            try {
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_SHARE,
                    body
                });
                if(res.code > 0) {
                    message.success('设置分发对象成功');
                }else {
                    message.error('设置分发对象失败: ' + res.msg);
                }
            }catch(e) {
                message.error('分发失败: ' + e.message);
            }
        },
        *shareList(action, { put, call, select }) {
            const { code } = action;
            const body = code;
            const res = yield call(service.fetch, {
                url: URLS.DASHBOARD_SHARE_LIST,
                body
            });
            return res;
        },
        *transfer(action, { put, call, select }) {
            const { userCode, dashboardCode } = action;
            const body = {
                userId: userCode,
                id: dashboardCode
            };
            try {
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_TRANSFER,
                    body
                });
                if(res.code > 0) {
                    const dashboard = yield select(state => state.dashboard);
                    const list = dashboard.list;
                    for(let i = 0; i < list.length; i++) {
                        if(list[i].code === dashboardCode) {
                            list.splice(i, 1);
                            break;
                        }
                    }
                    yield put({ type: 'list', list });
                    message.success('移交成功');
                }else {
                    message.error('移交失败: ' + res.msg);
                }
            }catch(e) {
                message.error('移交失败: ' + e.message);
            }
        },
        *remoteShareDetail(action, { select, call, put }) {
            const code = action.code;
            if(!code){
                return
            }
            try {
                yield put({ type: 'dashboardDesigner/silentSetField', name: 'loading', value: true });
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_SHARE_DETAIL_BY_CODE,
                    method: 'GET',
                    allow: true,
                    body: {
                        code: code
                    }
                });
                if(res.code > 0) {
                    const resData = res.data;
                    let items = resData.bdConfiguration ? JSON.parse(resData.bdConfiguration) : [];
                    let relationColumns = resData.relationColumns ? JSON.parse(resData.relationColumns) : [];
                    let chartCodes = resData.chartIds ? resData.chartIds.split(',') : [];
                    const main = yield select(state => state.main);
                    const { currentUser } = main;

                    const allDataSources = items.map(item => {
                        if(item.viewType === 'chart') {
                            return {
                                code: item.dataSourceCode,
                                name: item.dataSourceName
                            }
                        }else {
                            return null
                        }
                    }).filter(item => !!item);

                    const dataSources = [];
                    allDataSources.forEach(ad => {
                        if(!dataSources.find(d => d.code === ad.code)) {
                            dataSources.push(ad);
                        }
                    });

                    let data = {
                        code:  resData.id+'',
                        name: resData.bdName,
                        menuCode: resData.menuId + '',
                        items: items,
                        description: resData.bdNote || '',
                        creatorCode: resData.createId + '',
                        creatorName: resData.createBy,
                        createTime: resData.createDate,
                        dataSources: dataSources,
                        relationColumns: relationColumns,
                        editMode: currentUser.code === resData.createId + '',
                        filters: JSON.parse((resData.filters|| "[]")),
                        shareCode: resData.bdCode,
                        chartCodes: chartCodes,
                        demo: resData.demo,
                        theme: resData.theme
                    }

                    let fields = [];
                    for(let key in data) {
                        fields.push({
                            name: key,
                            value: data[key]
                        })
                    }
                    yield put({ type: 'dashboardDesigner/silentSetFields', fields: fields });
                }else {
                    message.error('解析报表错误: ' + res.msg);
                }
            }catch(e) {
                message.error('解析报表错误: ' + e.message);
            }finally {
                yield put({ type: 'dashboardDesigner/silentSetField', name: 'loading', value: false });
            }
        },
        *getShareKey (action, { select, call, put }) {
            const record = action.record;
            const delay = action.delay;
            if(!record){
                return
            }
            try {
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_GET_SHAREKEY,
                    method: 'POST',
                    body: {
                        id: record.code,
                        delay: delay
                    }
                });
                if(res.code > 0) {
                    const resData = res.data;
                    return resData;
                }else {
                    message.error('生成分享链接失败: ' + res.msg);
                }
            }catch(e) {
                message.error('生成分享链接失败: ' + e.message);
            }
        },
        *remoteShareKeyDetail(action, { select, call, put }) {
            const code = action.code;
            if(!code){
                return
            }
            try {
                yield put({ type: 'dashboardDesigner/silentSetField', name: 'loading', value: true });
                const res = yield call(service.fetch, {
                    url: URLS.DASHBOARD_SHARE_DETAIL_BY_KEY,
                    method: 'GET',
                    allow: true,
                    body: {
                        data: code
                    }
                });
                if(res.code > 0) {
                    const resData = res.data;
                    let items = resData.bdConfiguration ? JSON.parse(resData.bdConfiguration) : [];
                    let relationColumns = resData.relationColumns ? JSON.parse(resData.relationColumns) : [];
                    let chartCodes = resData.chartIds ? resData.chartIds.split(',') : [];
                    const main = yield select(state => state.main);
                    const { currentUser } = main;

                    const allDataSources = items.map(item => {
                        if(item.viewType === 'chart') {
                            return {
                                code: item.dataSourceCode,
                                name: item.dataSourceName
                            }
                        }else {
                            return null
                        }
                    }).filter(item => !!item);

                    const dataSources = [];
                    allDataSources.forEach(ad => {
                        if(!dataSources.find(d => d.code === ad.code)) {
                            dataSources.push(ad);
                        }
                    });

                    let data = {
                        code:  resData.id+'',
                        name: resData.bdName,
                        menuCode: resData.menuId + '',
                        items: items,
                        description: resData.bdNote || '',
                        creatorCode: resData.createId + '',
                        creatorName: resData.createBy,
                        createTime: resData.createDate,
                        dataSources: dataSources,
                        relationColumns: relationColumns,
                        editMode: currentUser.code === resData.createId + '',
                        filters: JSON.parse((resData.filters|| "[]")),
                        shareCode: resData.bdCode,
                        chartCodes: chartCodes,
                        demo: resData.demo,
                        theme: resData.theme
                    }

                    let fields = [];
                    for(let key in data) {
                        fields.push({
                            name: key,
                            value: data[key]
                        })
                    }
                    yield put({ type: 'dashboardDesigner/silentSetFields', fields: fields });
                }else {
                    message.error('解析报表错误: ' + res.msg);
                }
            }catch(e) {
                message.error('解析报表错误: ' + e.message);
            }finally {
                yield put({ type: 'dashboardDesigner/silentSetField', name: 'loading', value: false });
            }
        },
        *copy(action, { select, call, put }) {
            const { dashboardCode, dataConnectCode } = action;

            const res = yield call(service.fetch, {
                url: URLS.DASHBOARD_COPY,
                body: {
                    dashboardId: dashboardCode,
                    dataSourceId: dataConnectCode
                }
            });
            if(res.code > 0) {
                message.success('复制成功');
                // yield put({ type: 'fetchList', mandatory: true });
                const dashboard = yield select(state => state.dashboard);
                yield put({ type: 'remoteMenuDashboardList', menuCode: dashboard.currentMenu.code });
                yield put({ type: 'dataSource/fetchList', mandatory: true });
                yield put({ type: 'chart/fetchList', mandatory: true });
                return true;
            }else {
                message.error('复制失败: ' + res.msg);
                return false;
            }
        }
    },
    subscriptions: {
        setup({ dispatch, history}) {
            dispatch({ type: 'reset' });
        }
    }
}