package com.axis.innovators.box.browser;

import com.axis.innovators.box.tools.FolderCreator;
import org.cef.*;
import org.cef.browser.*;
import org.cef.callback.CefQueryCallback;
import org.cef.handler.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.UUID;
import java.util.function.Consumer;

public class BrowserWindow extends JFrame {
    private final String windowId;
    private CefApp cefApp;
    private CefClient client;
    private CefBrowser browser;
    private final Component browserComponent;
    private final String htmlPath;
    private static boolean isInitialized = false;
    private WindowOperationHandler operationHandler;
    private static Thread cefThread;
    private CefMessageRouter msgRouter;
    public static class Builder {
        private String windowId;
        private String title = "JCEF Window";
        private Dimension size = new Dimension(800, 600);
        private WindowOperationHandler operationHandler;
        private String htmlPath;
        private Image icon;

        public Builder(String windowId) {
            this.windowId = windowId;
        }

        public Builder title(String title) {
            this.title = title;
            return this;
        }

        public Builder size(int width, int height) {
            this.size = new Dimension(width, height);
            return this;
        }

        public Builder operationHandler(WindowOperationHandler handler) {
            this.operationHandler = handler;
            return this;
        }

        public Builder icon(Image icon) {
            this.icon = icon;
            return this;
        }

        public BrowserWindow build() {
            if (this.htmlPath == null || this.htmlPath.isEmpty()) {
                throw new IllegalArgumentException("HTML paths cannot be empty");
            }
            File htmlFile = new File(this.htmlPath);
            if (!htmlFile.exists()) {
                throw new RuntimeException("The HTML file does not exist: " + htmlFile.getAbsolutePath());
            }
            return new BrowserWindow(this);
        }

        public Builder htmlPath(String path) {
            this.htmlPath = path;
            return this;
        }
    }

