package com.unibuy.smartdevice.ui.dialog;

import android.content.Context;

import com.unibuy.smartdevice.DialogAbstract;
import com.unibuy.smartdevice.MyApp;
import com.unibuy.smartdevice.R;
import com.unibuy.smartdevice.databinding.DialogAccessCodeBinding;
import com.unibuy.smartdevice.databinding.DialogFreeGiftCodeBinding;
import com.unibuy.smartdevice.devices.DeviceType;
import com.unibuy.smartdevice.devices.UsbDev;
import com.unibuy.smartdevice.exception.LogsEmptyException;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsParseException;
import com.unibuy.smartdevice.exception.LogsSettingEmptyException;
import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException;
import com.unibuy.smartdevice.external.HttpAPI;
import com.unibuy.smartdevice.structure.BuyStructure;
import com.unibuy.smartdevice.structure.ProductStructure;
import com.unibuy.smartdevice.structure.ReportFreeGiftCodeStructure;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.HandlerMainCountdown;
import com.unibuy.smartdevice.tools.HandlerMainScheduler;
import com.unibuy.smartdevice.tools.ToastHandlerMain;
import com.unibuy.smartdevice.tools.Tools;
import com.unibuy.smartdevice.ui.FontendActivity;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class CheckoutFreeGiftCodeDialog extends DialogAbstract {
    public enum Option {
        TOAST(0),
        COUNTDOWN_CANCEL(1),
        SET_COUNTDOWN_TEXT(2),
        INVOICE_SUCCESSFUL(4),
        INVOICE_FAILED(5),
        CHANGE_DISPATCH(6),
        CHANGE_BUY(7),
        SET_STATUS_TEXT(8),
        SET_SCAN_INPUT(9),
        ;

        private int option;

        public int getOption() {
            return option;
        }

        Option(int option) {
            this.option = option;
        }
    }

    public static final Map<Integer, Option> optionMap = new HashMap<>();
    static {
        for (Option option : Option.values()) {
            optionMap.put(option.getOption(), option);
        }
    }

    @Override
    protected Context setCtx() {
        return getContext();
    }

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

    @Override
    protected HandlerMain setHandlerMain() {
        return new ToastHandlerMain(getCtx(), getLogs()) {
            @Override
            protected void execute(Context context, int commandCode, String message) {
                if (MyApp.getInstance().getBuyList().size() <= 0) {

                    dialogCancel();
                } else {
                    Option option = optionMap.get(commandCode);

                    switch (option) {
                        case TOAST:
                            super.execute(context, commandCode, message);
                            break;
                        case COUNTDOWN_CANCEL:
                            cancelOnThreadCountdown();
                            break;
                        case SET_COUNTDOWN_TEXT:
                            setButtonCancelText(Integer.valueOf(message));
                            break;
                        case INVOICE_SUCCESSFUL:
                            MyApp.getInstance().getInvoiceData().setCarrier(message);
                            MyApp.getInstance().getReportFlowInfoData().setInvoiceInfo("carrier:" + MyApp.getInstance().getInvoiceData().getCarrier());
                            break;
                        case INVOICE_FAILED:
                            break;
                        case CHANGE_DISPATCH:
                            changeDispatch();
                            break;
                        case CHANGE_BUY:
                            getSrcHandlerMain().start(getClass().getSimpleName(), FontendActivity.Option.ADD_PRODUCT.getOption(), "");
                            changeBuy();
                            break;
                        case SET_STATUS_TEXT:
                            setStatusText(message);
                            break;
                        case SET_SCAN_INPUT:
                            // 掃碼即時回饋：把掃到的內容顯示在輸入框，讓使用者確認有掃到
                            binding.editTextNumber.setText(message);
                            binding.editTextNumber.setSelection(binding.editTextNumber.getText().length());
                            break;
                    }
                }
            }
        };
    }

    private DialogFreeGiftCodeBinding binding;
    private CloseDialogOnThreadHandler closeDialogCountdown;
    private boolean isChangeDispatch;
    private HttpAPI httpAPI;
    private boolean openBarcode;

    public CheckoutFreeGiftCodeDialog(Context context, HandlerMain srcHandlerMain) {
        super(context, srcHandlerMain);
    }

    @Override
    protected void onCreate(Context context) {
        binding = DialogFreeGiftCodeBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        isChangeDispatch = true;
        openBarcode = true;
        httpAPI = new HttpAPI(getHandlerMain());

        setInputMode(true);

        binding.btnModeKeypad.setOnClickListener(v -> {
            setInputMode(true);
            if (closeDialogCountdown != null) closeDialogCountdown.setCountdown(40);
        });

        binding.btnModeScan.setOnClickListener(v -> {
            setInputMode(false);
            if (closeDialogCountdown != null) closeDialogCountdown.setCountdown(40);
        });

        binding.buttonFinish.setOnClickListener(v -> changeOk());
        binding.buttonCancel.setOnClickListener(v -> changeBuy());

        closeDialogCountdown = new CloseDialogOnThreadHandler(getHandlerMain());
        closeDialogCountdown.start(40);

//        ProductStructure buyProduct = MyApp.getInstance().getBuyList().get(0).getProduct();
//        MyApp.getInstance().getReportFreeGiftCodeStructure().setProductId(buyProduct.getProductID());

        binding.buttonR1.setOnClickListener(v -> {
            String text = binding.editTextNumber.getText().toString();
            binding.editTextNumber.setText(text.substring(0, text.length()-1));
            binding.editTextNumber.setSelection(binding.editTextNumber.getText().length());
            closeDialogCountdown.setCountdown(40);
        });

        binding.buttonC1.setOnClickListener(v -> {
            binding.editTextNumber.setText("");
            closeDialogCountdown.setCountdown(40);
        });

        binding.button10.setOnClickListener(v -> {
            String btnName = binding.button10.getText().toString();
            String text = binding.editTextNumber.getText().toString();
            binding.editTextNumber.setText(text+btnName);
            binding.editTextNumber.setSelection(binding.editTextNumber.getText().length());
            closeDialogCountdown.setCountdown(40);
        });

        binding.button11.setOnClickListener(v -> {
            String btnName = binding.button11.getText().toString();
            String text = binding.editTextNumber.getText().toString();
            binding.editTextNumber.setText(text+btnName);
            binding.editTextNumber.setSelection(binding.editTextNumber.getText().length());
            closeDialogCountdown.setCountdown(40);
        });

        binding.button12.setOnClickListener(v -> {
            String btnName = binding.button12.getText().toString();
            String text = binding.editTextNumber.getText().toString();
            binding.editTextNumber.setText(text+btnName);
            binding.editTextNumber.setSelection(binding.editTextNumber.getText().length());
            closeDialogCountdown.setCountdown(40);
        });

        binding.button13.setOnClickListener(v -> {
            String btnName = binding.button13.getText().toString();
            String text = binding.editTextNumber.getText().toString();
            binding.editTextNumber.setText(text+btnName);
            binding.editTextNumber.setSelection(binding.editTextNumber.getText().length());
            closeDialogCountdown.setCountdown(40);
        });

        binding.button14.setOnClickListener(v -> {
            String btnName = binding.button14.getText().toString();
            String text = binding.editTextNumber.getText().toString();
            binding.editTextNumber.setText(text+btnName);
            binding.editTextNumber.setSelection(binding.editTextNumber.getText().length());
            closeDialogCountdown.setCountdown(40);
        });

        binding.button15.setOnClickListener(v -> {
            String btnName = binding.button15.getText().toString();
            String text = binding.editTextNumber.getText().toString();
            binding.editTextNumber.setText(text+btnName);
            binding.editTextNumber.setSelection(binding.editTextNumber.getText().length());
            closeDialogCountdown.setCountdown(40);
        });

        binding.button16.setOnClickListener(v -> {
            String btnName = binding.button16.getText().toString();
            String text = binding.editTextNumber.getText().toString();
            binding.editTextNumber.setText(text+btnName);
            binding.editTextNumber.setSelection(binding.editTextNumber.getText().length());
            closeDialogCountdown.setCountdown(40);
        });

        binding.button17.setOnClickListener(v -> {
            String btnName = binding.button17.getText().toString();
            String text = binding.editTextNumber.getText().toString();
            binding.editTextNumber.setText(text+btnName);
            binding.editTextNumber.setSelection(binding.editTextNumber.getText().length());
            closeDialogCountdown.setCountdown(40);
        });

        binding.button18.setOnClickListener(v -> {
            String btnName = binding.button18.getText().toString();
            String text = binding.editTextNumber.getText().toString();
            binding.editTextNumber.setText(text+btnName);
            binding.editTextNumber.setSelection(binding.editTextNumber.getText().length());
            closeDialogCountdown.setCountdown(40);
        });

        binding.button19.setOnClickListener(v -> {
            String btnName = binding.button19.getText().toString();
            String text = binding.editTextNumber.getText().toString();
            binding.editTextNumber.setText(text+btnName);
            binding.editTextNumber.setSelection(binding.editTextNumber.getText().length());
            closeDialogCountdown.setCountdown(40);
        });

        // 立即開始聽掃描器（原本延遲 5 秒，導致對話框剛彈出時掃碼被整個丟掉 → 時好時壞、無回饋）
        new ReadBarCodeOnScheduler(getHandlerMain()).start(0, TimeUnit.SECONDS);
    }

    public class ReadBarCodeOnScheduler extends HandlerMainScheduler {
        public ReadBarCodeOnScheduler(HandlerMain handlerMain) {
            super(handlerMain);
        }

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

        @Override
        protected void execute(HandlerMain handlerMain) {
            try {
                int totalPrice = 0;
                for (BuyStructure buy : MyApp.getInstance().getBuyList()) {
                    totalPrice += buy.getFullPrice();
                }

                UsbDev usbDev = new UsbDev(DeviceType.QRCODE_SCANNER);
                byte[] buffer = new byte[1000];
                usbDev.read(buffer, 100);
                for (int i=0; i<9; i++) { // 約 45 秒讀取窗口，覆蓋 40 秒對話框存活時間
                    if (isRun() && openBarcode) {
                        int size = usbDev.read(buffer, 5000);
                        if (size > 5) {
                            String barCodeString = new String(buffer, 0, size).trim();
                            // 掃碼即時回饋：先把掃到的內容顯示在輸入框，再送出驗證
                            getHandlerMain().start(getClass().getSimpleName(), Option.SET_SCAN_INPUT.getOption(), barCodeString);
                            submitWelcomeGift(barCodeString);
                            openBarcode = false;
                        }
                    }
                }
                usbDev.closePort();
            } catch (LogsUnsupportedOperationException | LogsIOException | LogsEmptyException e) {
                getLogs().warning(e);
            }
        }

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

    private void setInputMode(boolean isKeyboard) {
        binding.btnModeKeypad.setSelected(isKeyboard);
        binding.btnModeScan.setSelected(!isKeyboard);

        binding.linearNumpad.setVisibility(isKeyboard ? android.view.View.VISIBLE : android.view.View.GONE);
        binding.imageViewScanHint.setVisibility(isKeyboard ? android.view.View.GONE : android.view.View.VISIBLE);
    }

    public int getTotalPrice() {
        int totalPrice = 0;
        if (MyApp.getInstance().getBuyList().size() == 0) return totalPrice;
        for(BuyStructure buy: MyApp.getInstance().getBuyList()) {
            totalPrice += buy.getFullPrice();
        }
        return totalPrice;
    }

    public void changeDispatch() {
        if (isChangeDispatch) {
            closeDialogCountdown.shutdown();
            isChangeDispatch = false;
            changeDialog(DispatchDialog.class);
        }
    }

    public void changeOk() {
        String number = binding.editTextNumber.getText().toString().trim();
        if (number.isEmpty() || number.length() < 8) {
            getHandlerMain().start(getClass().getSimpleName(), Option.SET_STATUS_TEXT.getOption(), getCtx().getString(R.string.gift_code_min_8));
            return;
        }
        submitWelcomeGift(number);
    }

    /**
     * 來店禮驗證改走 StarCloudAPI B690（取代舊 HttpAPI.freeGiftCode）。
     * B690 只回折扣（amount/percentage），無「免費商品」型；成功即套折扣並返回 BuyDialog 結帳。
     */
    private void submitWelcomeGift(String code) {
        // 防護：來店禮關閉即不開放呼叫 B690（即使 UI 漏出入口也擋下）
        if (!MyApp.getInstance().getDevSet().isWelcomeGift()) {
            openBarcode = true;
            getHandlerMain().start(getClass().getSimpleName(), Option.SET_STATUS_TEXT.getOption(), getCtx().getString(R.string.gift_not_enabled));
            return;
        }
        getHandlerMain().start(getClass().getSimpleName(), Option.SET_STATUS_TEXT.getOption(), getCtx().getString(R.string.verifying));
        new com.unibuy.smartdevice.external.StarCloudAPI(getHandlerMain(), getHandlerMain())
                .verifyWelcomeGift(code, new com.unibuy.smartdevice.external.StarCloudAPI.WelcomeGiftCallback() {
            @Override
            public void onSuccess(String codeId, String discountType, int discountValue, String discountLabel, String name) {
                // 映射到既有折扣機制：mode 1=折抵金額、mode 2=折扣百分比（乘數）。
                MyApp.getInstance().getReportFreeGiftCodeStructure().setFreeGiftId(codeId);
                MyApp.getInstance().getReportFreeGiftCodeStructure().setPassCode(code);
                MyApp.getInstance().getReportFlowInfoData().setReportFlowId(code);
                MyApp.getInstance().getReportFlowInfoData().setFlowBarCode(code);
                if ("amount".equals(discountType)) {
                    MyApp.getInstance().getReportFreeGiftCodeStructure().setMode(1);
                    MyApp.getInstance().getReportFreeGiftCodeStructure().setDiscountAmount(discountValue);
                } else if ("percentage".equals(discountType)) {
                    MyApp.getInstance().getReportFreeGiftCodeStructure().setMode(2);
                    // discountValue 為折扣趴數（八折=20）→ 換算成總價乘數 0.8
                    MyApp.getInstance().getReportFreeGiftCodeStructure()
                            .setDiscountPercentage((100 - discountValue) / 100f);
                } else {
                    openBarcode = true;
                    getHandlerMain().start(getClass().getSimpleName(), Option.SET_STATUS_TEXT.getOption(), getContext().getString(R.string.unsupported_discount_type));
                    return;
                }
                getHandlerMain().start(getClass().getSimpleName(), Option.CHANGE_BUY.getOption(), "change buy");
            }

            @Override
            public void onFailure(String message) {
                openBarcode = true; // 允許重新掃碼/輸入
                getHandlerMain().start(getClass().getSimpleName(), Option.SET_STATUS_TEXT.getOption(), message);
            }
        });
    }

    public void changeBuy() {
        closeDialogCountdown.shutdown();
        changeDialog(BuyDialog.class);
//        BuyDialog buyDialog = new BuyDialog(getContext(), getSrcHandlerMain());
//        buyDialog.show();
//        cancel();
    }

    public void setStatusText(String message) {
        binding.textStatus.setText(message);
    }

    public void dialogCancel() {
        MyApp.getInstance().setReportFreeGiftCodeStructure(new ReportFreeGiftCodeStructure("", 0, "", 0, 0, ""));
        getSrcHandlerMain().start(getClass().getSimpleName(), FontendActivity.Option.STOP_COUNTDOWN.getOption(), "");
        closeDialogCountdown.shutdown();
        MyApp.getInstance().getBuyList().clear();
        cancel();
    }

    public void cancelOnThreadCountdown() {
        MyApp.getInstance().getBuyList().clear();
        cancel();
    }

    public void setButtonCancelText(long countdown) {
        binding.buttonCancel.setText(getCtx().getString(R.string.return_to)+"("+countdown+")");
    }

//    public void reportAccessCodeData()  {
//        try {
//            MyApp.getInstance().getReportAccessCodeStructure().setField(MyApp.getInstance().getReportAccessCodeStructure().getField());
//            MyApp.getInstance().getReportAccessCodeStructure().setSlot(MyApp.getInstance().getBuyList().get(0).getSlot());
//            MyApp.getInstance().getReportAccessCodeStructure().setProductId(MyApp.getInstance().getReportAccessCodeStructure().getProductId());
//            httpAPI.reportAccessCode(MyApp.getInstance().getReportAccessCodeStructure());
//        } catch (LogsParseException e) {
//            throw new RuntimeException(e);
//        } catch (LogsSettingEmptyException e) {
//            throw new RuntimeException(e);
//        }
//    }

    public static class CloseDialogOnThreadHandler extends HandlerMainCountdown {
        public CloseDialogOnThreadHandler(HandlerMain handlerMain) {
            super(handlerMain);
            handlerMain.start(getClass().getSimpleName(), CashPayDialog.Option.SET_COUNTDOWN_TEXT.getOption(), String.valueOf(getSrcCountdown()));
        }

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

        @Override
        protected void close(HandlerMain handlerMain) {
            handlerMain.start(getClass().getSimpleName(), BuyDialog.Option.COUNTDOWN_CANCEL.getOption(), "close dialog");
        }

        @Override
        protected void execute(long countdown, HandlerMain handlerMain) {
            handlerMain.start(getClass().getSimpleName(), BuyDialog.Option.SET_COUNTDOWN_TEXT.getOption(), String.valueOf(countdown));
        }

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