/*
 * -------------------------------------------------------------------------
 * This file is part of the MindStudio project.
 * Copyright (c) 2025 Huawei Technologies Co.,Ltd.
 *
 * MindStudio is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *          http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * -------------------------------------------------------------------------
 */
import { store } from '../store';
import { runInAction } from 'mobx';
import type { NotificationHandler } from './defs';
import i18n from '@insight/lib/i18n';
import { workerDestroy } from '@/leaksWorker/blockWorker/worker';
import { errorCenter, ErrorCode, WsError } from '@insight/lib';
import { workerDestroy as stateWorkerDestroy } from '@/leaksWorker/stateWorker/worker';
import { LEAKS_WORKER_INFO_DEFAULT, MARK_LINE_POSITION_DEFAULT, STATE_WORKER_INFO_DEFAULT } from '@/entity/session';

interface ImportFileTreeNode {
    filePath?: string;
    fileDir?: string;
    path?: string;
    children?: ImportFileTreeNode[];
}

interface RemoteImportData {
    dataSource?: {
        selectedFilePath?: string;
        projectPath?: string | string[];
    };
    importResult?: {
        isLeaks?: boolean;
        children?: ImportFileTreeNode[];
    };
}

interface MemSnapshotProgressData {
    fileId?: string;
    progress?: number;
}

const isMemSnapshotFile = (filePath: unknown): filePath is string => {
    if (typeof filePath !== 'string') {
        return false;
    }
    const lowerPath = filePath.toLowerCase();
    return lowerPath.endsWith('.pkl') || lowerPath.endsWith('.pickle');
};

const normalizeFilePath = (filePath: string): string => filePath.replace(/\\/g, '/');

const findMemSnapshotFile = (nodes?: ImportFileTreeNode[]): string => {
    if (!Array.isArray(nodes)) {
        return '';
    }
    for (const node of nodes) {
        const filePath = [node.filePath, node.path, node.fileDir].find(isMemSnapshotFile);
        if (filePath) {
            return filePath;
        }
        const childFilePath = findMemSnapshotFile(node.children);
        if (childFilePath) {
            return childFilePath;
        }
    }
    return '';
};

const getImportedMemSnapshotFile = (data: RemoteImportData): string => {
    const selectedFilePath = data.dataSource?.selectedFilePath;
    if (isMemSnapshotFile(selectedFilePath)) {
        return selectedFilePath;
    }
    const projectPath = data.dataSource?.projectPath;
    if (isMemSnapshotFile(projectPath)) {
        return projectPath;
    }
    if (Array.isArray(projectPath)) {
        const filePath = projectPath.find(isMemSnapshotFile);
        if (filePath) {
            return filePath;
        }
    }
    return findMemSnapshotFile(data.importResult?.children);
};

const clearMemSnapshotParseProgress = (session: any): void => {
    session.memSnapshotParseLoading = false;
    session.memSnapshotParseProgress = 0;
    session.memSnapshotParseFileId = '';
};

const clampProgress = (progress: unknown): number => {
    if (typeof progress !== 'number' || Number.isNaN(progress)) {
        return 0;
    }
    return Math.min(100, Math.max(0, Math.round(progress)));
};

export const setTheme: NotificationHandler = (data): void => {
    window.setTheme(Boolean(data.isDark));
};

export const updateSessionHandler: NotificationHandler = (data): void => {
    const { sessionStore } = store;
    const session = sessionStore.activeSession;
    runInAction(() => {
        if (!session || typeof session !== 'object' || typeof data !== 'object') {
            return;
        }
        const dataKeys = Object.keys(data);
        const sessionKeys = Object.keys(session);
        dataKeys.forEach((key: string) => {
            if (sessionKeys.includes(key)) {
                (session as unknown as Record<string, unknown>)[key] = data[key];
            }
        });
    });
};

