package com.dspread.pos.ui.mulberry;

import static com.dspread.pos.utils.PosParameters.NAV_HOME;

import android.app.Application;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.databinding.Observable;
import androidx.databinding.ObservableArrayList;
import androidx.databinding.ObservableField;
import androidx.databinding.ObservableList;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;

import com.dspread.pos.common.base.BaseAppViewModel;
import com.dspread.pos.data.local.PreferencesManager;
import com.dspread.pos.utils.ImageUtils;
import com.dspread.pos.utils.PosParameters;
import com.dspread.pos.utils.TRACE;
import com.dspread.pos_android_app.BR;
import com.dspread.pos_android_app.R;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import me.tatarka.bindingcollectionadapter2.ItemBinding;
import me.goldze.mvvmhabit.bus.event.SingleLiveEvent;
import me.goldze.mvvmhabit.base.ItemViewModel;

public class MulberryViewModel extends BaseAppViewModel {
    private static final String TAG = "MulberryVM";

    // UI Observables
    public final ObservableField<Integer> mainLogo = new ObservableField<>();
    public final ObservableField<Integer> footerLogo = new ObservableField<>();

    public final ObservableField<Bitmap> mainLogoBitmap = new ObservableField<>();
    public final ObservableField<Bitmap> footerLogoBitmap = new ObservableField<>();
    public final ObservableField<Boolean> logoVisibility = PosParameters.footerLogoVisibility;
    public final ObservableField<Boolean> logoTextVisibility = PosParameters.footerTextVisibility;
    public final ObservableField<String> greetingText = PosParameters.footerGreetingText;
    public final ObservableField<String> footerText = PosParameters.footerText;
    public final ObservableField<String> primaryColor = PosParameters.primaryColor;

    // Navigation
    public final SingleLiveEvent<Integer> navigateToFragment = new SingleLiveEvent<>();
    public final SingleLiveEvent<Class<?>> navigateToActivity = new SingleLiveEvent<>();
    public final ObservableList<MulberryItemViewModel> navItems = new ObservableArrayList<>();
    public final ItemBinding<MulberryItemViewModel> itemBinding =
            ItemBinding.of(BR.viewModel, R.layout.item_mulberry_card);

    // Image cache
    private final Map<String, Bitmap> imageCache = new HashMap<>();
    private final MutableLiveData<Boolean> imagesLoaded = new MutableLiveData<>(false);

    public MulberryViewModel(@NonNull Application application) {
        super(application);
        TRACE.i("Mulberry fragment init");
        Log.d(TAG, "MulberryViewModel constructor called");

        // Add this to track initialization
        Log.d(TAG, "ViewModel hash: " + this.hashCode());
        if (Build.MODEL.equalsIgnoreCase("D70") ||
                Build.MODEL.equalsIgnoreCase("D30") ||
                Build.MODEL.equalsIgnoreCase("D30M") ||
                Build.MODEL.equalsIgnoreCase("D80")||
                Build.MODEL.equalsIgnoreCase("D80K")) {
            Log.d("Build.MODEL", "MainViewModel: " + Build.MODEL);;
            // To-Do set small size of logo ,and grid size 3 by 1
        }



        // Observe WebSocket connection status
        getWebSocketConnectionStatus().observeForever(isConnected -> {
            if (isConnected) {
                Log.d("MulberryVM", "Connected to WebSocket");
            } else {
                Log.d("MulberryVM", "Disconnected from WebSocket");
            }
        });

        // Observe WebSocket errors
        getWebSocketError().observeForever(error -> {

            Log.d(TAG, "WebSocket error: " + error);
        });

        initialize();
    }

    private void initialize() {
        Log.d(TAG, "Initializing ViewModel");

        // Load configuration from pref
        loadConfigurationFromPrefs();

        // Set up live data observers
        setupObservers();
    }

    /**
     * Loads configuration with option for fast/slow mode
     * @param fullRefresh true to reload all images from disk (slower)
     */
    private void loadConfiguration(boolean fullRefresh) {
        Log.d(TAG, "Loading configuration (fullRefresh: " + fullRefresh + ")");

        // 1. Update main config parameters
        updateMainConfig(fullRefresh);

        // 2. Load navigation items
        loadNavigationItems(fullRefresh);


        // 3. If full refresh, notify when images are ready
        if (fullRefresh) {
            imagesLoaded.postValue(true);
        }
    }

