import { ref, toRefs, readonly } from 'vue'
import { createRouter, RouterOptions, RouteRecordRaw, RouteRecordName } from 'vue-router'

interface HistoryStack {
    name?: RouteRecordName,
    title: string,
    fullPath: string,
    redirected: boolean,
}

interface HistoryState {
    historyStacks: HistoryStack[]; // 已访问的路由列表
    historyIndex: number; // 当前历史索引位置
    excludeViews: string[]; // 不缓存的页面
    actionName: '' | 'push' | 'replace' | 'forward' | 'back'; // 当前路由动作
}

export default new (class {
    private storageKey = 'history_pc';

    private _state = ref<HistoryState>({
        historyStacks: [],
        historyIndex: 0,
        excludeViews: [],
        actionName: '',
    })

    /** 只读状态 */
    state;

    constructor() {
        const state = sessionStorage.getItem(this.storageKey);
        if (state) {
            const data: HistoryState = JSON.parse(state);
            this._state.value = data;
        }
        this.state = readonly(toRefs(this._state.value));
    }

    /**
     * 创建路由
     * @param options 
     * @returns 
     */
    create = (options: RouterOptions) => {
        const router = createRouter(options);
        const { push, replace, go, forward, back } = router;
        const { actionName, excludeViews } = toRefs(this._state.value);

        // 添加
        router.push = (to: RouteRecordRaw) => {
            actionName.value = 'push';
            return push(to);
        }

        // 替换
        router.replace = (to: RouteRecordRaw) => {
            actionName.value = 'replace';
            return replace(to);
        }

        // 前进后退
        router.go = (delta: number) => {
            if (delta > 0) {
                actionName.value = 'forward';
            }
            if (delta < 0) {
                actionName.value = 'back';
            }
            go(delta);
        }

        // 前进
        router.forward = () => {
            actionName.value = 'forward';
            forward();
        }

        // 后退
        router.back = () => {
            actionName.value = 'back';
            back();
        }

        router.beforeResolve((to) => {
            if (to.meta.keepAlive) {
                this.addHistory({
                    name: to.name || to.path,
                    title: to.meta.title as string ?? '标签页',
                    fullPath: to.fullPath,
                    redirected: !!to.redirectedFrom,
                });
            }
        })

        router.afterEach(() => {
            excludeViews.value = [];
        })

        return router;
    }

    /**
     * 添加历史记录
     * @param route 
     */
    private addHistory = (route: HistoryStack) => {
        const { historyStacks, historyIndex, excludeViews, actionName } = toRefs(this._state.value);
        const index = historyStacks.value.findIndex((e) => e.name === route.name);

        if (index > -1) {
            historyStacks.value[index] = route;
            historyIndex.value = index;
        } else {
            if (actionName.value === 'replace') {
                const lastIndex = historyStacks.value.length - 1;
                const lastView = historyStacks.value[lastIndex];

                if (lastView) {
                    excludeViews.value.push(lastView.name as string);
                    historyStacks.value[lastIndex] = route; // 更新最后一条记录
                } else {
                    historyStacks.value.push(route);
                }
            } else {
                // 忽略重定向的页面
                if (!route.redirected) {
                    historyStacks.value.push(route);
                    historyIndex.value = historyStacks.value.length - 1;
                }
            }
        }

        actionName.value = '';
        sessionStorage.setItem(this.storageKey, JSON.stringify(this._state.value));
    }

    /**
     * 移除历史记录
     * @param routeName 
     */
    removeHistory = (routeName?: string) => {
        const { historyStacks, excludeViews } = toRefs(this._state.value);
        if (routeName) {
            const index = historyStacks.value.findIndex((e) => e.name === routeName);
            excludeViews.value.push(routeName);

            if (index > -1) {
                historyStacks.value.splice(index, 1);
                sessionStorage.setItem(this.storageKey, JSON.stringify(this._state.value));
            }
        } else {
            historyStacks.value = [] // 待优化，清除缓存
        }
    }
})