package com.unibuy.smartdevice.ui.dialog;

import android.app.AlertDialog;
import android.content.Context;
import android.os.Handler;
import android.text.InputFilter;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.unibuy.smartdevice.DialogAbstract;
import com.unibuy.smartdevice.MyApp;
import com.unibuy.smartdevice.R;
import com.unibuy.smartdevice.databinding.DialogInvoiceBarcodeBinding;
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.LogsUnsupportedOperationException;
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 java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class InvoiceBarcodeDialog 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),
        CHANGE_CHECKOUT(8),
        ;

        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);
                    getLogs().info("Option " + option.getOption() + ":" + option.name());
                    switch (option) {
                        case TOAST:
                            super.execute(context, commandCode, message);
                            break;
                        case COUNTDOWN_CANCEL:
                            cancelOnThreadCountdown();
                            break;
                        case SET_COUNTDOWN_TEXT:
                            try {
                                setButtonCancelText(Integer.valueOf(message));
                            } catch (NumberFormatException e) {
                                return;
                            }
                            break;
                        case INVOICE_SUCCESSFUL:
                            // --- 新增：如果手動輸入視窗開著，就關閉它 ---
                            if (inputVehicleDialog != null && inputVehicleDialog.isShowing()) {
                                inputVehicleDialog.dismiss();
                            }
                            if (donationDialog != null && donationDialog.isShowing()) {
                                donationDialog.dismiss();
                            }
                            //----- 發票載具 ------
                            binding.textInvoiceCarrier.setText(getContext().getString(R.string.vehicles)+":"+message);//載具
                            MyApp.getInstance().getInvoiceData().setCarrier(message);
                            MyApp.getInstance().getReportFlowInfoData().setInvoiceInfo("carrier:" + MyApp.getInstance().getInvoiceData().getCarrier());
                            new HandlerMainCountdown(this) {
                                @Override
                                protected Class<?> setCls() {
                                    return this.getClass();
                                }

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

                                @Override
                                protected void execute(long countdown, HandlerMain handlerMain) {

                                }

                                @Override
                                protected void close(HandlerMain handlerMain) {
                                    handlerMain.start(getSrcClassName(), Option.CHANGE_CHECKOUT.getOption(), "change dispatch");
                                }
                            }.start(2);
                            break;
                        case INVOICE_FAILED:
                            break;
                        case CHANGE_DISPATCH:
                            super.execute(context, commandCode, message);
                            changeDispatch();
                            break;
                        case CHANGE_BUY:
                            super.execute(context, commandCode, message);
                            changeBuy();
                            break;
                        case CHANGE_CHECKOUT:
                            super.execute(context, commandCode, message);
                            changeCheckout();
                            break;
                    }
                }
            }
        };
    }

    private DialogInvoiceBarcodeBinding binding;
    private CloseDialogOnThreadHandler closeDialogCountdown;
    private boolean openBarcode;
    private ReadBarCodeOnScheduler readBarCodeOnScheduler;
    private LinkedHashMap<String, String> donationMap;
    private AlertDialog inputVehicleDialog;
    private AlertDialog donationDialog;

    public InvoiceBarcodeDialog(Context context, HandlerMain srcHandlerMain) {
        super(context, srcHandlerMain);
        openBarcode = true;
    }

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

        donationMap = new LinkedHashMap<>();
        intiDonationMap();

        binding.buttonCustomerIdentifier.setOnClickListener(v -> changeCustomerIdentifier());
