import {app, BrowserWindow, ipcMain, dialog, session, protocol, net} from 'electron';
import {createRequire} from 'node:module';
import {fileURLToPath} from 'node:url';
import path from 'node:path';

import {getPlatform, isMacOS} from './main/utils/platform';
import {getWindowIconPath} from './main/utils/logo';
import {buildWindowTitle} from '../shared/constants/app';
import {loadEnvFile} from './main/load-env';
import {initUpdater, registerUpdateIpcHandlers} from './main/updater';
import {setupAppMenu} from './main/menu';
import {initLogger, flushLogger, logger, setLogDirResolver} from './main/logger';
import {registerLogIpcHandlers} from './main/ipc/log-ipc';
import {registerSafeStorageIpcHandlers} from './main/ipc/safe-storage-ipc';
import {registerStorageIpcHandlers, setDataDirResolver} from './main/ipc/storage-ipc';
import {registerCanvasIpcHandlers} from './main/ipc/canvas-ipc';
import {BIDIRECTIONAL, RENDERER_TO_MAIN, MAIN_TO_RENDERER} from '../shared/constants/ipc-channels';

createRequire(import.meta.url);
const __dirname = path.dirname(fileURLToPath(import.meta.url));

process.env.APP_ROOT = path.join(__dirname, '..');

// 加载 .env 文件中的环境变量到 process.env
// 必须在任何读取 process.env.UPDATE_API_URL 的模块之前调用
loadEnvFile();

export const VITE_DEV_SERVER_URL = process.env['VITE_DEV_SERVER_URL'];
export const MAIN_DIST = path.join(process.env.APP_ROOT, 'dist-electron');
export const RENDERER_DIST = path.join(process.env.APP_ROOT, 'dist');

process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL
    ? path.join(process.env.APP_ROOT, 'public')
    : RENDERER_DIST;

// ---------- 平台 & 版本信息 ----------
const currentPlatform = getPlatform();
/** 当前版控后缀（登录后通过 IPC 更新） */
let currentEdition: string | null = null;
/** 基础标题（无版控后缀），登录后通过 IPC 追加 */
const WINDOW_TITLE = buildWindowTitle(currentPlatform);

// ============================================================
// 全局未捕获异常（主进程兜底记录）
// ============================================================

process.on('uncaughtException', (error) => {
    try {
        logger.error('app', 'Uncaught exception (main process)', error);
    } catch {
        /* logger 自身异常 — 最后防线 */
    }
});

process.on('unhandledRejection', (reason) => {
    try {
        const error = reason instanceof Error ? reason : new Error(String(reason));
        logger.error('app', 'Unhandled rejection (main process)', error);
    } catch {
        /* logger 自身异常 — 最后防线 */
    }
});

// ============================================================
// 窗口引用
// ============================================================

let mainWindow: BrowserWindow | null = null;
let canvasWindow: BrowserWindow | null = null;

// ============================================================
// 主窗口
// ============================================================

function createMainWindow(): BrowserWindow {
    const iconPath = getWindowIconPath(app.getAppPath());

    mainWindow = new BrowserWindow({
        title: WINDOW_TITLE,
        icon: iconPath,
        width: 1280,
        height: 800,
        minWidth: 960,
        minHeight: 600,
        show: false,
        ...(isMacOS() ? {titleBarStyle: 'hiddenInset' as const} : {}),
        webPreferences: {
            preload: path.join(__dirname, 'preload.mjs'),
            contextIsolation: true,
            nodeIntegration: false,
        },
    });

    mainWindow.setTitle(WINDOW_TITLE);

    if (VITE_DEV_SERVER_URL) {
        mainWindow.webContents.openDevTools();
    }

    // macOS 全屏事件
    if (isMacOS()) {
        mainWindow.on('enter-full-screen', () =>
            mainWindow?.webContents.send('window-fullscreen-changed', true),
        );
        mainWindow.on('leave-full-screen', () =>
            mainWindow?.webContents.send('window-fullscreen-changed', false),
        );
    }

    mainWindow.webContents.on('did-finish-load', () => {
        mainWindow?.webContents.send('main-process-message', new Date().toLocaleString());
        mainWindow?.webContents.send('platform-info', {
            platform: currentPlatform,
            edition: currentEdition,
        });
    });

    // ready-to-show 后显示，避免白屏闪烁
    mainWindow.once('ready-to-show', () => {
        mainWindow?.show();
    });

    if (VITE_DEV_SERVER_URL) {
        mainWindow.loadURL(VITE_DEV_SERVER_URL);
    } else {
        mainWindow.loadFile(path.join(RENDERER_DIST, 'index.html'));
    }

    return mainWindow;
}

