package com.suixingpay.serialkit.service;

import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.suixingpay.serialkit.comm.CommHelper;
import com.suixingpay.serialkit.listener.TppMessageListener;

import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.Timer;
import java.util.TimerTask;

import timber.log.Timber;

public class SerialSdkService {

    private static final String TAG = "SerialSdkService";
    private static SerialSdkService instance;
    private CountDownTimer countdownTimer;
    private Timer timer;
    private TimerTask timerTask;
    private TppMessageListener messageListener = null;
    private final Handler handler = new Handler(Looper.getMainLooper());

    // 购物流程控制
    private final Boolean isShopping = false;

    private final Integer shoppingStep = 0;

    private SerialSdkService() {
    }

    public static SerialSdkService getInstance() {
        if (instance == null) {
            instance = new SerialSdkService();
        }
        return instance;
    }

    public void setListener(TppMessageListener listener) {
        this.messageListener = listener;
    }

    public boolean isConnect() {
        return CommHelper.getInstance().isConnect();
    }

    public void connect() {
        CommHelper.getInstance().connect();
        startTimer();
    }

    public void send(String data) {
        CommHelper.getInstance().send(data.getBytes(StandardCharsets.UTF_8));
        // 尝试获取下一个完整的 JSON 对象
        String jsonString = getNextJson();
        if (jsonString != null && !jsonString.isEmpty()) {
            logInfo("接收到数据:" + jsonString);
            cancelCountdownTimer();
            if (messageListener != null) {
                messageListener.onDataReceived(jsonString);
            }
        }
    }

    private final JsonFactory jsonFactory = new JsonFactory();
    private final StringBuffer jsonBuffer = new StringBuffer();

    public String recvNonBlocking() {

        byte[] result = CommHelper.getInstance().recvNonBlocking();

        if (result != null && result.length > 0) {
            String str = new String(result, StandardCharsets.UTF_8);
            logInfo("读到数据:" + str);
            jsonBuffer.append(str);
        }

        // 尝试获取下一个完整的 JSON 对象
        String jsonString = getNextJson();
        // 如果获取到完整的 JSON，则返回它；否则返回空字符串
        return jsonString != null ? jsonString : "";
    }

    // 获取当前jsonBuffer
    public String getJsonBuffer() {
        if (jsonBuffer.length() == 0) {
            return null; // 如果缓冲区为空，返回 null
        }
        return jsonBuffer.toString();
    }

    // 清空jsonBuffer
    public void clearJsonBuffer() {
        jsonBuffer.setLength(0);
    }

    /**
     * 从缓冲区中提取下一个完整的JSON对象
     *
     * @return 完整的JSON字符串，如果没有则返回null
     */
    public String getNextJson() {
        if (jsonBuffer.length() == 0) {
            return null;
        }
        logInfo("getNextJson begin jsonBuffer:" + getJsonBuffer());
        try (StringReader reader = new StringReader(jsonBuffer.toString())) {
            JsonParser parser = jsonFactory.createParser(reader);
            JsonToken token;
            int objectDepth = 0;
            int startPos = 0;
            int endPos = 0;
            boolean inObject = false;

            while ((token = parser.nextToken()) != null) {
                endPos = (int) parser.getTokenLocation().getCharOffset();

                if (token == JsonToken.START_OBJECT) {
                    if (objectDepth == 0) {
                        startPos = endPos;
                        inObject = true;
                    }
                    objectDepth++;
                } else if (token == JsonToken.END_OBJECT) {
                    objectDepth--;
                    if (objectDepth == 0 && inObject) {
                        // 找到完整JSON对象
                        String jsonStr = jsonBuffer.substring(startPos, endPos + 1);
                        logInfo("getNextJson jsonStr:" + jsonStr);
                        // 验证JSON有效性
                        if (validateJson(jsonStr)) {
                            jsonBuffer.delete(0, endPos + 1);
                            logInfo("getNextJson remain jsonBuffer:" + getJsonBuffer());
                            return jsonStr;
                        } else {
                            String msg = "Incorrect json:" + jsonStr;
                            logError(msg);
                            if (messageListener != null) {
                                messageListener.onError(400, msg);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            String msg = "JSON parse error:" + e.getMessage() + ",jsonBuffer:" + getJsonBuffer();
            // 记录错误日志
            logError(e, msg);
            // 清空jsonBuffer
            clearJsonBuffer();
            if (messageListener != null) {
                messageListener.onError(400, msg);
            }
        }
        logInfo("getNextJson is null,remain jsonBuffer:" + getJsonBuffer());
        return null;
    }

    /**
     * 使用Jackson验证JSON有效性
     */
    private boolean validateJson(String jsonStr) {
        try (JsonParser parser = jsonFactory.createParser(jsonStr)) {
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    public void disConnect() {
        CommHelper.getInstance().disConnect();
        stopTimer();
        cancelCountdownTimer();
    }


    private void startCountdownTimer() {
        handler.post(() -> {
            if (countdownTimer != null) {
                countdownTimer.cancel();
            }
            countdownTimer = new CountDownTimer(CommHelper.getInstance().getRecvTimeout(), 1000) {
                public void onTick(long millisUntilFinished) {
                    Log.i(TAG, "Countdown timer: " + millisUntilFinished / 1000 + " seconds remaining");
                }

                public void onFinish() {
                    logError("Timeout: Calling onError(408, 'Receive data timeout')");
                    if (messageListener != null) {
                        messageListener.onError(408, "Receive data timeout");
                    }
                }
            };
            countdownTimer.start();
        });
    }

    private void cancelCountdownTimer() {
        if (countdownTimer != null) {
            countdownTimer.cancel();
            countdownTimer = null;
        }
    }

    private void startTimer() {
        if (timer == null) {
            timer = new Timer();
            timerTask = new TimerTask() {
                @Override
                public void run() {
                    // 这里是你希望每秒执行的任务
                    String jsonString = recvNonBlocking();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        logInfo("APP接收到数据:" + jsonString);
                        cancelCountdownTimer();
                        if (messageListener != null) {
                            messageListener.onDataReceived(jsonString);
                        }
                    } else {
                        logInfo("正在等待接收数据...");
                    }

                }
            };
            // 安排定时任务，延迟0毫秒后每1000毫秒执行一次
            timer.schedule(timerTask, 0, 1000);
        }
    }

    private void stopTimer() {
        if (timer != null) {
            timer.cancel();
            timer = null;
            timerTask = null;
        }
    }

    public void sendStringNoTimer(String jsonString) {
        logInfo("调用sendStringNoTimer发送消息: " + jsonString);
        sendTextNoTimer(jsonString);
    }

    private void sendTextNoTimer(String data) {
        if (isConnect()) {
            logInfo("POS发送串口数据：" + data);
            send(data);
        } else {
            logError("请先打开串口");
        }
    }

    private void logInfo(String msg) {
        Timber.tag(TAG).i(msg);
    }

    private void logError(String msg) {
        Timber.tag(TAG).e(msg);
    }

    private void logError(Throwable t, String msg) {
        Timber.tag(TAG).e(t, msg);
    }
}
