import globalConfig from '@/config';
import { createLocalStorage, StorageOptions, decryptKey } from '@/utils/storage';

/**
 * 创建 localStorage 工具实例
 * @see 在 src/utils/storage 的基础上，添加了命名空间，如果 encryptKey 为 false，能有效避免多个应用在同一个域名下的数据冲突。
 * @param opts {StorageOptions} 本实例使用的全局配置
 * @returns
 */
function createLocalTools(storageOptions: StorageOptions = {}) {
    const ls = createLocalStorage(storageOptions);

    /**
     * 保存数据
     * @param key
     * @param value
     * @param opts 当传递了 opts 时，opts 中存在的配置项会覆盖当前实例的全局配置中的配置项。
     */
    function setLocal<T = any>(key: string, value: T, opts?: StorageOptions) {
        ls.set<T>(`${globalConfig.app.storageNameSpace}${key}`, value, opts);
    }

    /**
     * 读取数据
     * @param key
     * @param opts 当传递了 opts 时，opts 中存在的配置项会覆盖当前实例的全局配置中的配置项。
     * @returns
     */
    function getLocal<T>(key: string, opts?: StorageOptions) {
        return ls.get<T>(`${globalConfig.app.storageNameSpace}${key}`, opts);
    }

    /**
     * 删除数据
     * @param key
     * @param opts 当传递了 opts 时，opts 中存在的配置项会覆盖当前实例的全局配置中的配置项。
     */
    function removeLocal(key: string, opts?: StorageOptions) {
        ls.remove(`${globalConfig.app.storageNameSpace}${key}`, opts);
    }

    /**
     * 清除 localStorage 中的所有数据。**慎用**
     */
    function clearLocal() {
        const removedKeys = [];

        for (let i = 0; i < window.localStorage.length; i++) {
            const key = window.localStorage.key(i);
            if (!key) continue;

            // 先检查原始 key 是否属于当前命名空间
            if (key.startsWith(globalConfig.app.storageNameSpace)) {
                removedKeys.push(key);
                continue;
            }

            // 如果不是，尝试解密后检查是否属于当前命名空间
            const decryptedKey = decryptKey(key);
            if (decryptedKey && decryptedKey.startsWith(globalConfig.app.storageNameSpace)) {
                removedKeys.push(key);
            }
        }

        // 删除所有匹配的 key
        for (const key of removedKeys) {
            ls.remove(key, { encryptKey: false });
        }
    }

    return { setLocal, getLocal, removeLocal, clearLocal };
}

const secureLocalStorage = createLocalTools({ encryptKey: true, encryptData: true });

export { createLocalTools, secureLocalStorage };