// ============================================================
// 画布窗口
// ============================================================

function createCanvasWindow(): BrowserWindow {
    const iconPath = getWindowIconPath(app.getAppPath());

    logger.info('canvas-window', '创建画布窗口', {
        isDev: !!VITE_DEV_SERVER_URL,
        url: VITE_DEV_SERVER_URL
            ? VITE_DEV_SERVER_URL + '#/canvas'
            : path.join(RENDERER_DIST, 'index.html') + '#/canvas',
    });

    canvasWindow = new BrowserWindow({
        title: '无限画布 - HeiXiu',
        icon: iconPath,
        width: 1400,
        height: 900,
        minWidth: 800,
        minHeight: 600,
        show: false,
        webPreferences: {
            preload: path.join(__dirname, 'preload.mjs'),
            contextIsolation: true,
            nodeIntegration: false,
        },
    });

    if (VITE_DEV_SERVER_URL) {
        canvasWindow.loadURL(VITE_DEV_SERVER_URL + '#/canvas');
        canvasWindow.webContents.openDevTools();
        logger.info('canvas-window', '画布窗口 DevTools 已自动打开（开发模式）');
    } else {
        canvasWindow.loadFile(path.join(RENDERER_DIST, 'index.html'), {
            hash: '/canvas',
        });
    }

    // 禁用浏览器默认页面缩放（Ctrl/Cmd+滚轮 和 触控板捏合）。
    // 画布使用 CSS transform 实现独立缩放，不允许 Chromium 页面级缩放干扰。
    // before-input-event 在 Chromium 处理输入之前触发，比 JS event listener 更早。
    canvasWindow.webContents.on('before-input-event', (event, input) => {
        if (input.type === 'mouseWheel' && (input.control || input.meta)) {
            event.preventDefault();
        }
    });

    canvasWindow.once('ready-to-show', () => {
        logger.info('canvas-window', '画布窗口 ready-to-show，即将显示');
        canvasWindow?.show();
    });

    canvasWindow.on('closed', () => {
        logger.info('canvas-window', '画布窗口已关闭');
        canvasWindow = null;
    });

    return canvasWindow;
}

// ============================================================
// 自定义协议：local-media — 安全加载本地文件
// 必须在 app.whenReady 之前注册为特权 scheme
// ============================================================

protocol.registerSchemesAsPrivileged([
    {
        scheme: 'local-media',
        privileges: {
            standard: true,
            secure: true,
            supportFetchAPI: true,
            bypassCSP: true,
            stream: true,
        },
    },
]);

// ============================================================
// 应用生命周期
// ============================================================

app.on('window-all-closed', () => {
    if (!isMacOS()) {
        app.quit();
    }
});

app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
        createMainWindow();
    }
});

app.on('before-quit', () => {
    flushLogger();
});

