package com.amazon.ads.apidemo.fragments;

import android.app.AlertDialog;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.ArrayAdapter;
import android.widget.Toast;

import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.amazon.ads.apidemo.HttpStatusCode;
import com.amazon.ads.apidemo.R;
import com.amazon.ads.apidemo.utils.L;
import com.amazon.ads.ema.api.model.ApiResponse;
import com.amazon.ads.ema.api.model.CacheClearOptions;
import com.amazon.ads.ema.api.model.CacheClearResult;


/**
 * Fragment for system control operations (power, reboot, factory reset, cache)
 */
public class SystemControlFragment extends BaseFragment {
    private EditText mEtRebootReason;
    private ScrollView mScrollView;
    private Button mBtnReboot;
    private Button mBtnFactoryReset;
    private Button mBtnClearCache;
    private Button mBtnRebootCms;
    private CheckBox mCbSystemCache;
    private CheckBox mCbAppCache;
    private Spinner mSpinnerRotation;
    private Button mBtnSetRotation;
    private TextView mTvCurrentRotation;

    private static final String[] ROTATION_OPTIONS = {"landscape", "portrait", "reverse_landscape", "reverse_portrait"};
    private static final String[] ROTATION_LABELS = {"Landscape (0°)", "Portrait (90°)", "Reverse Landscape (180°)", "Reverse Portrait (270°)"};

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_system_control, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        initializeBase();

        // Initialize views
        mScrollView = view.findViewById(R.id.scroll_view_system_control);
        mBtnReboot = view.findViewById(R.id.btn_reboot);
        mBtnFactoryReset = view.findViewById(R.id.btn_factory_reset);
        mBtnClearCache = view.findViewById(R.id.btn_clear_cache);
        mBtnRebootCms = view.findViewById(R.id.btn_reboot_cms);

        mEtRebootReason = view.findViewById(R.id.et_reboot_reason);
        mCbSystemCache = view.findViewById(R.id.cb_system_cache);
        mCbAppCache = view.findViewById(R.id.cb_app_cache);

        // Set click listeners
        mBtnReboot.setOnClickListener(v -> confirmAndReboot());
        mBtnFactoryReset.setOnClickListener(v -> confirmAndFactoryReset());
        mBtnClearCache.setOnClickListener(v -> confirmAndClearCache());
        mBtnRebootCms.setOnClickListener(v -> confirmAndRebootCms());

        // Screen rotation
        mSpinnerRotation = view.findViewById(R.id.spinner_rotation);
        mBtnSetRotation = view.findViewById(R.id.btn_set_rotation);
        mTvCurrentRotation = view.findViewById(R.id.tv_current_rotation);

        ArrayAdapter<String> rotationAdapter = new ArrayAdapter<>(requireContext(),
                android.R.layout.simple_spinner_item, ROTATION_LABELS);
        rotationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mSpinnerRotation.setAdapter(rotationAdapter);

