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.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

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.UpdateStatus;

/**
 * Fragment for OTA Update management.
 * Provides UI to check update status, trigger checks, and force CMS/OS updates.
 */
public class OtaUpdateFragment extends BaseFragment {
    private ScrollView mScrollView;
    private Button mBtnRefreshStatus;
    private Button mBtnCheckCms;
    private Button mBtnForceCms;
    private Button mBtnCheckOs;
    private Button mBtnForceOs;
    private TextView mTvCmsStatus;
    private TextView mTvCmsVersion;
    private TextView mTvCmsProgress;
    private TextView mTvOsStatus;
    private TextView mTvOsVersion;
    private TextView mTvOsProgress;
    private TextView mTvForceUpdateResult;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_ota_update, 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_ota);
        mBtnRefreshStatus = view.findViewById(R.id.btn_refresh_status);
        mBtnCheckCms = view.findViewById(R.id.btn_force_cms_update);
        mBtnForceCms = view.findViewById(R.id.btn_force_cms_apply);
        mBtnCheckOs = view.findViewById(R.id.btn_force_device_update);
        mBtnForceOs = view.findViewById(R.id.btn_force_device_apply);
        mTvCmsStatus = view.findViewById(R.id.tv_cms_status);
        mTvCmsVersion = view.findViewById(R.id.tv_cms_version);
        mTvCmsProgress = view.findViewById(R.id.tv_cms_progress);
        mTvOsStatus = view.findViewById(R.id.tv_os_status);
        mTvOsVersion = view.findViewById(R.id.tv_os_version);
        mTvOsProgress = view.findViewById(R.id.tv_os_progress);
        mTvForceUpdateResult = view.findViewById(R.id.tv_force_update_result);

        // Set click listeners
        mBtnRefreshStatus.setOnClickListener(v -> refreshUpdateStatus());
        mBtnCheckCms.setOnClickListener(v -> performCheckCms(false));
        mBtnForceCms.setOnClickListener(v -> confirmForceCms());
        mBtnCheckOs.setOnClickListener(v -> performCheckOs(false));
        mBtnForceOs.setOnClickListener(v -> confirmForceOs());

        setupKeyboardShortcuts(view);
        refreshUpdateStatus();
    }

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

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

    public void triggerRefresh() {
        L.i("OtaUpdateFragment triggerRefresh()");
        showButtonPressEffect(mBtnRefreshStatus);
        refreshUpdateStatus();
    }

    private void refreshUpdateStatus() {
        if (!checkConnection()) return;
        updateLastApiCall("Loading update status...");
        mTvCmsStatus.setText("Status: Loading...");
        mTvOsStatus.setText("Status: Loading...");

        new Thread(() -> {
            UpdateStatus status = mApiClient.getUpdateStatus();
            mHandler.post(() -> {
                if (status.code == HttpStatusCode.OK_200) {
                    mTvCmsStatus.setText("Status: " + status.cmsUpdateStatus
                            + (status.cmsUpdateAvailable ? " (update available)" : " (up to date)"));
                    mTvCmsVersion.setText("Version: " + nvl(status.cmsCurrentVersion)
                            + (status.cmsTargetVersion != null ? " → " + status.cmsTargetVersion : ""));
                    mTvCmsProgress.setText("Progress: " + status.cmsDownloadProgress + "%");

                    mTvOsStatus.setText("Status: " + status.osUpdateStatus
                            + (status.osUpdateAvailable ? " (update available)" : " (up to date)"));
                    mTvOsVersion.setText("Version: " + nvl(status.osCurrentVersion)
                            + (status.osTargetVersion != null ? " → " + status.osTargetVersion : ""));
                    mTvOsProgress.setText("Progress: " + status.osDownloadProgress + "%");

                    updateLastApiCall("Update status refreshed");
                } else {
                    showError("Failed to get update status", status.message);
                    mTvCmsStatus.setText("Status: Error");
                    mTvOsStatus.setText("Status: Error");
                }
            });
        }).start();
    }

    // ---- CMS ----

    private void performCheckCms(boolean forceApply) {
        if (!checkConnection()) return;
        String action = forceApply ? "Force CMS update" : "CMS update check";
        updateLastApiCall(action + "...");
        mTvForceUpdateResult.setText(action + "...");

        new Thread(() -> {
            ApiResponse response = mApiClient.checkCmsUpdate(forceApply);
            mHandler.post(() -> {
                mTvForceUpdateResult.setText(formatResponse("CMS", response));
                if (response.code == HttpStatusCode.OK_200) {
                    Toast.makeText(getContext(), action + " initiated", Toast.LENGTH_SHORT).show();
                    updateLastApiCall(action + " initiated");
                    mHandler.postDelayed(this::refreshUpdateStatus, 2000);
                } else {
                    showError(action, response.message);
                }
            });
        }).start();
    }

    private void confirmForceCms() {
        if (!checkConnection()) return;
        new AlertDialog.Builder(getContext())
                .setTitle("Force CMS Update")
                .setMessage("This will check for new CMS update, download and install immediately, bypassing normal time window.\n\nProceed?")
                .setPositiveButton("Force Update", (d, w) -> performCheckCms(true))
                .setNegativeButton("Cancel", null)
                .show();
    }

    // ---- OS ----

    private void performCheckOs(boolean forceApply) {
        if (!checkConnection()) return;
        String action = forceApply ? "Force OS update" : "OS update check";
        updateLastApiCall(action + "...");
        mTvForceUpdateResult.setText(action + "...");

        new Thread(() -> {
            ApiResponse response = mApiClient.checkOsUpdate(forceApply);
            mHandler.post(() -> {
                mTvForceUpdateResult.setText(formatResponse("OS", response));
                if (response.code == HttpStatusCode.OK_200) {
                    Toast.makeText(getContext(), action + " initiated", Toast.LENGTH_SHORT).show();
                    updateLastApiCall(action + " initiated");
                    mHandler.postDelayed(this::refreshUpdateStatus, 2000);
                } else {
                    showError(action, response.message);
                }
            });
        }).start();
    }

    private void confirmForceOs() {
        if (!checkConnection()) return;
        new AlertDialog.Builder(getContext())
                .setTitle("Force OS Update")
                .setMessage("This will check for new OS update, download and install immediately.\n\nWARNING: Device will REBOOT after installation.\n\nProceed?")
                .setPositiveButton("Force Update & Reboot", (d, w) -> performCheckOs(true))
                .setNegativeButton("Cancel", null)
                .show();
    }

    // ---- Helpers ----

    private String formatResponse(String type, ApiResponse response) {
        switch (response.code) {
        case HttpStatusCode.OK_200:
            return type + ": " + response.message;
        case 409:
            return type + ": Update already in progress";
        case HttpStatusCode.SERVICE_UNAVAILABLE_503:
            return type + ": Device not ready";
        default:
            return type + " failed (code " + response.code + "): " + response.message;
        }
    }

    private String nvl(String value) {
        return value != null ? value : "--";
    }
}
