package com.unibuy.smartdevice;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

import androidx.appcompat.app.AppCompatActivity;

import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.Tools;
import com.unibuy.smartdevice.ui.FontendActivity;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public abstract class DialogAbstract extends AlertDialog {
    private static final Map<Class<? extends DialogAbstract>, DialogAbstract> dialogInstances = new HashMap<>();
    private Context ctx;
    private Logs logs;
    private Tools tools;
    private HandlerMain handlerMain;
    private HandlerMain srcHandlerMain;


    public Context getCtx() {
        return ctx;
    }

    public Logs getLogs() {
        return logs;
    }

    public Tools getTools() {
        return tools;
    }

    public HandlerMain getHandlerMain() {
        return handlerMain;
    }

    public HandlerMain getSrcHandlerMain() {
        return srcHandlerMain;
    }

    protected abstract Context setCtx();
    protected abstract Class<? extends DialogAbstract> setCls();
    protected abstract HandlerMain setHandlerMain();

    public DialogAbstract(Context context, HandlerMain srcHandlerMain) {
        super(context);
        ctx = setCtx();
        this.logs = new Logs(setCls());
        this.tools = new Tools(getCtx(), logs);
        this.srcHandlerMain = srcHandlerMain;
        this.handlerMain = setHandlerMain();

        getLogs().info("open dialog:" + setCls().getSimpleName());
        getLogs().info("srcHandlerMain class:" + getSrcHandlerMain().getLogs().getClassName());
        getLogs().info("handlerMain class:" + getHandlerMain().getLogs().getClassName());

        setCanceledOnTouchOutside(false);
        setOnShowListener(dialogInterface -> {
            if (getWindow() != null) {
                getWindow().getDecorView().setSystemUiVisibility(
                        View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                );
            }
        });

        getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 設定對話框寬度為螢幕的 90%
        Window window = getWindow();
        if (window != null) {
            window.setBackgroundDrawable(new android.graphics.drawable.ColorDrawable(android.graphics.Color.TRANSPARENT));
            WindowManager.LayoutParams layoutParams = window.getAttributes();
//            layoutParams.width = (int) (getContext().getResources().getDisplayMetrics().widthPixels * 0.9);

            // 設定寬度為螢幕寬度
            layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;

            // 設定高度為包裹內容（可調整為 MATCH_PARENT）
            layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

            // 設定對話框居中顯示
            layoutParams.gravity = Gravity.CENTER;

            window.setAttributes(layoutParams);
            getSrcHandlerMain().start(getClass().getSimpleName(), FontendActivity.Option.HIDE_SALE_OVERLAY.getOption(), "hide sale overlay");
        }

        setCancelable(false);
        if (setCtx() instanceof Activity) {
            setOwnerActivity((Activity) setCtx());
        }

        MyApp.getInstance().setShowDialog(true);

        onCreate(setCtx());
    }

    public void changeDialog(Class<? extends DialogAbstract> cls) {
        try {
            // 檢查 getCtx() 和 getSrcHandlerMain() 返回有效值
            Context context = getCtx();
            HandlerMain handlerMain = getSrcHandlerMain();

            if (context == null || handlerMain == null) {
                getLogs().debug("Context or HandlerMain is null. Cannot proceed with dialog change.");
                return;
            }

            // 創建新對話框實例
            DialogAbstract newDialog = cls
                    .getConstructor(Context.class, HandlerMain.class)
                    .newInstance(context, handlerMain);

            // 顯示對話框
            if (!newDialog.isShowing()) {
                newDialog.show();
            }

            // 取消當前對話框
            this.cancel();

            getLogs().debug("dialog is change:" + cls.getSimpleName());
        } catch (Exception e) {
            getLogs().warning(e);
        }
    }

    /**
     * 解析當前 flavor 要使用的現金付款 Dialog 類別。
     * General 使用強化版 CashPayDialogGeneral，其餘 flavor 使用標準 CashPayDialog。
     * 透過 SaleFlowHandler.cashDialogClass() 由各 flavor 決定，避免共用碼直接相依 flavor 類別。
     */
    protected Class<? extends DialogAbstract> cashDialogClass() {
        Context c = getCtx();
        if (c instanceof FontendActivity) {
            com.unibuy.smartdevice.ui.SaleFlowHandler handler =
                    ((FontendActivity) c).getSaleFlowHandler();
            if (handler != null) {
                return handler.cashDialogClass();
            }
        }
        return com.unibuy.smartdevice.ui.dialog.CashPayDialogGeneral.class;
    }


//    public void changeDialog(Class<? extends DialogAbstract> cls) {
//        try {
//            // 創建新對話框實例
//            DialogAbstract newDialog = cls
//                    .getConstructor(Context.class, HandlerMain.class)
//                    .newInstance(getCtx(), getSrcHandlerMain());
//
//            newDialog.show();
//            if (!newDialog.isShow()) {
//                newDialog.show();
//            }
//
//            // 取消當前對話框
//            super.cancel();
//        } catch (Exception e) {
//            getLogs().debug("Failed to change dialog: " + e.getMessage());
//        }
//    }

    @Override
    public void show() {
        Class<? extends DialogAbstract> cls = setCls();

        if (dialogInstances.containsKey(cls) && dialogInstances.get(cls).isShowing()) {
            getLogs().debug("dialog is open:" + cls.getSimpleName());
            getHandlerMain().start(cls.getSimpleName(), getLogs().getMessage());
            getLogs().clearMessage();
            return;
        }

        dialogInstances.put(cls, this);
        super.show();
        MyApp.getInstance().setShowDialog(true);
    }

    public boolean isShow() {
        Class<? extends DialogAbstract> cls = setCls();

        return dialogInstances.containsKey(cls);
    }

    @Override
    public void dismiss() {
        super.dismiss();
        // 在關閉對話框時，移除記錄並重置全域狀態
        dialogInstances.remove(setCls());
        if (dialogInstances.isEmpty()) {
            MyApp.getInstance().setShowDialog(false);
        }
    }

    protected abstract void onCreate(Context context);

    @Override
    public void cancel() {
        super.cancel();
        // MyApp.getInstance().setShowDialog(false); // 移至 dismiss 統一處理
        getSrcHandlerMain().start(getClass().getSimpleName(), FontendActivity.Option.SHOW_SALE_OVERLAY.getOption(), "show sale overlay");
    }

    @Override
    public boolean dispatchTouchEvent(android.view.MotionEvent ev) {
        // 對話框有自己的 Window，使用者觸控對話框時不會經過宿主 Activity 的 dispatchTouchEvent。
        // 這裡補上「真人觸控即更新全域閒置時間」，避免使用者正在操作對話框時被待機看門狗誤關。
        // 只認觸控、不認 HID 按鍵(掃碼槍/讀卡機)，故幽靈按鍵仍無法把對話框卡死。
        MyApp.getInstance().updateLastInteraction();
        return super.dispatchTouchEvent(ev);
    }

    /**
     * 此對話框是否需要接收實體鍵盤/掃碼槍/讀卡機等 HID 輸入。
     * 預設 false：購物畫面的 Enter/Numpad_Enter 會被攔截以防 HID 誤觸。
     * 取貨碼、會員卡等真正需要 HID 輸入的對話框應覆寫為 true。
     */
    public boolean isInputNeededDialog() {
        return false;
    }

    /**
     * 此對話框是否屬於「忙碌」狀態（交易/金流/出貨進行中），不可被閒置返回首頁或遠端重啟打斷。
     * 預設 true（付款、出貨等沿用既有保護）；純瀏覽性質的對話框（如商品詳情）應覆寫為 false，
     * 以免把機台一直卡在 [Dialog Open] 忙碌而擋掉待機與遠端重啟。
     */
    public boolean isBusyDialog() {
        return true;
    }

    /** 目前是否有任何「需要 HID 輸入」的對話框正在顯示 */
    public static boolean hasInputNeededDialogShowing() {
        synchronized (dialogInstances) {
            for (DialogAbstract dialog : dialogInstances.values()) {
                if (dialog != null && dialog.isShowing() && dialog.isInputNeededDialog()) {
                    return true;
                }
            }
        }
        return false;
    }

    /** 目前是否有任何「忙碌（交易/金流/出貨）」對話框正在顯示 */
    public static boolean hasBusyDialogShowing() {
        synchronized (dialogInstances) {
            for (DialogAbstract dialog : dialogInstances.values()) {
                if (dialog != null && dialog.isShowing() && dialog.isBusyDialog()) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 閒置返回首頁時統一安全關閉所有顯示中的對話框，避免殘窗（WindowLeaked）並重置全域旗標。
     * 以 dialogInstances 的複本迭代，避免 dismiss() 內移除元素造成 ConcurrentModification。
     */
    public static void dismissAll() {
        synchronized (dialogInstances) {
            for (DialogAbstract dialog : new java.util.ArrayList<>(dialogInstances.values())) {
                if (dialog != null && dialog.isShowing()) {
                    try {
                        dialog.dismiss();
                    } catch (Exception e) {
                        // 忽略單一對話框關閉異常，確保其餘對話框仍會被關閉
                    }
                }
            }
            dialogInstances.clear();
        }
        MyApp.getInstance().setShowDialog(false);
    }
}