        // Restore focus to Set Rotation button after spinner selection
        mSpinnerRotation.setOnItemSelectedListener(new android.widget.AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(android.widget.AdapterView<?> parent, View v, int position, long id) {
                mBtnSetRotation.requestFocus();
            }
            @Override
            public void onNothingSelected(android.widget.AdapterView<?> parent) {}
        });

        mBtnSetRotation.setOnClickListener(v -> performSetRotation());

        // Load current rotation
        refreshRotation();

        // Setup keyboard shortcuts
        setupKeyboardShortcuts(view);
    }

    @Override
    public void onResume() {
        super.onResume();
        if (getView() != null) {
            getView().requestFocus();
        }
    }

    private void setupKeyboardShortcuts(View view) {
        if (mScrollView != null) {
            mScrollView.setFocusable(true);
            mScrollView.setFocusableInTouchMode(true);
            mScrollView.setOnKeyListener((v, keyCode, event) -> {
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    switch (keyCode) {
                    case KeyEvent.KEYCODE_DPAD_UP:
                        mScrollView.smoothScrollBy(0, -200);
                        return true;
                    case KeyEvent.KEYCODE_DPAD_DOWN:
                        mScrollView.smoothScrollBy(0, 200);
                        return true;
                    }
                }
                return false;
            });
        }
    }


    /**
     * Public methods to trigger actions from MainActivity
     */
    public void triggerReboot() {
        L.i("SystemControlFragment triggerReboot() called from MainActivity");
        showButtonPressEffect(mBtnReboot);
        confirmAndReboot();
    }

    public void triggerFactoryReset() {
        L.i("SystemControlFragment triggerFactoryReset() called from MainActivity");
        showButtonPressEffect(mBtnFactoryReset);
        confirmAndFactoryReset();
    }

    public void triggerClearCache() {
        L.i("SystemControlFragment triggerClearCache() called from MainActivity");
        showButtonPressEffect(mBtnClearCache);
        confirmAndClearCache();
    }

    private void confirmAndReboot() {
        if (!checkConnection())
            return;

        new AlertDialog.Builder(getContext()).setTitle("Confirm Reboot").setMessage("Are you sure you want to reboot the device?")
                .setPositiveButton("Reboot", (dialog, which) -> {
                    String reason = mEtRebootReason.getText().toString().trim();
                    if (reason.isEmpty()) {
                        reason = "User initiated from Partner API Demo";
                    }
                    performReboot(reason);
                }).setNegativeButton("Cancel", null).show();
    }

    private void performReboot(String reason) {
        updateLastApiCall("Rebooting device...");

        new Thread(() -> {
            ApiResponse response = mApiClient.rebootDevice(30); // 30 second delay
            mHandler.post(() -> {
                if (response.code == HttpStatusCode.OK_200) {
                    Toast.makeText(getContext(), "Reboot initiated. Device will restart soon.", Toast.LENGTH_LONG).show();
                    updateLastApiCall("Reboot initiated");
                } else {
                    showError("Reboot failed", response.message);
                }
            });
        }).start();
    }

    private void confirmAndFactoryReset() {
        if (!checkConnection())
            return;

        // Default to not wiping external storage as per requirement
        String message = "This will erase all data on the device!\n\n" + "External storage will be preserved.\n\n" + "Are you absolutely sure?";

        new AlertDialog.Builder(getContext()).setTitle("⚠️ Confirm Factory Reset").setMessage(message)
                .setPositiveButton("Factory Reset", (dialog, which) -> {
                    // Second confirmation
                    new AlertDialog.Builder(getContext()).setTitle("⚠️ Final Confirmation")
                            .setMessage("This action cannot be undone. Proceed with factory reset?")
                            .setPositiveButton("Yes, Factory Reset", (d, w) -> performFactoryReset(false)).setNegativeButton("Cancel", null).show();
                }).setNegativeButton("Cancel", null).show();
    }

    private void performFactoryReset(boolean wipeExternal) {
        updateLastApiCall("Performing factory reset...");

        new Thread(() -> {
            ApiResponse response = mApiClient.factoryResetDevice(wipeExternal);
            mHandler.post(() -> {
                if (response.code == HttpStatusCode.OK_200) {
                    Toast.makeText(getContext(), "Factory reset initiated. Device will be wiped.", Toast.LENGTH_LONG).show();
                    updateLastApiCall("Factory reset initiated");
                } else {
                    showError("Factory reset failed", response.message);
                }
            });
        }).start();
    }

    private void confirmAndClearCache() {
        if (!checkConnection())
            return;

        boolean systemCache = mCbSystemCache.isChecked();
        boolean appCache = mCbAppCache.isChecked();

        String message = "Clear cache?\n\n";
        if (systemCache) {
            message += "• System cache\n";
        }
        if (appCache) {
            message += "• All app caches\n";
        }
        if (!systemCache && !appCache) {
            message += "• Demo app cache only\n";
        }

        new AlertDialog.Builder(getContext()).setTitle("Confirm Clear Cache").setMessage(message)
                .setPositiveButton("Clear", (dialog, which) -> performClearCache()).setNegativeButton("Cancel", null).show();
    }

    private void performClearCache() {
        updateLastApiCall("Clearing cache...");

        new Thread(() -> {
            CacheClearOptions options = new CacheClearOptions();
            options.systemCache = mCbSystemCache.isChecked();
            options.appCache = mCbAppCache.isChecked();

            // If appCache is selected, set packageNames to empty list (clears all apps)
            // If appCache is not selected, set packageNames to demo app's package name only
            // This ensures demo app cache is always cleared when no options are selected
            if (options.appCache) {
                options.packageNames = new String[0]; // Empty list means all apps
            } else {
                // Always use the demo app's package name when appCache is not selected
                options.packageNames = new String[]{getContext().getPackageName()};
            }

            CacheClearResult response = mApiClient.clearCache(options);
            mHandler.post(() -> {
                if (response.code == HttpStatusCode.OK_200) {
                    String resultMsg = "Cache cleared successfully";
                    if (response.data != null) {
                        if (response.data.systemCacheFreedMB > 0) {
                            resultMsg += "\n• System cache: " + response.data.systemCacheFreedMB + " MB freed";
                        }
                        if (response.data.appCacheFreedMB > 0) {
                            resultMsg += "\n• App cache: " + response.data.appCacheFreedMB + " MB freed";
                        }
                        if (response.data.appsProcessed > 0) {
                            resultMsg += "\n• Apps processed: " + response.data.appsProcessed;
                        }
                        if (response.data.totalFreedMB > 0) {
                            resultMsg += "\n• Total: " + response.data.totalFreedMB + " MB freed";
                        }
                    }
                    Toast.makeText(getContext(), resultMsg, Toast.LENGTH_LONG).show();
                    updateLastApiCall("Cache cleared");
                } else {
                    showError("Clear cache failed", response.message);
                }
            });
        }).start();
    }

    private void confirmAndRebootCms() {
        if (!checkConnection()) return;

        new AlertDialog.Builder(getContext())
                .setTitle("Reboot CMS App")
                .setMessage("This will force-stop and relaunch this application.\n\nProceed?")
                .setPositiveButton("Restart", (d, w) -> performRebootCms())
                .setNegativeButton("Cancel", null)
                .show();
    }

    private void performRebootCms() {
        updateLastApiCall("Rebooting CMS app...");

        new Thread(() -> {
            ApiResponse response = mApiClient.restartCms();
            mHandler.post(() -> {
                if (response.code == HttpStatusCode.OK_200) {
                    Toast.makeText(getContext(), "CMS app reboot initiated", Toast.LENGTH_SHORT).show();
                    updateLastApiCall("CMS app reboot initiated");
                } else {
                    showError("Reboot CMS failed", response.message);
                }
            });
        }).start();
    }

    private void refreshRotation() {
        if (!checkConnection()) return;

        new Thread(() -> {
            ApiResponse response = mApiClient.getScreenRotation();
            mHandler.post(() -> {
                if (response.code == HttpStatusCode.OK_200 && response.data != null) {
                    String rotation = (String) response.data.get("rotation");
                    String degrees = (String) response.data.get("degrees");
                    mTvCurrentRotation.setText("Current: " + rotation + " (" + degrees + "°)");
                    // Select matching spinner item
                    for (int i = 0; i < ROTATION_OPTIONS.length; i++) {
                        if (ROTATION_OPTIONS[i].equals(rotation)) {
                            mSpinnerRotation.setSelection(i);
                            break;
                        }
                    }
                } else {
                    mTvCurrentRotation.setText("Current: unknown");
                }
            });
        }).start();
    }

    private void performSetRotation() {
        if (!checkConnection()) return;

        int selected = mSpinnerRotation.getSelectedItemPosition();
        if (selected < 0 || selected >= ROTATION_OPTIONS.length) return;

        String rotation = ROTATION_OPTIONS[selected];
        updateLastApiCall("Setting rotation to " + rotation + "...");

        new Thread(() -> {
            ApiResponse response = mApiClient.setScreenRotation(rotation);
            mHandler.post(() -> {
                if (response.code == HttpStatusCode.OK_200) {
                    Toast.makeText(getContext(), "Rotation set to " + rotation, Toast.LENGTH_SHORT).show();
                    updateLastApiCall("Rotation set to " + rotation);
                    refreshRotation();
                } else {
                    showError("Set rotation failed", response.message);
                }
            });
        }).start();
    }
}
