package com.ecep.contract.controller;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.ecep.contract.Desktop;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import lombok.Setter;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.WebSocket;

public class OkHttpLoginController implements MessageHolder {
    private static final Logger logger = LoggerFactory.getLogger(OkHttpLoginController.class);
    public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");

    @Setter
    private MessageHolder holder;
    @Setter
    private Stage primaryStage;
    @Setter
    private Properties properties;
    @Setter
    private OkHttpClient httpClient;
    private WebSocket webSocket;
    private String serverUrl;
    private String webSocketUrl;

    public OkHttpLoginController() {
        this.httpClient = new OkHttpClient().newBuilder().cookieJar(new CookieJar() {
            private final List<Cookie> cookies = new java.util.ArrayList<>();

            @Override
            public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                // 保存服务器返回的Cookie（如JSESSIONID）
                this.cookies.addAll(cookies);
                System.out.println("保存Cookie: " + cookies);
            }

            @Override
            public List<Cookie> loadForRequest(HttpUrl url) {
                // 请求时自动携带Cookie
                return cookies;
            }

        }).build();
    }

    @Override
    public void addMessage(Level level, String message) {
        if (holder != null) {
            holder.addMessage(level, message);
        }
    }

    private void initServerUrls() {
        String host = properties.getProperty("server.host", "localhost");
        String port = properties.getProperty("server.port", "8080");
        this.serverUrl = "http://" + host + ":" + port;
        this.webSocketUrl = "ws://" + host + ":" + port + "/ws";
    }

    public CompletableFuture<Void> tryLogin() {
        initServerUrls();

        // 检查配置文件中是否保存用户名和密码
        String userName = getUserName();
        String password = getPassword();

        if (StringUtils.hasText(userName) && StringUtils.hasText(password)) {
            return login(userName, password);
        } else {
            CompletableFuture<Void> loginFuture = new CompletableFuture<>();
            Platform.runLater(() -> {
                showLoginDialog();
                loginFuture.complete(null);
            });
            return loginFuture;
        }
    }

    private String getUserName() {
        return properties.getProperty("user.name", "");
    }

    private String getPassword() {
        return properties.getProperty("user.password", "");
    }

    private void showLoginDialog() {
        Stage stage = new Stage();
        stage.initOwner(primaryStage);
        stage.setTitle("系统登录");

        // 创建 BorderPane 并设置边距
        BorderPane borderPane = new BorderPane();
        borderPane.setPadding(new Insets(20));

        // 创建布局
        GridPane grid = new GridPane();
        grid.setHgap(10);
        grid.setVgap(15);

        // 账户输入框
        Label userLabel = new Label("用户名:");
        TextField userField = new TextField();
        {
            String username = getUserName();
            if (StringUtils.hasText(username)) {
                userField.setText(username);
            }
            grid.add(userLabel, 0, 0);
            grid.add(userField, 1, 0);
        }

        // 密码输入框
        Label passwordLabel = new Label("密码:");
        PasswordField passwordField = new PasswordField();
        {
            String password = getPassword();
            if (StringUtils.hasText(password)) {
                passwordField.setText(password);
            }
            grid.add(passwordLabel, 0, 1);
            grid.add(passwordField, 1, 1);
        }

        // 记住密码复选框
        CheckBox rememberCheckBox = new CheckBox("记住密码");
        {
            String property = properties.getProperty("remember.password", "false");
            if (Boolean.parseBoolean(property)) {
                rememberCheckBox.setSelected(true);
            }
        }
        grid.add(rememberCheckBox, 1, 2);

        // 错误消息提示
        Label errorLabel = new Label();
        errorLabel.setStyle("-fx-text-fill: red;");
        errorLabel.setVisible(false);
        grid.add(errorLabel, 0, 3);
        GridPane.setColumnSpan(errorLabel, 2);

        borderPane.setCenter(grid);

        // 登录按钮
        Button loginButton = new Button("登录");
        loginButton.setDefaultButton(true);
        loginButton.setPrefWidth(100);
        borderPane.setBottom(loginButton);
        BorderPane.setAlignment(loginButton, javafx.geometry.Pos.CENTER);
        BorderPane.setMargin(loginButton, new Insets(20, 0, 0, 0));

        // 登录按钮点击事件
        loginButton.setOnAction(event -> {
            String username = userField.getText();
            String password = passwordField.getText();
            boolean remember = rememberCheckBox.isSelected();

            if (!StringUtils.hasText(username) || !StringUtils.hasText(password)) {
                errorLabel.setText("用户名和密码不能为空");
                errorLabel.setVisible(true);
                return;
            }

            errorLabel.setVisible(false);

            // 保存配置
            properties.setProperty("user.name", username);
            if (remember) {
                properties.setProperty("user.password", password);
                properties.setProperty("remember.password", "true");
            } else {
                properties.setProperty("user.password", "");
                properties.setProperty("remember.password", "false");
            }

            // 执行登录
            login(username, password).whenComplete((v, e) -> {
                if (e != null) {
                    Platform.runLater(() -> {
                        errorLabel.setText(e.getMessage());
                        errorLabel.setVisible(true);
                        // showError("登录失败", e.getMessage());
                    });
                    return;
                }
                Platform.runLater(() -> {
                    stage.close();
                });
            });
        });

        // 创建场景并设置到窗口
        Scene scene = new Scene(borderPane, 400, 280);
        stage.setScene(scene);
        stage.setResizable(false);
        stage.showAndWait();

        System.out.println("登录窗口关闭");
    }

    private CompletableFuture<Void> login(String username, String password) {
        // 添加详细日志，记录服务器URL和请求准备情况
        info("正在连接服务器: " + serverUrl);
        logger.debug("login方法被调用，用户名: " + username);
        CompletableFuture<Void> future = new CompletableFuture<>();

        try {
            while (!SpringApp.isRunning()) {
                holder.info("环境准备中，请稍后...");
                Thread.sleep(1000);
            }

            ObjectMapper objectMapper = SpringApp.getBean(ObjectMapper.class);
            ObjectNode objectNode = objectMapper.createObjectNode();
            objectNode.put("username", username);
            objectNode.put("password", password);
            objectNode.put("type", "client");

            // 将MacIP列表转换为Map<String, String>格式（MAC地址->IP地址）
            List<MacIP> macIpList = getMacAndIP().join();
            ObjectNode signNode = objectMapper.createObjectNode();
            for (MacIP macIp : macIpList) {
                signNode.put(macIp.mac, macIp.ip);
            }
            objectNode.set("sign", signNode);

            // 构建JSON格式的登录请求
            RequestBody body = RequestBody.create(objectNode.toString(), JSON);

            // 构建并记录完整的请求URL
            String loginUrl = serverUrl + "/api/login";
            logger.debug("构建登录请求URL: " + loginUrl);
            Request request = new Request.Builder()
                    .url(loginUrl)
                    .post(body)
                    .build();

            httpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    future.completeExceptionally(
                            new IOException("登录失败: 无法连接到服务器，请检查网络连接或服务器配置 - " + e.getMessage(), e));
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    try {
                        if (!response.isSuccessful()) {
                            future.completeExceptionally(
                                    new IOException("登录失败: 服务器返回错误码 - " + response.toString()));
                            return;
                        }
                        ResponseBody body = response.body();
                        System.out.println("contentType = " + body.contentType());
                        JsonNode jsonNode = objectMapper.readTree(body.string());

                        boolean success = jsonNode.get("success").asBoolean(false);
                        if (!success) {
                            future.completeExceptionally(
                                    new IOException("登录失败: 服务器返回错误 - " + jsonNode.get("error").asText()));
                            return;
                        }
                        System.out.println("登录成功: " + jsonNode.toString());
                        // 登录成功后，调用新的API端点获取用户信息

                        Desktop.instance.setActiveEmployeeId(jsonNode.get("employeeId").asInt());
                        Desktop.instance.setSessionId(jsonNode.get("sessionId").asText());
                        future.complete(null);

                    } finally {
                        // 确保主响应体被关闭
                        response.close();
                    }
                }
            });
        } catch (Exception e) {
            future.completeExceptionally(new IOException("登录过程中发生错误: " + e.getMessage(), e));
        }
        return future;
    }

    CompletableFuture<List<MacIP>> getMacAndIP() {
        return CompletableFuture.supplyAsync(() -> {
            List<MacIP> list = new ArrayList<>();
            try {
                Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
                while (interfaces.hasMoreElements()) {
                    NetworkInterface anInterface = interfaces.nextElement();
                    if (anInterface.isLoopback() || !anInterface.isUp()) {
                        continue;
                    }

                    byte[] hardwareAddress = anInterface.getHardwareAddress();
                    if (hardwareAddress == null) {
                        continue;
                    }

                    Enumeration<InetAddress> inetAddresses = anInterface.getInetAddresses();
                    if (!inetAddresses.hasMoreElements()) {
                        continue;
                    }

                    // -分割16进制表示法
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < hardwareAddress.length; i++) {
                        sb.append(
                                String.format("%02X%s", hardwareAddress[i], i < hardwareAddress.length - 1 ? "-" : ""));
                    }

                    String mac = sb.toString();
                    while (inetAddresses.hasMoreElements()) {
                        InetAddress inetAddress = inetAddresses.nextElement();
                        if (inetAddress.getHostAddress().contains(":")) {
                            continue; // 跳过IPv6地址
                        }
                        list.add(new MacIP(mac, inetAddress.getHostAddress()));
                    }
                }
            } catch (SocketException e) {
                throw new RuntimeException(e);
            }
            return list;
        });
    }

    // WebSocket消息发送方法
    public void sendMessage(String message) {
        if (webSocket != null) {
            webSocket.send(message);
        }
    }

    // 关闭WebSocket连接
    public void closeWebSocket() {
        if (webSocket != null) {
            webSocket.close(1000, "正常关闭");
            webSocket = null;
        }
    }

    static class MacIP {
        String mac;
        String ip;

        public MacIP(String mac, String ip) {
            this.mac = mac;
            this.ip = ip;
        }
    }
}