app.whenReady().then(() => {
    // ── 存储路径配置 ──
    // 修改以下两行即可将日志/数据存储到任意位置
    setLogDirResolver(() => path.join(app.getPath('userData'), 'logs'));
    setDataDirResolver(() => path.join(app.getPath('userData'), 'heixiu-data'));

    initLogger();
    registerLogIpcHandlers();
    registerSafeStorageIpcHandlers();
    registerStorageIpcHandlers();
    registerCanvasIpcHandlers();

    protocol.handle('local-media', (request) => {
        const urlObj = new URL(request.url);
        let filePath: string;

        if (urlObj.hostname) {
            // UNC 路径：local-media://server/share/path → \\server\share\path
            filePath = '\\\\' + urlObj.hostname + decodeURIComponent(urlObj.pathname).replace(/\//g, '\\');
        } else {
            // 本地路径：local-media:///C:/path/to/file → C:/path/to/file
            filePath = decodeURIComponent(urlObj.pathname.slice(1));
        }

        const fwd = filePath.replace(/\\/g, '/');
        let fileUrl: string;
        if (fwd.startsWith('//')) {
            fileUrl = 'file:' + fwd;
        } else {
            fileUrl = 'file:///' + fwd;
        }

        // 只转发 Range 头，确保音视频 seek 时返回 206 Partial Content。
        // ⚠️ 不能转发所有 headers（Origin/Referer/Sec-Fetch-* 等），
        // 否则会干扰 Chromium 内部的 file:// 协议处理，导致请求失败。
        const rangeHeader = request.headers.get('Range');
        if (rangeHeader) {
            return net.fetch(fileUrl, {headers: {Range: rangeHeader}});
        }
        return net.fetch(fileUrl);
    });

    setupAppMenu();
    app.setName(WINDOW_TITLE);
    registerUpdateIpcHandlers();
    const fakeUserAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36';
    session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
        const url = details.url;
        if (url.includes("rh-images-1252422369.cos.ap-beijing.myqcloud.com")) {
            details.requestHeaders['User-Agent'] = fakeUserAgent;
        }
        callback({
            requestHeaders: details.requestHeaders
        });
    });

    // 文件对话框 IPC 处理（供渲染进程选择文件夹）
    ipcMain.handle(BIDIRECTIONAL.FILE_DIALOG, async (_event, options: Electron.OpenDialogOptions) => {
        try {
            const parentWindow = mainWindow && !mainWindow.isDestroyed() ? mainWindow : canvasWindow;
            if (!parentWindow) return {canceled: true, filePaths: []};
            return dialog.showOpenDialog(parentWindow, {
                title: options?.title || '选择文件夹',
                defaultPath: options?.defaultPath || app.getPath('home'),
                properties: options?.properties || ['openDirectory'],
            });
        } catch (err) {
            logger.warn('ipc', '文件对话框打开失败', err instanceof Error ? err : undefined);
            return {canceled: true, filePaths: []};
        }
    });

    // 窗口标题版控后缀（渲染进程登录/登出后调用）
    ipcMain.on(RENDERER_TO_MAIN.SET_WINDOW_TITLE, (_event, edition: string | null) => {
        try {
            currentEdition = edition;
            if (!mainWindow) return;
            const title = edition
                ? buildWindowTitle(currentPlatform, undefined, edition as 'personal' | 'enterprise')
                : buildWindowTitle(currentPlatform);
            mainWindow.setTitle(title);
        } catch (err) {
            logger.warn('ipc', '设置窗口标题失败', err instanceof Error ? err : undefined);
        }
    });

    // 打开无限画布窗口（渲染进程请求 → 主进程创建新 BrowserWindow）
    ipcMain.on(RENDERER_TO_MAIN.OPEN_CANVAS_WINDOW, (_event, payload?: { projectPath?: string }) => {
        try {
            const existingAlive = canvasWindow && !canvasWindow.isDestroyed();
            logger.info('canvas-window', '收到 OPEN_CANVAS_WINDOW IPC', {
                projectPath: payload?.projectPath || '(未指定)',
                existingAlive,
            });

            if (existingAlive) {
                logger.info('canvas-window', '画布窗口已存在，聚焦现有窗口');
                canvasWindow?.focus();
            } else {
                logger.info('canvas-window', '画布窗口不存在或已销毁，创建新窗口');
                canvasWindow = createCanvasWindow();
            }
            // 画布页面加载完成后，发送初始化参数
            if (payload?.projectPath) {
                const readyHandler = () => {
                    logger.info('canvas-window', '画布页面 did-finish-load，发送 CANVAS_READY', {
                        projectPath: payload.projectPath,
                    });
                    canvasWindow?.webContents.send(MAIN_TO_RENDERER.CANVAS_READY, {
                        projectPath: payload.projectPath,
                    });
                };
                canvasWindow?.webContents.on('did-finish-load', readyHandler);
            }
        } catch (err) {
            logger.warn('canvas-window', '打开画布窗口失败', err instanceof Error ? err : undefined);
        }
    });

    // 始终打开主窗口
    // 登录/注册由渲染进程内的 Modal 弹层处理，不再新开窗口
    const win = createMainWindow();
    initUpdater(win);
});
