package com.unibuy.smartdevice.controller;

import com.unibuy.smartdevice.MyApp;
import com.unibuy.smartdevice.devices.ComPort;
import com.unibuy.smartdevice.devices.DevNFCPay;
import com.unibuy.smartdevice.devices.PortTools;
import com.unibuy.smartdevice.devices.Rs232Dev;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsParseException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.HandlerMainScheduler;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class DevNFCPayController extends HandlerMainScheduler {

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

    public enum Option {
        TOAST(0),
        RESPONSE(5),
        ;
        private int option;
        public int getOption() { return option; }
        Option(int option) { this.option = option; }
    }

    private Rs232Dev comPort2;
    private DevNFCPay devNFCPay;
    private int payType;
    private int totalPrice;
    private boolean isShuttingDown = false; // ✅ 新增：標記是否正在關閉中

    public DevNFCPayController(HandlerMain handlerMain) {
        super(handlerMain);
        try {
            comPort2 = new Rs232Dev(MyApp.getInstance().getComPort2ByNFCPay());
            devNFCPay = new DevNFCPay(handlerMain.getContext());
        } catch (LogsUnsupportedOperationException | LogsIOException e) {
            getLogs().warning(e);
        }
    }

    @Override
    protected HandlerMain setHandlerMain() {
        return getSrcHandlerMain();
    }

    public void start(int payType, int totalPrice) throws LogsIOException {
        if (devNFCPay != null) {
            this.payType = payType;
            this.totalPrice = totalPrice;
            clearOldBuffer();
            MyApp.getInstance().setNfcPaymentActive(true);
            byte[] sendBuffer = devNFCPay.swipe(payType, totalPrice);
            String sendData = new String(sendBuffer);
            getLogs().info("電文送出:" + sendData);
            MyApp.getInstance().getReportFlowInfoData().setFlowSendInfo(sendData);
            comPort2.send(sendBuffer);
            start();
        } else {
            throw new LogsIOException(getLogs(), "Dev comport not found");
        }
    }

    private void clearOldBuffer() {
        try {
            byte[] dummy;
            while ((dummy = comPort2.readNonBlocking()) != null && dummy.length > 0) {
                getLogs().info("清除舊資料: " + new String(dummy));
            }
        } catch (Exception e) {
            getLogs().info("清空 buffer 發生錯誤: " + e.getMessage());
        }
    }

    @Override
    protected void close(HandlerMain handlerMain) {
        try {
            comPort2.closePort();
        } catch (LogsIOException e) {
            getLogs().warning(e);
        }
    }

    /*
    0000 ? 交易成功
    0001 ? 交易失敗 請連絡銀行
    0002 ? 交易逾時
    0003 ? 操作錯誤
    0004 ? 通訊失敗
    0005 ? 使用者終止交易
    0006 ? 非參加機構卡片
    0009 ? 電文錯誤
    0010 ? 非聯名卡-客製化參數 075/103 使用
    0011 ? 電票金額超過上限
    0012 ? 票卡已鎖
    0013 ? 無法比對原始電票交易
    0014 ? 票卡未開啟自動加值
    0015 ? 電票餘額不足
    0016 ? 多張票卡讀取失敗
    0017 ? 請重新感應卡片
    0018 ? 信用卡及電票皆結帳失敗
    1001 ? CreditCard settlement is success, 信用卡結帳成功，電票結帳失敗
    1002 ? CreditCard settlement is failure, 信用卡結帳失敗，電票結帳成功
    1003 ? CreditCard settlement is failure, 信用卡結帳失敗，電票結帳成功
     */

    @Override
    public void shutdown() {
        isShuttingDown = true; // ✅ 標記正在關閉，避免再次回報錯誤
        MyApp.getInstance().setNfcPaymentActive(false); // ✅ 關閉 NFC 支付感應
        super.shutdown();
        close(getHandlerMain());
    }

    @Override
    protected void execute(HandlerMain handlerMain) {
        if (!MyApp.getInstance().isShowDialog() || !MyApp.getInstance().isNfcPaymentActive()) {
            getLogs().info("⚠️ NFC 支付狀態未啟動或對話框已關閉，停止服務");
            shutdown();
            return;
        }



        try {
            byte[] readBuffer = comPort2.readToMatch(new byte[]{0x03}, 4096);
            getLogs().info("readBuffer length:" + readBuffer.length);

            if (!MyApp.getInstance().isShowDialog()) {
                getLogs().info("⚠️ 讀取完成後發現對話框已關閉，捨棄本次交易內容");
                return;
            }

            if (readBuffer.length != 404) {
                getLogs().info("❌ 長度不符，立即中止");
                // 讀取長度異常，直接結束
                reportError("0001", "讀取長度錯誤");
                return;
            }

            comPort2.send(devNFCPay.ok());
            String readData = new String(readBuffer);
            getLogs().info("電文接收:" + readData);
            MyApp.getInstance().getReportFlowInfoData().setFlowRequestInfo(readData);

            while (isRun() && MyApp.getInstance().isShowDialog()) { // ✅ 增加狀態檢查
                byte[] buffer = comPort2.readListen(30, 200);

                if (buffer.length > 0) {
                    getLogs().info("NFC 收到資料: " + PortTools.showHex(buffer));
                    String rxData = new String(buffer, StandardCharsets.UTF_8);

                    if (rxData.contains(String.valueOf((char) 0x03))) { // ETX
                        HashMap<String, String> response = devNFCPay.read(rxData);
                        String code = response.get("code");

                        if (isRun() && !isShuttingDown && MyApp.getInstance().isShowDialog()) { // ✅ 最後回報前的檢查
                            getHandlerMain().start(getClass().getSimpleName(), Option.RESPONSE.getOption(), code);
                        } else {
                            getLogs().info("🚫 控制器已停止或對話框已關閉，捨棄 NFC 回傳結果");
                        }
                        break;
                    }
                }

                if (!isRun() || isShuttingDown || !MyApp.getInstance().isShowDialog()) {
                    getLogs().info("NFC 讀取中斷: 控制器關閉或對話框消失");
                    break;
                }
            }
        } catch (LogsParseException | LogsIOException e) {
            getLogs().warning(e);
            reportError("9999", "例外異常");
        }
    }

    private void reportError(String code, String logMessage) {
        if (isShuttingDown) return; // ✅ 關閉中不報錯
        getLogs().info("錯誤回報 code: " + code + " 描述: " + logMessage);
        getHandlerMain().start(getClass().getSimpleName(), Option.RESPONSE.getOption(), code);
    }

    private void logReadMap(HashMap<String, String> readMap) {
        getLogs().info("======== DevNFCPay parse result ========");
        for (Map.Entry<String, String> entry : readMap.entrySet()) {
            getLogs().info("Key='" + entry.getKey() + "', Value='" + entry.getValue() + "'");
        }
        getLogs().info("========================================");
    }
}