export const switchLanguageHandler: NotificationHandler = (data): void => {
    const session = store.sessionStore.activeSession;
    const lang = data.lang as 'zhCN' | 'enUS';
    if (session) {
        runInAction(() => {
            session.language = lang;
        });
    }
    i18n.changeLanguage(lang);
};
const commonRestore = (session: any): void => {
    session.maxTime = 0;
    session.minTime = 0;
    session.legendSelect = {};
    session.synStartTime = 0;
    session.synEndTime = 0;
};
const funcRestore = (session: any): void => {
    session.funcData = { traces: [], maxTimestamp: 0, minTimestamp: 0 };
    session.threadId = '';
    session.threadOps = [];
    session.searchFunc = [];
    session.funcOptions = [];
    session.maxDepth = 0;
    session.allowTrim = true;
};
const barRestore = (session: any): void => {
    session.deviceId = '';
    session.eventType = '';
    session.deviceIdOpts = [];
    session.typeOpts = [];
    session.allocationData = { allocations: [], maxTimestamp: 0, minTimestamp: 0 };
    session.blockData = { blocks: [], minSize: 0, maxSize: 0, minTimestamp: 0, maxTimestamp: 0 };
    session.firstOffset = 0;
    session.lastOffset = 0;
    session.markLineshow = 'none';
    session.contextMenu = { visible: false, xPos: 0, yPos: 0 };
    session.allowMark = true;
    session.menuItems = [];
    session.firstLastStamps = { first: 0, last: 0 };
    session.threadFlag = false;
};
const sliceRestore = (session: any): void => {
    session.memoryData = { size: 0, name: '', subNodes: [] };
    session.memoryStamp = 0;
};
const blocksDetailsRestore = (session: any): void => {
    session.blocksTableData = [];
    session.blocksTableHeader = [];
    session.blocksCurrentPage = 1;
    session.blocksPageSize = 10;
    session.blocksTotal = 0;
    session.blocksOrder = '';
    session.blocksOrderBy = '';
    session.blocksFilters = {};
    session.blocksRangeFilters = {};
};
const eventsDetailsRestore = (session: any): void => {
    session.eventsRangeFilters = {};
    session.eventsTableData = [];
    session.eventsTableHeader = [];
    session.eventsCurrentPage = 1;
    session.eventsPageSize = 10;
    session.eventsTotal = 0;
    session.eventsOrder = '';
    session.eventsOrderBy = '';
    session.eventsFilters = {};
};
const detailsRestore = (session: any): void => {
    session.tableType = 'blocks';
    session.tableKey = (session.tableKey + 1) % 10;
    session.lazyUsedThreshold = { perT: null, valueT: null };
    session.delayedFreeThreshold = { perT: null, valueT: null };
    session.longIdleThreshold = { perT: null, valueT: null };
    session.onlyInefficient = false;
    session.autoFilterPotentialLeaks = false;
};
const restore = (session: any): void => {
    commonRestore(session);
    funcRestore(session);
    barRestore(session);
    sliceRestore(session);
    blocksDetailsRestore(session);
    eventsDetailsRestore(session);
    detailsRestore(session);
};
export const importRemoteHandler: NotificationHandler = (data): void => {
    const session = store.sessionStore.activeSession;
    if (!session || typeof data !== 'object') {
        return;
    }
    const fileId = getImportedMemSnapshotFile(data as RemoteImportData);
    if (!fileId) {
        runInAction(() => {
            clearMemSnapshotParseProgress(session);
        });
        return;
    }
    runInAction(() => {
        session.memSnapshotParseLoading = true;
        session.memSnapshotParseProgress = 0;
        session.memSnapshotParseFileId = fileId;
    });
};

export const parseProgressHandler: NotificationHandler = (data): void => {
    const session = store.sessionStore.activeSession;
    if (!session || typeof data !== 'object') {
        return;
    }
    const { fileId = '', progress } = data as MemSnapshotProgressData;
    if (!isMemSnapshotFile(fileId)) {
        return;
    }
    runInAction(() => {
        const currentFileId = session.memSnapshotParseFileId;
        if (!currentFileId || normalizeFilePath(currentFileId) !== normalizeFilePath(fileId)) {
            return;
        }
        session.memSnapshotParseLoading = true;
        session.memSnapshotParseProgress = Math.max(session.memSnapshotParseProgress, clampProgress(progress));
    });
};

export const parseCompletedHandler = (data: any): void => {
    const session = store.sessionStore.activeSession;
    workerDestroy();
    if (session) {
        runInAction(() => {
            clearMemSnapshotParseProgress(session);
            session.deviceIds = data.deviceIds;
            session.threadIds = data.threadIds;
            session.module = data.module;
            restore(session);
        });
    }
};
export const removeRemoteHandler: NotificationHandler = (data): void => {
    const session = store.sessionStore.activeSession;
    workerDestroy();
    stateWorkerDestroy();
    if (session) {
        runInAction(() => {
            session.deviceIds = {};
            session.threadIds = [];
            session.module = 'leaks';
            session.clickEventItem = null;
            session.leaksWorkerInfo = { ...LEAKS_WORKER_INFO_DEFAULT, renderOptions: { ...session.leaksWorkerInfo.renderOptions } };
            session.stateWorkerInfo = { ...STATE_WORKER_INFO_DEFAULT };
            session.markLineInfo = MARK_LINE_POSITION_DEFAULT;
            session.loadingBlocks = false;
            session.loadingState = false;
            clearMemSnapshotParseProgress(session);
            restore(session);
        });
    }
};

export const parseFailHandler: NotificationHandler = (data): void => {
    errorCenter.handleError(new WsError(ErrorCode.PARSE_FAIL, data.error as string));
    removeRemoteHandler(data);
};