    private BrowserWindow(Builder builder) {
        this.windowId = builder.windowId;
        this.htmlPath = builder.htmlPath;
        this.operationHandler = builder.operationHandler;

        if (builder.icon != null) {
            setIconImage(builder.icon);
        }
        try {
            this.browserComponent = initializeCef(builder);
            if (operationHandler != null) {
                setupMessageHandlers(operationHandler);
            }
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, "初始化失败: " + e.getMessage());
            //System.exit(1);
            throw new RuntimeException(e);
        }
    }

    private Component initializeCef(Builder builder) throws MalformedURLException {
        if (!isInitialized && CefApp.getState() != CefApp.CefAppState.INITIALIZED) {
            try {
                // 1. 初始化CEF设置（禁用多窗口）
                CefSettings settings = new CefSettings();
                settings.windowless_rendering_enabled = false;
                settings.javascript_flags = "--expose-gc";
                settings.log_severity = CefSettings.LogSeverity.LOGSEVERITY_VERBOSE;
                String subprocessPath = FolderCreator.getLibraryFolder() + "/jcef/lib/win64/jcef_helper.exe";

                // 验证子进程路径
                if (!new File(subprocessPath).exists()) {
                    throw new IllegalStateException("jcef_helper.exe not found at: " + subprocessPath);
                }
                settings.browser_subprocess_path = subprocessPath;
                System.out.println("Subprocess Path: " + settings.browser_subprocess_path);

                // 2. 创建CefApp和Client（严格单例）
                cefApp = CefApp.getInstance(settings);
                client = cefApp.createClient();

                client.addDisplayHandler(new CefDisplayHandler (){
                    @Override
                    public void onAddressChange(CefBrowser browser, CefFrame frame, String url) {

                    }

                    @Override
                    public void onTitleChange(CefBrowser browser, String title) {

                    }

                    @Override
                    public void OnFullscreenModeChange(CefBrowser browser, boolean fullscreen) {

                    }

                    @Override
                    public boolean onTooltip(CefBrowser browser, String text) {
                        return false;
                    }

                    @Override
                    public void onStatusMessage(CefBrowser browser, String value) {

                    }

                    @Override
                    public boolean onConsoleMessage(
                            CefBrowser browser,
                            CefSettings.LogSeverity level,
                            String message,
                            String source,
                            int line
                    ) {
                        // 格式化输出到 Java 控制台
                        String log = String.format(
                                "[Browser Console] %s %s (Line %d) -> %s",
                                getLogLevelSymbol(level),
                                source,
                                line,
                                message
                        );
                        System.out.println(log);
                        return false;
                    }

                    @Override
                    public boolean onCursorChange(CefBrowser browser, int cursorType) {
                        return false;
                    }

                    private String getLogLevelSymbol(CefSettings.LogSeverity level) {
                        switch (level) {
                            case LOGSEVERITY_ERROR:   return "⛔";
                            case LOGSEVERITY_WARNING: return "⚠️";
                            case LOGSEVERITY_DEFAULT:   return "🐞";
                            default:                  return "ℹ️";
                        }
                    }
                });

                // 3. 拦截所有新窗口（关键修复点！）
                //client.addLifeSpanHandler(new CefLifeSpanHandlerAdapter() {
                //    @Override
                //    public boolean onBeforePopup(CefBrowser browser,
                //                                 CefFrame frame, String target_url, String target_frame_name) {
                //        return true; // 返回true表示拦截弹窗
                //    }
                //});


                Thread.currentThread().setName("BrowserRenderThread");

                // 4. 加载HTML
                String fileUrl = new File(htmlPath).toURI().toURL().toString();
                System.out.println("Loading HTML from: " + fileUrl);

                // 5. 创建浏览器组件（直接添加到内容面板）
                browser = client.createBrowser(fileUrl, false, false);

                Component browserComponent = browser.getUIComponent();
                browser.executeJavaScript("console.log('Java -> HTML 消息测试')",null,2);

                CefMessageRouter.CefMessageRouterConfig config = new CefMessageRouter.CefMessageRouterConfig();
                config.jsQueryFunction = "javaQuery";// 定义方法
                config.jsCancelFunction = "javaQueryCancel";// 定义取消方法


                // 6. 配置窗口布局（确保只添加一次）
                SwingUtilities.invokeLater(() -> {
                    getContentPane().removeAll(); // 清空已有组件
                    getContentPane().setLayout(new BorderLayout());

                    // 透明拖拽层（仅顶部可拖拽）
                    JPanel dragPanel = new JPanel(new BorderLayout());
                    dragPanel.setOpaque(false);

                    JPanel titleBar = new JPanel();
                    titleBar.setOpaque(false);
                    titleBar.setPreferredSize(new Dimension(builder.size.width, 20));
                    final Point[] dragStart = new Point[1];
                    titleBar.addMouseListener(new MouseAdapter() {
                        @Override
                        public void mousePressed(MouseEvent e) {
                            dragStart[0] = e.getPoint();
                        }

                        @Override
                        public void mouseReleased(MouseEvent e) {
                            dragStart[0] = null;
                        }
                    });
                    titleBar.addMouseMotionListener(new MouseMotionAdapter() {
                        @Override
                        public void mouseDragged(MouseEvent e) {
                            if (dragStart[0] != null) {
                                Point curr = e.getLocationOnScreen();
                                setLocation(curr.x - dragStart[0].x, curr.y - dragStart[0].y);
                            }
                        }
                    });

                    dragPanel.add(titleBar, BorderLayout.NORTH);
                    getContentPane().add(dragPanel, BorderLayout.CENTER);
                    getContentPane().add(browserComponent, BorderLayout.CENTER);

                    // 7. 窗口属性设置
                    setTitle(builder.title);
                    setSize(builder.size); // 直接设置尺寸，避免pack()计算错误
                    setLocationRelativeTo(null);
                    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

                    // 8. 资源释放
                    addWindowListener(new WindowAdapter() {
                        @Override
                        public void windowClosed(WindowEvent e) {
                            browser.close(true); // 强制关闭浏览器
                            client.dispose();
                            cefApp.dispose();
                            isInitialized = false;
                        }
                    });

                    setVisible(true);
                    isInitialized = true;
                });
                return browserComponent;
            } catch (Exception e) {
                e.printStackTrace();
                isInitialized = false;
                JOptionPane.showMessageDialog(null, "初始化失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                System.exit(1);
            }
        } else {
            SwingUtilities.invokeLater(() -> {
                dispose();
            });
        }
        return null;
    }

    public static void printStackTrace() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (int i = 2; i < stackTrace.length; i++) {
            StackTraceElement element = stackTrace[i];
            System.out.println(element.getClassName() + "." + element.getMethodName() +
                    "(" + (element.getFileName() != null ? element.getFileName() : "Unknown Source") +
                    ":" + element.getLineNumber() + ")");
        }
    }

    @Override
    public void setVisible(boolean b) {
        super.setVisible(b);
    }

    public Component getBrowserComponent() {
        return browserComponent;
    }

    private void setupMessageHandlers(WindowOperationHandler handler) {
        if (client != null) {
            msgRouter = CefMessageRouter.create();
            msgRouter.addHandler(new CefMessageRouterHandlerAdapter() {
                @Override
                public boolean onQuery(CefBrowser browser,
                                       CefFrame frame,
                                       long queryId,
                                       String request,
                                       boolean persistent,
                                       CefQueryCallback callback) {
                    if (request.startsWith("system:")) {
                        String[] parts = request.split(":");
                        String operation = parts.length >= 2 ? parts[1] : null;
                        String targetWindow = parts.length > 2 ? parts[2] : null;
                        handler.handleOperation(
                                new WindowOperation(operation, targetWindow, callback) // [!code ++]
                        );
                        return true;
                    }
                    if (request.startsWith("java-response:")) {
                        String[] parts = request.split(":");
                        String requestId = parts[1];
                        String responseData = parts.length > 2 ? parts[2] : "";
                        Consumer<String> handler = WindowRegistry.getInstance().getCallback(requestId);
                        if (handler != null) {
                            handler.accept(responseData);
                            callback.success("");
                        } else {
                            callback.failure(-1, "无效的请求ID");
                        }
                        return true;
                    }
                    return false;
                }
            }, true);
            client.addMessageRouter(msgRouter);
        }
    }

    public String getWindowId() {
        return windowId;
    }

    /**
     * 获取消息路由器
     * @return 消息路由器
     */
    public CefMessageRouter getMsgRouter() {
        return msgRouter;
    }

    /**
     * 获取浏览器对象
     * @return 浏览器对象
     */
    public CefBrowser getBrowser() {
        return browser;
    }

    public void closeWindow() {
        SwingUtilities.invokeLater(() -> {
            if (browser != null) {
                browser.close(true);
            }
            dispose();
            cefApp.dispose();
            WindowRegistry.getInstance().unregisterWindow(windowId);
        });
    }
}