    private void updateMainConfig(boolean loadImages) {
        Log.d(TAG, "Updating main configuration");

        // Set observable fields
        mainLogo.set(PosParameters.mainLogo.get());
        footerLogo.set(PosParameters.footerLogo.get());
        greetingText.set(PosParameters.footerGreetingText.get());
        footerText.set(PosParameters.footerText.get());
        primaryColor.set(PosParameters.primaryColor.get());

        // Load images if requested
        if (loadImages) {
            loadLogoImages();
        }
    }

    private void loadLogoImages() {
        new Thread(() -> {
            // Main logo
            Integer mainLogoRes = PosParameters.mainLogo.get();
            if (mainLogoRes != null) {
                if (mainLogoRes == -1) {
                    // Handle file path from prefs
                    String path = prefs.getString("main_logo_path", null);
                    if (path != null) {
                        Bitmap bitmap = BitmapFactory.decodeFile(path);
                        if (bitmap != null) {
                            mainLogoBitmap.set(bitmap);
                            imageCache.put("main_logo", bitmap);
                        }
                    }
                } else {
                    // Regular resource ID
                    Bitmap bitmap = loadImageForResource(mainLogoRes);
                    if (bitmap != null) {
                        imageCache.put("main_logo", bitmap);
                    }
                }
            }

            // Footer logo
            Integer footerLogoRes = PosParameters.footerLogo.get();
            if (footerLogoRes != null) {
                if (footerLogoRes == -1) {
                    String path = prefs.getString("footer_logo_path", null);
                    if (path != null) {
                        Bitmap bitmap = BitmapFactory.decodeFile(path);
                        if (bitmap != null) {
                            footerLogoBitmap.set(bitmap);
                            imageCache.put("footer_logo", bitmap);
                        }
                    }
                } else {
                    Bitmap bitmap = loadImageForResource(footerLogoRes);
                    if (bitmap != null) {
                        imageCache.put("footer_logo", bitmap);
                    }
                }
            }

            imagesLoaded.postValue(true);
        }).start();
    }

    private Bitmap loadImageForResource(Integer resourceId) {
        if (resourceId == null) return null;

        try {
            // Default to Android resource
            return BitmapFactory.decodeResource(getApplication().getResources(), resourceId);
        } catch (Exception e) {
            Log.e(TAG, "Error loading image resource", e);
            return null;
        }
    }

    private void loadNavigationItems(boolean loadImages) {
        Log.d(TAG, "========== START loadNavigationItems ==========");
        Log.d(TAG, "loadImages flag: " + loadImages);

        navItems.clear();
        Log.d(TAG, "Cleared existing navItems list");

        // Collect all enabled items
        List<PosParameters.NavItem> enabledItems = new ArrayList<>();
        Log.d(TAG, "Initialized empty enabledItems list");

        // Log all available items first
        Log.d(TAG, "==== ALL AVAILABLE ITEMS IN PosParameters ====");
        for (Map.Entry<Integer, List<PosParameters.NavItem>> entry : PosParameters.NAV_ITEMS.entrySet()) {
            int pageId = entry.getKey();
            String pageName = PosParameters.getNavPageName(pageId);
            Log.d(TAG, "Page: " + pageName + " (ID: " + pageId + ") has " + entry.getValue().size() + " items");

            for (PosParameters.NavItem item : entry.getValue()) {
                Log.d(TAG, "  Item: " + item.name +
                        " | Position: " + item.position +
                        " | Enabled: " + item.enabled +
                        " | Icon: " + item.iconSource);
            }
        }

        // Now collect enabled items
        Log.d(TAG, "==== COLLECTING ENABLED ITEMS ====");
        for (Map.Entry<Integer, List<PosParameters.NavItem>> entry : PosParameters.NAV_ITEMS.entrySet()) {
            int pageId = entry.getKey();
            String pageName = PosParameters.getNavPageName(pageId);

            for (PosParameters.NavItem item : entry.getValue()) {
                if (item.enabled) {
                    enabledItems.add(item);
                    Log.d(TAG, "ADDED to enabledItems - Page: " + pageName +
                            " | Item: " + item.name +
                            " | Position: " + item.position +
                            " | Icon: " + item.iconSource);
                } else {
                    Log.d(TAG, "SKIPPED disabled item - Page: " + pageName +
                            " | Item: " + item.name);
                }
            }
        }

        Log.d(TAG, "Found " + enabledItems.size() + " enabled items total");

        // Log before sorting
        Log.d(TAG, "==== ITEMS BEFORE SORTING ====");
        for (PosParameters.NavItem item : enabledItems) {
            Log.d(TAG, "Pre-sort - Position: " + item.position + " | Name: " + item.name);
        }

        // Sort by position
        Collections.sort(enabledItems, (i1, i2) -> {
            Log.d(TAG, "Comparing positions: " + i1.position + " (" + i1.name + ") vs " +
                    i2.position + " (" + i2.name + ")");
            return Integer.compare(i1.position, i2.position);
        });

        // Log after sorting
        Log.d(TAG, "==== ITEMS AFTER SORTING ====");
        for (PosParameters.NavItem item : enabledItems) {
            Log.d(TAG, "Post-sort - Position: " + item.position + " | Name: " + item.name);
        }

        // Create ViewModels
        Log.d(TAG, "==== CREATING VIEWMODELS ====");
        for (PosParameters.NavItem item : enabledItems) {
            Log.d(TAG, "Creating ViewModel for: " + item.name);
            navItems.add(createNavItemViewModel(item, loadImages));
        }

        Log.d(TAG, "========== FINISHED loadNavigationItems ==========");
        Log.d(TAG, "Total navigation items loaded: " + navItems.size());
    }

