package com.unibuy.smartdevice.tools;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import java.util.List;

import com.unibuy.smartdevice.MyApp;
import com.unibuy.smartdevice.controller.DevController;
import com.unibuy.smartdevice.controller.DevXinYuanController;
import com.unibuy.smartdevice.devices.PortTools;
import com.unibuy.smartdevice.external.mqtt.MqttManager;

/**
 * 遠端出貨管理器
 * 負責在背景執行商品出貨流程，不依賴於 UI (DispatchDialog)。
 */
public class ProductDispenseManager {
    private static final String TAG = "ProductDispenseManager";

    public interface DispenseListener {
        void onProgress(String message);

        void onSuccess();

        void onFailure(String error);
    }

    private final Context context;
    private final DispenseListener listener;
    private final com.unibuy.smartdevice.exception.Logs logs;
    private final Handler mainHandler = new Handler(Looper.getMainLooper());
    private int checkRetryCount = 0;

    public ProductDispenseManager(Context context, com.unibuy.smartdevice.exception.Logs logs,
            DispenseListener listener) {
        this.context = context;
        this.logs = logs;
        this.listener = listener;
    }

    public void startDispense(int slot) {
        if (logs != null)
            logs.info("Starting background dispense for slot: " + slot);
        listener.onProgress("正在檢查貨道狀態...");

        DevXinYuanController controller = MyApp.getInstance().getDevXinYuanController();
        if (controller == null || !controller.isConnected()) {
            listener.onFailure("下位機控制器未連線");
            return;
        }

        // 步驟 1: 檢查貨道狀態 (CMD 01 -> VMC 02)
        controller.getReadBufferByNow(new DevController.ReadBufferOnScheduler(new HandlerMain(context, null) {
            @Override
            protected void execute(Context context, int commandCode, String message) {
            }
        }) {
            @Override
            protected HandlerMain setHandlerMain() {
                return getSrcHandlerMain();
            }

            @Override
            protected Class<?> setCls() {
                return getClass();
            }

            @Override
            public void readBufferOnScheduler(DevController devController, HandlerMain handlerMain) {
                boolean isCMD = false;
                boolean isStatusOk = false;
                String errorDetail = "";

                for (byte[] buffer : devController.getReadBufferByMax()) {
                    if (buffer[0] == 0x02) { // VMC_02_CHECK_SLOT_STATUS
                        isCMD = true;
                        if (logs != null)
                            logs.debug("Check Slot Result: " + PortTools.showHex(buffer));
                        // 01: OK, 02: PDT_EMPTY (有些機型空也會允許出貨指令), 04: TMP_USE
                        if (buffer[1] == 0x01 || buffer[1] == 0x02 || buffer[1] == 0x04) {
                            isStatusOk = true;
                        } else {
                            errorDetail = String.format("%02X%02X", buffer[0], buffer[1]);
                        }
                        break;
                    }
                }

                if (isCMD) {
                    if (isStatusOk) {
                        mainHandler.post(() -> executeActualDispense(slot));
                    } else {
                        // Error during CMD 01
                        if (!errorDetail.isEmpty()) {
                            MqttManager.getInstance().publishError(slot, errorDetail);
                        }
                        mainHandler.post(() -> listener.onFailure("貨道狀態異常，無法出貨"));
                    }
                } else {
                    if (checkRetryCount < 3) {
                        checkRetryCount++;
                        controller.addSendBuffer(controller.getDevXinYuan().checkSlot(slot));
                        controller.getReadBuffer(this, 1000);
                    } else {
                        mainHandler.post(() -> listener.onFailure("下位機檢查貨道無回應"));
                    }
                }
            }
        }, 1000);

        controller.addSendBuffer(controller.getDevXinYuan().checkSlot(slot));
    }

