import { getSelectedAppCode } from "@/shared/api/request";

const storagePrefix = "hyapp-admin.menu-usage.v1";
const maxStoredItems = 80;
const dedupeWindowMs = 1000;

export function recordSecondLevelMenuVisit({ appCode, menus = [], now = Date.now(), pathname, storage, user }) {
    const safeStorage = storage || localStorageOrNull();
    if (!safeStorage || !user || !pathname) {
        return [];
    }
    const matchedItem = findSecondLevelNavItemByPath(pathname, menus);
    if (!matchedItem?.path) {
        return getFrequentSecondLevelMenus({ appCode, menus, storage: safeStorage, user });
    }

    const storageKey = menuUsageStorageKey(user, appCode);
    const currentItems = readUsageItems(storageKey, safeStorage);
    const previous = currentItems.find((item) => item.code === matchedItem.code);
    const previousVisitAt = Number(previous?.lastVisitedAtMs || 0);
    const shouldCount = previous?.path !== matchedItem.path || now - previousVisitAt > dedupeWindowMs;
    const nextItem = {
        code: matchedItem.code,
        count: (Number(previous?.count || 0) || 0) + (shouldCount ? 1 : 0),
        label: matchedItem.label,
        lastVisitedAtMs: now,
        parentCode: matchedItem.parentCode,
        parentLabel: matchedItem.parentLabel,
        path: matchedItem.path,
    };
    const nextItems = [nextItem, ...currentItems.filter((item) => item.code !== matchedItem.code)]
        .sort(compareUsageItems)
        .slice(0, maxStoredItems);
    writeUsageItems(storageKey, nextItems, safeStorage);
    return getFrequentSecondLevelMenus({ appCode, menus, storage: safeStorage, user });
}

export function getFrequentSecondLevelMenus({ appCode, limit = 8, menus = [], storage, user }) {
    const safeStorage = storage || localStorageOrNull();
    if (!safeStorage || !user) {
        return [];
    }
    const itemByCode = new Map(flattenSecondLevelNavItems(menus).map((item) => [item.code, item]));
    return readUsageItems(menuUsageStorageKey(user, appCode), safeStorage)
        .sort(compareUsageItems)
        .map((item) => {
            const currentItem = itemByCode.get(item.code);
            if (!currentItem?.path) {
                return null;
            }
            return {
                ...item,
                icon: currentItem.icon,
                label: currentItem.label,
                parentLabel: currentItem.parentLabel,
                path: currentItem.path,
            };
        })
        .filter(Boolean)
        .slice(0, limit);
}

export function findSecondLevelNavItemByPath(pathname, menus = []) {
    return flattenSecondLevelNavItems(menus)
        .filter((item) => isActiveRoute(pathname, item.path))
        .sort((left, right) => right.path.length - left.path.length)[0];
}

export function flattenSecondLevelNavItems(menus = []) {
    return menus.flatMap((parent) =>
        (parent.children || [])
            .filter((child) => child.path)
            .map((child) => ({
                ...child,
                parentCode: parent.code,
                parentLabel: parent.label,
            })),
    );
}

function menuUsageStorageKey(user, appCode) {
    const scope = user?.id || user?.account || "anonymous";
    const app = appCode || getSelectedAppCode() || "default";
    return `${storagePrefix}.${app}.${scope}`;
}

function readUsageItems(storageKey, storage) {
    try {
        const payload = JSON.parse(storage.getItem(storageKey) || "{}");
        return Array.isArray(payload.items) ? payload.items.filter((item) => item?.code && item?.path) : [];
    } catch {
        return [];
    }
}

function writeUsageItems(storageKey, items, storage) {
    storage.setItem(storageKey, JSON.stringify({ items, updatedAtMs: Date.now(), version: 1 }));
}

function compareUsageItems(left, right) {
    const countDiff = Number(right.count || 0) - Number(left.count || 0);
    if (countDiff !== 0) {
        return countDiff;
    }
    return Number(right.lastVisitedAtMs || 0) - Number(left.lastVisitedAtMs || 0);
}

function isActiveRoute(activePath, itemPath) {
    if (!itemPath) {
        return false;
    }
    if (activePath === itemPath) {
        return true;
    }
    return activePath.startsWith(`${itemPath}/`);
}

function localStorageOrNull() {
    try {
        return globalThis.localStorage || null;
    } catch {
        return null;
    }
}