    private MulberryItemViewModel createNavItemViewModel(PosParameters.NavItem item, boolean loadImage) {

        return new MulberryItemViewModel(
                this,
                item.name,
                item.iconSource, // Pass either resource name or file path
//                iconBitmap,    // Pass pre-loaded bitmap if available
                item.navPage,
                null
        );
    }

    @Override
    protected void onConfigurationUpdated() {
        super.onConfigurationUpdated();
        Log.d(TAG, "onConfigurationUpdated called - hash: " + this.hashCode());

        // Check if ViewModel is still active
        if (navItems == null) {
            Log.w(TAG, "navItems is null - ViewModel might be cleared");
            return;
        }

        try {
            Log.d(TAG, "Configuration updated - performing full refresh");
            loadConfiguration(true);
        } catch (Exception e) {
            Log.e(TAG, "Error in onConfigurationUpdated", e);
        }
    }

    private void setupObservers() {
        // Observe logo changes
        PosParameters.mainLogo.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
            @Override
            public void onPropertyChanged(Observable sender, int propertyId) {
                mainLogo.set(PosParameters.mainLogo.get());
            }
        });

        PosParameters.footerLogo.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
            @Override
            public void onPropertyChanged(Observable sender, int propertyId) {
                footerLogo.set(PosParameters.footerLogo.get());
            }
        });
        // Observe other important parameters
        PosParameters.footerLogoVisibility.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
            @Override
            public void onPropertyChanged(Observable sender, int propertyId) {
                logoVisibility.set(PosParameters.footerLogoVisibility.get());
            }
        });

    }

    public void onItemClick(MulberryItemViewModel item) {
        Log.d(TAG, "Navigation item clicked: " + item.title.get());
//        sendWebSocketMessage("{\"type\":\"message\", \"content\": \"Navigation item clicked\" }");

        if (item.fragmentId != null) {
            navigateToFragment.setValue(item.fragmentId);
        } else if (item.activityClass != null) {
            navigateToActivity.setValue(item.activityClass);
        }
    }

    private void loadConfigurationFromPrefs() {
        Log.d(TAG, "Loading configuration exclusively from preferences");

        prefs = PreferencesManager.getInstance(getApplication());


        // Handle logos - supports both resource IDs and file paths
        int mainLogoRes = prefs.getInt("main_logo", -1);
        if (mainLogoRes == -1) {
            // Load from file path
            String path = prefs.getString("main_logo_path", null);
            if (path != null) {
                Bitmap bitmap = BitmapFactory.decodeFile(path);
                if (bitmap != null) {
                    // Use a custom binding adapter to set bitmap
                    mainLogoBitmap.set(bitmap);
                }
            }
        } else {
            // Regular resource ID
            mainLogo.set(mainLogoRes);
        }

        // same logic for footer logo
        int footerLogoRes = prefs.getInt("footer_logo", -1);
        if (footerLogoRes == -1) {
            String path = prefs.getString("footer_logo_path", null);
            if (path != null) {
                Bitmap bitmap = BitmapFactory.decodeFile(path);
                if (bitmap != null) {
                    footerLogoBitmap.set(bitmap);
                }
            }
        } else {
            footerLogo.set(footerLogoRes);
        }

        // 1. Load UI configuration
//        mainLogo.set(prefs.getInt("main_logo", 2131230807));
//        footerLogo.set(prefs.getInt("footer_logo", 2131230807));

        greetingText.set(prefs.getString("footer_greeting_text", ""));
        footerText.set(prefs.getString("footer_text", ""));
        primaryColor.set(prefs.getString("primary_color", "#000000"));
        logoVisibility.set(prefs.getBoolean("footer_logo_visibility", true));

        // 2. Load navigation items from prefs
//        String savedNavItemsJson = prefs.getString("PREF_NAV_ITEMS", null);
        String savedNavItemsJson = prefs.getString("nav_items", null);
        if (savedNavItemsJson != null) {
            loadNavigationItemsFromJson(savedNavItemsJson, false);
        } else {
            Log.w(TAG, "No saved navigation items found in prefs");
            navItems.clear();
        }
    }

    private void loadNavigationItemsFromJson(String json, boolean loadImages) {
        Log.d(TAG, "Loading navigation items from JSON");
        navItems.clear();

        final Map<String, Integer> PAGE_MAP = new HashMap<String, Integer>() {{
            put("NAV_HOME", R.id.nav_home);
            put("NAV_SCAN", R.id.nav_scan);
            put("NAV_PRINTER", R.id.nav_printer);
            put("NAV_SETTINGS", R.id.nav_setting);
        }};

        try {
            JSONArray navItemsArray = new JSONArray(json);
            List<NavItemViewModel> enabledItems = new ArrayList<>();

            for (int i = 0; i < navItemsArray.length(); i++) {
                JSONObject itemJson = navItemsArray.getJSONObject(i);

                // Use your exact existing model structure
                NavItemViewModel item = new NavItemViewModel(
                        itemJson.getString("navName"),
                        parseIconSource(itemJson.opt("icon")),
                        itemJson.optInt("position", 0),
                        itemJson.optBoolean("enabled", true) // Keep enabled status
                );

                // Only add enabled items (matching your working version's behavior)
                if (item.enabled) {
                    enabledItems.add(item);
                    Log.d(TAG, "Loaded item: " + item.name +
                            " | Pos: " + item.position +
                            " | Enabled: " + item.enabled);
                }
            }

            // 2. Sort with position logging (like your working version)
            Collections.sort(enabledItems, (i1, i2) -> {
                Log.v(TAG, "Sorting: " + i1.position + " vs " + i2.position);
                return Integer.compare(i1.position, i2.position);
            });

            // 3. Create ViewModels - optimized page ID handling
            for (int i = 0; i < enabledItems.size(); i++) {
                JSONObject originalJson = navItemsArray.getJSONObject(i);
                NavItemViewModel item = enabledItems.get(i);

                // Directly get page ID from the original JSON
                String pageName = originalJson.optString("navPage");
                int pageId = PAGE_MAP.containsKey(pageName)
                        ? PAGE_MAP.get(pageName)
                        : NAV_HOME;



                navItems.add(new MulberryItemViewModel(
                        this,
                        item.name,
                        item.iconSource,
                        pageId,  // Maintain page structure
//                        null,
                        null
                ));
            }

            Log.d(TAG, "Loaded " + navItems.size() + " items from prefs");
        } catch (Exception e) {
            Log.e(TAG, "Error parsing nav items JSON", e);
        }
    }

    private Object parseIconSource(Object icon) {
        if (icon instanceof String) {
            try {
                // Try to parse as resource ID first
                return Integer.parseInt((String) icon);
            } catch (NumberFormatException e) {
                // If not a number, return as file path string
                return icon;
            }
        }
        return icon; // Return as-is if not string
    }

    // Simple model for navigation items
    private static class NavItemViewModel {
        String name;
        Object iconSource;
        int position;
        boolean enabled;

        NavItemViewModel(String name, Object iconSource, int position, boolean enabled) {
            this.name = name;
            this.iconSource = iconSource;
            this.position = position;
            this.enabled = enabled;
        }
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        Log.d(TAG, "MulberryViewModel cleared - hash: " + this.hashCode());
    }

}