    private void executeActualDispense(int slot) {
        listener.onProgress("貨道正常，正在發送出貨指令...");
        DevXinYuanController controller = MyApp.getInstance().getDevXinYuanController();
        long startTime = System.currentTimeMillis();
        long timeoutMillis = 60000; // 60 秒超時

        // 步驟 2: 發送出貨指令並監聽狀態 (CMD 06 -> VMC 04)
        controller.getReadBufferByNow(new DevController.ReadBufferOnScheduler(new HandlerMain(context, null) {
            @Override
            protected void execute(Context context, int commandCode, String message) {
            }
        }) {
            @Override
            protected HandlerMain setHandlerMain() {
                return getSrcHandlerMain();
            }

            @Override
            protected Class<?> setCls() {
                return getClass();
            }

            @Override
            public void readBufferOnScheduler(DevController devController, HandlerMain handlerMain) {
                boolean isVmc04Found = false;
                boolean isSuccess = false;
                boolean isFailed = false;
                String errorDetail = "";

                // 讀取所有緩衝區中的 VMC_04 訊息
                // 注意：buffer 中可能同時存在 VMC_11、VMC_23 等其他訊號，
                // 必須只判斷 VMC_04，非 04 的封包一律忽略並繼續輪詢。
                List<byte[]> buffers = devController.getReadBufferByMax();
                for (byte[] buffer : buffers) {
                    if (buffer.length >= 2 && buffer[0] == 0x04) { // VMC_04_BUY_STATUS
                        isVmc04Found = true;
                        if (logs != null)
                            logs.info("Dispense Status Received: " + PortTools.showHex(buffer));

                        // 02: OK, 24: PLIS_BOX
                        if (buffer[1] == 0x02 || buffer[1] == 0x24) {
                            if (logs != null)
                                logs.info("Dispense SUCCESS detected from VMC_04: " + PortTools.showHex(buffer));
                            isSuccess = true;
                            break;
                        }
                        // 01: NOW (處理中), 10: PLATFORM_UP, 11: PLATFORM_DOWN
                        else if (buffer[1] == 0x01 || buffer[1] == 0x10 || buffer[1] == 0x11) {
                            if (logs != null)
                                logs.info("Machine busy (status " + String.format("%02X", buffer[1])
                                        + "), continuing poll...");
                            // 繼續掃描其他 buffer
                        } else {
                            if (logs != null)
                                logs.info("Dispense FAILED detected from VMC_04: " + PortTools.showHex(buffer));
                            isFailed = true;
                            errorDetail = String.format("%02X", buffer[1]);
                            break;
                        }
                    }
                    // 非 VMC_04 的封包 (如 VMC_11_GIVE_PRODUCT_INFO, VMC_23_NOW_GET_TOTAL) 一律跳過
                }

                if (isSuccess) {
                    mainHandler.post(() -> {
                        listener.onSuccess();
                    });
                } else if (isFailed) {
                    String errCode = String.format("04%s", errorDetail);
                    MqttManager.getInstance().publishError(slot, errCode);
                    String finalErrorDetail = errorDetail;
                    mainHandler.post(() -> listener.onFailure("出貨失敗，錯誤代碼: " + finalErrorDetail));
                } else {
                    // isVmc04Found=false 或 VMC_04 仍在處理中 → 繼續輪詢
                    // 【重要】即使 buffers 非空，只要沒有明確的成功/失敗 VMC_04，就必須繼續輪詢。
                    // 之前的 bug：buffers 含 VMC_11/VMC_23 時不為空，導致 else 分支被跳過，輪詢靜默終止。
                    if (logs != null) {
                        if (isVmc04Found) {
                            logs.info("VMC_04 still busy, rescheduling poll in 1s...");
                        } else {
                            logs.info("No VMC_04 in buffer yet, rescheduling poll in 1s...");
                        }
                    }

                    // 檢查是否超時
                    if (System.currentTimeMillis() - startTime > timeoutMillis) {
                        if (logs != null)
                            logs.info("ERROR: Dispense polling timeout after " + (timeoutMillis / 1000) + "s");
                        MqttManager.getInstance().publishError(slot, "TIMEOUT");
                        mainHandler.post(() -> listener.onFailure("出貨超時 (60s)"));
                        return;
                    }

                    // 使用 mainHandler.postDelayed 延遲 1 秒後重新輪詢
                    // 【重要】此處改用 getReadBuffer 而非 getReadBufferByNow。
                    // getReadBufferByNow 會清空 ReadBuffer，若 0402 訊號剛好在此時抵達，會被抹除。
                    final DevController.ReadBufferOnScheduler self = this;
                    mainHandler.postDelayed(() -> {
                        try {
                            devController.getReadBuffer(self, 500);
                        } catch (Exception e) {
                            // SchedulerAbstract 排程失敗時，確保仍能回報結果觸發 ACK
                            if (logs != null)
                                logs.info("ERROR: Polling reschedule failed: " + e.getMessage());
                            mainHandler.post(() -> listener.onFailure("輪詢排程異常"));
                        }
                    }, 100);
                }
            }
        }, 1000);

        controller.addSendBuffer(controller.getDevXinYuan().getProduct(slot));
    }

    private void updateLocalStock(int slot) {
        try {
            // 預設為 VMC 貨道 (Field 1)
            int field = com.unibuy.smartdevice.devices.SlotField.VMC.getField();
            com.unibuy.smartdevice.structure.SlotStructure slotData = MyApp.getInstance().getSlotData(field, slot);
            int currentCount = slotData.getCount();
            if (currentCount > 0) {
                int newCount = currentCount - 1;
                slotData.setCount(newCount);
                if (logs != null)
                    logs.info("Updated slot " + slot + " count: " + currentCount + " -> " + newCount);

                // 儲存至資料庫
                com.unibuy.smartdevice.database.SlotsDao slotsDao = new com.unibuy.smartdevice.database.SlotsDao(
                        context);
                slotsDao.deleteAll();
                slotsDao.insertAll(MyApp.getInstance().getSlotMap());
                slotsDao.close();
            }
        } catch (Exception e) {
            if (logs != null)
                logs.info("ERROR: Failed to update local stock: " + e.getMessage());
        }
    }
}