//        binding.buttonDonation.setOnClickListener(v -> changeDonation());
        binding.buttonDonation.setOnClickListener(v -> showDonationDialog());
        binding.buttonCancel.setOnClickListener(v -> changeBuy());

        binding.buttonInputVehicle.setOnClickListener(v -> showInputVehicleDialog());

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

        readBarCodeOnScheduler = new ReadBarCodeOnScheduler(getHandlerMain());
        readBarCodeOnScheduler.start();

        //binding.imageCheckout.setOnClickListener(v -> changeDispatch());
    }

    public void intiDonationMap(){
        donationMap.put("社團法人嘉義市腦性麻痺協會", "2855669");
        donationMap.put("社團法人桃園市唐氏症家長協會", "520321");
        donationMap.put("社團法人中華民國自閉症總會", "1577");
        donationMap.put("社團法人臺北市蒲公英聽語協會", "71521");
        donationMap.put("社團法人桃園市失智症關懷協會", "8185");
        donationMap.put("財團法人台灣痲瘋救濟基金會", "1954");
        donationMap.put("社團法人中華小腦萎縮症病友協會", "9972");
        donationMap.put("社團法人高雄市唐氏症歡喜協會", "7717299");
        donationMap.put("社團法人屏東縣腦性麻痺服務協會", "115");
        donationMap.put("社團法人台南市智障者福利家長協進會", "2070");
        donationMap.put("財團法人台灣肯納自閉症基金會", "1018");
        donationMap.put("社團法人高雄市腦性麻痺服務協會", "29636");
        donationMap.put("社團法人高雄市自閉症協進會", "8585885");
        donationMap.put("社團法人臺灣自閉兒家庭關懷協會", "338518");
        donationMap.put("社團法人臺東縣自閉症協進會", "3685");
        donationMap.put("社團法人中華民國外傷性腦損傷照顧者關懷協會", "5841");
        donationMap.put("財團法人天主教靈醫會私立聖嘉民啟智中心", "57880");
        donationMap.put("社團法人新竹市智障福利協進會", "6684");
        donationMap.put("社團法人屏東縣自閉症協進會", "7351024");
        donationMap.put("社團法人台北市自閉症家長協會", "772");
        donationMap.put("社團法人屏東縣啟智協進會", "159");
        donationMap.put("社團法人花蓮縣自閉症協會", "8588");
        donationMap.put("澎湖縣私立財團法人天主教澎湖教區附設惠民啟智中心", "9261790");
        donationMap.put("財團法人新竹市私立天主教仁愛啟智中心", "227");
        donationMap.put("社團法人中華民國唐氏症關愛者協會", "88321");
        donationMap.put("財團法人天主教會台中教區附設南投縣私立復活啟智中心", "7717");
        donationMap.put("財團法人喜憨兒社會福利基金會", "88432");
        donationMap.put("社團法人花蓮縣智障福利協進會", "7756");
        donationMap.put("社團法人雲林縣啟智協會", "1311");
        donationMap.put("社團法人新竹縣智障福利協進會", "3170");
        donationMap.put("社團法人台南市腦性麻痺之友協會", "815");
        donationMap.put("社團法人台南市癲癇之友協會", "2350253");
        donationMap.put("新北市自閉症服務協進會", "7688");
        donationMap.put("社團法人台中市?智協進會", "450");
        donationMap.put("社團法人台中市自閉症教育協進會", "1127");
        donationMap.put("財團法人中華民國自閉症基金會", "402");
        donationMap.put("社團法人台灣流浪貓狗關懷協會", "9958");
        donationMap.put("社團法人台灣愛貓協會", "921314");
        donationMap.put("社團法人台灣幸褔狗流浪中途協會", "856203");
        donationMap.put("社團法人新北市流浪貓狗再生保護協會", "8866");
        donationMap.put("社團法人台灣流浪動物希望協會", "119");
        donationMap.put("社團法人高雄市幸福狗尾巴友善動物協會", "6848");
        donationMap.put("社團法人臺南市貓狗流浪終點協會", "5866");
        donationMap.put("社團法人台灣黑糖流浪動物救援協會", "958");
        donationMap.put("社團法人台灣動物輔助活動及治療協會", "916");
        donationMap.put("社團法人台灣友善動物協會", "9305");
        donationMap.put("社團法人中華民國反棄養寵物協會", "11289");
        donationMap.put("社團法人台灣流浪貓關懷協會", "71706");
        donationMap.put("社團法人台灣浪愛不流浪關懷動物協會", "9458");
        donationMap.put("台灣米樂流浪動物中途協會", "9925");
        donationMap.put("社團法人中華民國寵物友善協會", "52982");
        donationMap.put("社團法人台灣愛兔協會", "5822");
        donationMap.put("社團法人台灣拾貓生命教育創新協會", "880222");
        donationMap.put("社團法人台灣防止虐待動物協會", "1772");
        donationMap.put("社團法人好好善待動物協會", "6666666");
        donationMap.put("社團法人臺北市毛小孩幸福聯盟協會", "99891");
        donationMap.put("社團法人台南市流浪動物愛護協會", "17966");
        donationMap.put("中華民國流浪動物花園協會", "528");
        donationMap.put("台灣流浪兔保護協會", "17922");
        donationMap.put("社團法人台北市愛兔協會", "5222");
        donationMap.put("社團法人臺灣照顧生命協會", "589");
        donationMap.put("新竹市保護動物協會", "860713");
        donationMap.put("社團法人中華民國動物福利環保協進會", "529529");
        donationMap.put("財團法人中華民國兒童癌症基金會", "88888");
        donationMap.put("中華民國癌病腫瘤患者扶助協會", "6088");
        donationMap.put("財團法人臺灣癌症基金會", "1799");
    }

    public static Map.Entry<String, String> getRandomDonationEntry(Map<String, String> donationMap) {
        List<Map.Entry<String, String>> entryList = new ArrayList<>(donationMap.entrySet());
        if (entryList.isEmpty()) return null;
        Random random = new Random();
        return entryList.get(random.nextInt(entryList.size()));
    }


    public void changeDispatch() {
        closeDialogCountdown.shutdown();
        DispatchDialog dispatchDialog = new DispatchDialog(getContext(), getSrcHandlerMain());
        dispatchDialog.show();
        openBarcode = false;
        cancel();
    }

    public void changeCustomerIdentifier() {
        closeDialogCountdown.shutdown();
        new InvoiceCustomerIdentifierDialog(getCtx(), getSrcHandlerMain()).show();
        openBarcode = false;
        cancel();
    }

    public void changeDonation() {
        // 168001 OMG關懷社會愛心基金會
        MyApp.getInstance().getInvoiceData().setLoveCode("168001");
        MyApp.getInstance().getReportFlowInfoData().setInvoiceInfo(
//                "loveCode:" + MyApp.getInstance().getInvoiceData().getLoveCode()
                MyApp.getInstance().getInvoiceData().getLoveCode()
        );
        changeCheckout();
    }

    private void showDonationDialog() {
        closeDialogCountdown.shutdown();

        AlertDialog.Builder builder = new AlertDialog.Builder(getCtx());
        LayoutInflater inflater = getLayoutInflater();
        View dialogView = inflater.inflate(R.layout.dialog_donation, null);
        builder.setView(dialogView);

        CheckBox checkboxDefault = dialogView.findViewById(R.id.checkboxDefault);
        Spinner spinnerCharity = dialogView.findViewById(R.id.spinnerCharity);
        TextView tvlovecode = dialogView.findViewById(R.id.tvlovecode);

        // 1. 建立捐贈機構對應表
        // 假設這是你的捐贈機構清單
        List<String> organizationNames = new ArrayList<>(donationMap.keySet());

        ArrayAdapter<String> adapter = new ArrayAdapter<>( getCtx(),
                R.layout.spinner_item,   // ✅ 改成自訂 layout
                R.id.spinnerText,
                organizationNames);
        adapter.setDropDownViewResource(R.layout.spinner_item); // 下拉選單也套用
        spinnerCharity.setAdapter(adapter);

        // 2. 預設勾選 checkbox，並禁用 spinner
        checkboxDefault.setChecked(true);
        spinnerCharity.setEnabled(false);

        // 3. 隨機一組愛心碼，並立刻寫入
        Map.Entry<String, String> randomEntry = getRandomDonationEntry(donationMap);
        if (randomEntry != null) {
            MyApp.getInstance().getInvoiceData().setLoveCode(randomEntry.getValue());
            MyApp.getInstance().getReportFlowInfoData().setInvoiceInfo("loveCode:" + MyApp.getInstance().getInvoiceData().getLoveCode());
//            Toast.makeText(getCtx(), "預設捐贈：" + randomEntry.getKey(), Toast.LENGTH_SHORT).show();
            tvlovecode.setText("捐贈機構："+randomEntry.getKey());
        }

        // 自訂 Title
        TextView title = new TextView(getCtx());
        title.setText("選擇捐贈方式");
        title.setTextSize(24); // 放大字體
        title.setPadding(40, 40, 40, 40);
        title.setGravity(Gravity.CENTER);

        donationDialog = new AlertDialog.Builder(getCtx())
                .setCustomTitle(title) // 使用自訂 Title
                .setView(dialogView)
                .setPositiveButton("確定", (d, which) -> {
                    if (!checkboxDefault.isChecked()) {
                        String selectedName = (String) spinnerCharity.getSelectedItem();
                        String loveCode = donationMap.get(selectedName);
                        MyApp.getInstance().getInvoiceData().setLoveCode(loveCode);
                        MyApp.getInstance().getReportFlowInfoData().setInvoiceInfo("loveCode:" + MyApp.getInstance().getInvoiceData().getLoveCode());
                        Toast.makeText(getCtx(), "選擇：" + selectedName, Toast.LENGTH_SHORT).show();
                    }
                    // 若是勾選預設，之前就寫入過，不需處理
                    closeDialogCountdown.start(40); // 再次開始倒數
                    changeCheckout();
                })
                .setNegativeButton("取消", (d, which) -> {
                    // 使用者取消後，重新開始倒數 40 秒
                    closeDialogCountdown.start(40);
                })
                .create();

        donationDialog.show();

        Button positive = donationDialog.getButton(AlertDialog.BUTTON_POSITIVE);
        Button negative = donationDialog.getButton(AlertDialog.BUTTON_NEGATIVE);

        if (positive != null) {
            positive.setTextSize(24);
            positive.setPadding(30, 20, 130, 20);
        }
        if (negative != null) {
            negative.setTextSize(24);
            negative.setPadding(30, 20, 30, 20);
        }

        // 放大框架 (寬度 90%)
        Window window = donationDialog.getWindow();
        if (window != null) {
            WindowManager.LayoutParams params = new WindowManager.LayoutParams();
            params.copyFrom(window.getAttributes());
            params.width = (int) (getCtx().getResources().getDisplayMetrics().widthPixels * 0.9);
            params.height = (int) (getCtx().getResources().getDisplayMetrics().heightPixels * 0.6); // 高度 60%
            window.setAttributes(params);
        }

        // 加入：20秒後自動關閉 Dialog
        Handler handler = new Handler();
        Runnable timeoutRunnable = () -> {
            if (donationDialog.isShowing()) {
                donationDialog.dismiss();
                Toast.makeText(getCtx(), "已逾時取消", Toast.LENGTH_SHORT).show();
            }
        };
        handler.postDelayed(timeoutRunnable, 10000); // 20秒

        // 4. Checkbox 切換時控制 Spinner
        checkboxDefault.setOnCheckedChangeListener((buttonView, isChecked) -> {
            spinnerCharity.setEnabled(!isChecked);
            handler.removeCallbacks(timeoutRunnable); // 取消 timeout
        });

        spinnerCharity.setOnTouchListener((v, event) -> {
            handler.removeCallbacks(timeoutRunnable); // 取消 timeout
            return false;
        });

    }

    private void showInputVehicleDialog() {
        closeDialogCountdown.shutdown(); // 停止倒數，避免中途跳掉

        // 建立 EditText
        final android.widget.EditText input = new android.widget.EditText(getCtx());
        input.setHint("請輸入手機條碼載具 (8碼)");
        input.setTextSize(20);
        input.setSingleLine(true);
        input.setPadding(50, 40, 50, 40);

        // 限制長度 = 8 位
        input.setFilters(new InputFilter[]{new InputFilter.LengthFilter(8)});

        // 建立 Dialog
        inputVehicleDialog = new AlertDialog.Builder(getCtx())
                .setTitle("輸入手機條碼載具")
                .setView(input)
                .setPositiveButton("確定", null) // 這裡先給 null，避免自動關閉
                .setNegativeButton("取消", (d, which) -> {
                    closeDialogCountdown.start(40); // 取消也要重啟倒數
                })
                .create();

        inputVehicleDialog.setOnShowListener(dlg -> {
            Button positive = inputVehicleDialog.getButton(AlertDialog.BUTTON_POSITIVE);
            Button negative = inputVehicleDialog.getButton(AlertDialog.BUTTON_NEGATIVE);

            if (positive != null) {
                positive.setTextSize(20);
                positive.setOnClickListener(v -> {
                    String barCodeString = input.getText().toString().trim();

                    if (barCodeString.length() == 8) {
                        // ✅ 呼叫 handlerMain，直接走跟掃描相同流程
                        getHandlerMain().start(
                                getClass().getSimpleName(),
                                Option.INVOICE_SUCCESSFUL.getOption(),
                                barCodeString
                        );

                        inputVehicleDialog.dismiss(); // 關閉輸入視窗
                    } else {
                        Toast.makeText(getCtx(), "手機條碼載具必須是 8 碼", Toast.LENGTH_SHORT).show();
                    }
                });
            }

            if (negative != null) {
                negative.setTextSize(20);
            }
        });

        inputVehicleDialog.show();
    }




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

    public void changeCheckout() {
        closeDialogCountdown.shutdown();
        int flowType = MyApp.getInstance().getReportFlowInfoData().getFlowType();
        switch (flowType) {
            case 1:
                changeDialog(CheckoutNfcCardDialog.class);
                break;
            case 2:
                changeDialog(CheckoutNfcRechargeDialog.class);
                break;
            case 3:
                changeDialog(CheckoutEsunPayDialog.class);
                break;
            case 4:
                changeDialog(CheckoutNfcPhoneDialog.class);
                break;
            case 9:
                changeDialog(CashPayDialog.class);
                break;
            case 30:
                changeDialog(CheckoutTapPayDialog.class);
                break;
            case 70:
                changeDialog(CheckoutLinePayDialog.class);
                break;
        }
        openBarcode = false;
        cancel();
    }

    public void dialogCancel() {
        readBarCodeOnScheduler.setRun(false);
        closeDialogCountdown.shutdown();
        MyApp.getInstance().getBuyList().clear();
        openBarcode = false;
        cancel();
    }

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

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

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

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

        @Override
        protected void execute(HandlerMain handlerMain) {
            try {
                UsbDev usbDev = new UsbDev(DeviceType.QRCODE_SCANNER);
                byte[] buffer = new byte[20];
                usbDev.read(buffer, 100);
                for (int i=0; i<7; i++) {
                    if (isRun() && openBarcode) {
                        int size = usbDev.read(buffer, 5000);
                        if (size > 5) {
                            String barCodeString = new String(buffer, 0, size);
                            handlerMain.start(getClass().getSimpleName(), Option.INVOICE_SUCCESSFUL.getOption(), barCodeString);
                            openBarcode = false;
                        }
                    }
                }
                usbDev.closePort();
            } catch (LogsUnsupportedOperationException | LogsIOException | LogsEmptyException e) {
                getLogs().warning(e);
            }
        }

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

    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();
        }
    }
}
