package com.amazon.ads.apidemo.api;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;

import com.amazon.ads.apidemo.HttpStatusCode;
import com.amazon.ads.apidemo.utils.L;
import com.amazon.ads.ema.api.IDeviceManagement;
import com.amazon.ads.ema.api.model.ApiResponse;
import com.amazon.ads.ema.api.model.CacheClearOptions;
import com.amazon.ads.ema.api.model.CacheClearResult;
import com.amazon.ads.ema.api.model.DeviceInfo;
import com.amazon.ads.ema.api.model.HdmiStatus;
import com.amazon.ads.ema.api.model.NetworkStatus;
import com.amazon.ads.ema.api.model.ScreenRecordChunk;
import com.amazon.ads.ema.api.model.ScreenRecordConfig;
import com.amazon.ads.ema.api.model.ScreenRecordStatus;
import com.amazon.ads.ema.api.model.ScreenshotResult;
import com.amazon.ads.ema.api.model.ScreenshotChunk;
import com.amazon.ads.ema.api.model.SystemResources;
import com.amazon.ads.ema.api.model.TimezoneListResult;
import com.amazon.ads.ema.api.model.UpdateStatus;
import com.amazon.ads.ema.api.model.WifiConfig;

/**
 * Remote API Client for managing connection to Remote Management Service.
 * Provides simplified access to all device management APIs.
 */
public class RemoteApiClient {
    // Service details for binding
    private static final String REMOTE_API_SERVICE_PACKAGE = "com.amazon.ads.ema.sys";
    private static final String REMOTE_API_SERVICE_CLASS = "com.amazon.ads.ema.service.DeviceManagementService";

    private final Context mContext;
    private IDeviceManagement mService;
    private boolean mBound = false;
    private ConnectionListener mConnectionListener;
    private final ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            L.i("Service connected: " + name);
            mService = IDeviceManagement.Stub.asInterface(service);
            mBound = true;

            if (mConnectionListener != null) {
                mConnectionListener.onConnected();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            L.w("Service disconnected: " + name);
            mService = null;
            mBound = false;

            if (mConnectionListener != null) {
                mConnectionListener.onDisconnected();
            }
        }
    };

    public interface ConnectionListener {
        void onConnected();

        void onDisconnected();

        void onConnectionFailed(String error);
    }

    /**
     * Check the health of the connection by attempting a lightweight API call
     *
     * @return true if connection is healthy, false otherwise
     */
    public boolean checkConnectionHealth() {
        if (!isConnected()) {
            L.w("Health check failed: Not connected");
            return false;
        }

        try {
            // Use a lightweight API call to verify connection health
            String version = mService.getApiVersion();
            boolean healthy = version != null && !version.isEmpty();
            if (healthy) {
                L.i("Health check passed: API version=" + version);
            } else {
                L.w("Health check failed: Invalid API version response");
            }
            return healthy;
        } catch (RemoteException e) {
            L.e("Health check failed: RemoteException", e);
            return false;
        } catch (Exception e) {
            L.e("Health check failed: Unexpected exception", e);
            return false;
        }
    }

    public RemoteApiClient(Context context) {
        mContext = context.getApplicationContext();
    }

    /**
     * Connect to the Partner API service
     */
    public void connect(ConnectionListener listener) {
        mConnectionListener = listener;

        if (mBound) {
            L.w("Already connected");
            if (listener != null) {
                listener.onConnected();
            }
            return;
        }

        try {
            Intent intent = new Intent();
            intent.setClassName(REMOTE_API_SERVICE_PACKAGE, REMOTE_API_SERVICE_CLASS);

            boolean result = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
            if (!result) {
                L.e("Failed to bind to service");
                if (listener != null) {
                    listener.onConnectionFailed("Failed to bind to Partner API service");
                }
            }
        } catch (Exception e) {
            L.e("Error connecting to service", e);
            if (listener != null) {
                listener.onConnectionFailed("Error: " + e.getMessage());
            }
        }
    }

    /**
     * Disconnect from the Partner API service
     */
    public void disconnect() {
        if (mBound) {
            try {
                mContext.unbindService(mServiceConnection);
            } catch (Exception e) {
                L.e("Error unbinding service", e);
            }
            mBound = false;
            mService = null;
        }
    }

    /**
     * Check if connected to the service
     */
    public boolean isConnected() {
        return mBound && mService != null;
    }

    // ============== Device Information APIs ==============

    public DeviceInfo getDeviceInfo() {
        L.i("[API Request] getDeviceInfo()");

        if (!isConnected()) {
            DeviceInfo response = new DeviceInfo();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] getDeviceInfo() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            DeviceInfo response = mService.getDeviceInfo();
            L.i("[API Response] getDeviceInfo() - Code:", response.code, "Message:", response.message, "Data:", response.data);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in getDeviceInfo", e);
            DeviceInfo response = new DeviceInfo();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] getDeviceInfo() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public SystemResources getSystemResources() {
        L.i("[API Request] getSystemResources()");

        if (!isConnected()) {
            SystemResources response = new SystemResources();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] getSystemResources() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            SystemResources response = mService.getSystemResources();
            L.i("[API Response] getSystemResources() - Code:", response.code, "Message:", response.message, "Data:", response.data);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in getSystemResources", e);
            SystemResources response = new SystemResources();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] getSystemResources() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public NetworkStatus getNetworkStatus() {
        L.i("[API Request] getNetworkStatus()");

        if (!isConnected()) {
            NetworkStatus response = new NetworkStatus();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] getNetworkStatus() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            NetworkStatus response = mService.getNetworkStatus();
            L.i("[API Response] getNetworkStatus() - Code:", response.code, "Message:", response.message, "Data:", response.data);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in getNetworkStatus", e);
            NetworkStatus response = new NetworkStatus();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] getNetworkStatus() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public HdmiStatus getHdmiStatus() {
        L.i("[API Request] getHdmiStatus()");

        if (!isConnected()) {
            HdmiStatus response = new HdmiStatus();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] getHdmiStatus() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            HdmiStatus response = mService.getHdmiStatus();
            L.i("[API Response] getHdmiStatus() - Code:", response.code, "Message:", response.message, "Data:", response.data);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in getHdmiStatus", e);
            HdmiStatus response = new HdmiStatus();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] getHdmiStatus() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ApiResponse refreshHdmiStatus() {
        L.i("[API Request] refreshHdmiStatus()");

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] refreshHdmiStatus() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.refreshHdmiStatus();
            L.i("[API Response] refreshHdmiStatus() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in refreshHdmiStatus", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] refreshHdmiStatus() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    // ============== Device Control APIs ==============

    public ApiResponse rebootDevice(int delaySeconds) {
        L.i("[API Request] rebootDevice() - delaySeconds:", delaySeconds);

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] rebootDevice() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.rebootDevice(delaySeconds);
            L.i("[API Response] rebootDevice() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in rebootDevice", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] rebootDevice() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ApiResponse factoryResetDevice(boolean wipeExternalStorage) {
        L.i("[API Request] factoryResetDevice() - wipeExternalStorage:", wipeExternalStorage);

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] factoryResetDevice() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.factoryResetDevice(wipeExternalStorage);
            L.i("[API Response] factoryResetDevice() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in factoryResetDevice", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] factoryResetDevice() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ApiResponse wakeScreen() {
        L.i("[API Request] wakeScreen()");

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] wakeScreen() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.wakeScreen();
            L.i("[API Response] wakeScreen() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in wakeScreen", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] wakeScreen() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    // ============== HDMI CEC Control APIs ==============

    public ApiResponse toggleDisplayPower() {
        L.i("[API Request] toggleDisplayPower()");

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] toggleDisplayPower() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.toggleDisplayPower();
            L.i("[API Response] toggleDisplayPower() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in toggleDisplayPower", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] toggleDisplayPower() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ApiResponse setDisplayPower(boolean powerOn) {
        L.i("[API Request] setDisplayPower() - powerOn:", powerOn);

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] setDisplayPower() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.setDisplayPower(powerOn);
            L.i("[API Response] setDisplayPower() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in setDisplayPower", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] setDisplayPower() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ApiResponse adjustVolume(boolean volumeUp) {
        L.i("[API Request] adjustVolume() - volumeUp:", volumeUp);

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] adjustVolume() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.adjustVolume(volumeUp);
            L.i("[API Response] adjustVolume() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in adjustVolume", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] adjustVolume() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ApiResponse toggleMute() {
        L.i("[API Request] toggleMute()");

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] toggleMute() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.toggleMute();
            L.i("[API Response] toggleMute() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in toggleMute", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] toggleMute() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ApiResponse setVolumeLevel(int level) {
        L.i("[API Request] setVolumeLevel() - level:", level);

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] setVolumeLevel() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.setVolumeLevel(level);
            L.i("[API Response] setVolumeLevel() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in setVolumeLevel", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] setVolumeLevel() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    // ============== Screen Capture API ==============

    public ScreenshotResult captureScreen(String format, int quality) {
        L.i("[API Request] captureScreen() - format:", format, "quality:", quality);

        if (!isConnected()) {
            ScreenshotResult response = new ScreenshotResult();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] captureScreen() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ScreenshotResult response = mService.captureScreen(format, quality);
            // Log response without binary data
            if (response.data != null) {
                L.i("[API Response] captureScreen() - Code:", response.code, "Message:", response.message, "Width:", response.data.widthPx, "Height:",
                        response.data.heightPx, "Format:", response.data.format, "DataSize:",
                        (response.data.imageData != null ? response.data.imageData.length + " bytes" : "null"));
            } else {
                L.i("[API Response] captureScreen() - Code:", response.code, "Message:", response.message, "Data: null");
            }
            return response;
        } catch (android.os.TransactionTooLargeException e) {
            L.e("BINDER LIMIT EXCEEDED in captureScreen - The screenshot data exceeds Android's ~1MB Binder transaction limit."
                    + " Format=" + format + " Quality=" + quality
                    + ". Use JPEG/WEBP with lower quality, or use captureScreenScaled() with maxWidth to reduce size.", e);
            ScreenshotResult response = new ScreenshotResult();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Screenshot too large for Binder transfer (~1MB limit). Use JPEG/WEBP, lower quality, or maxWidth scaling.";
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in captureScreen", e);
            ScreenshotResult response = new ScreenshotResult();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] captureScreen() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    // ============== Enhanced Screen Capture API ==============

    public ScreenshotResult captureScreenScaled(String format, int quality, int maxWidth) {
        L.i("[API Request] captureScreenScaled() - format:", format, "quality:", quality, "maxWidth:", maxWidth);

        if (!isConnected()) {
            ScreenshotResult response = new ScreenshotResult();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] captureScreenScaled() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ScreenshotResult response = mService.captureScreenScaled(format, quality, maxWidth);
            if (response.data != null) {
                L.i("[API Response] captureScreenScaled() - Code:", response.code, "Message:", response.message, "Width:", response.data.widthPx, "Height:",
                        response.data.heightPx, "Format:", response.data.format, "DataSize:",
                        (response.data.imageData != null ? response.data.imageData.length + " bytes" : "null"));
            } else {
                L.i("[API Response] captureScreenScaled() - Code:", response.code, "Message:", response.message, "Data: null");
            }
            return response;
        } catch (android.os.TransactionTooLargeException e) {
            L.e("BINDER LIMIT EXCEEDED in captureScreenScaled - The screenshot data exceeds Android's ~1MB Binder transaction limit."
                    + " Format=" + format + " Quality=" + quality + " MaxWidth=" + maxWidth
                    + ". Try lower quality or smaller maxWidth value.", e);
            ScreenshotResult response = new ScreenshotResult();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Screenshot too large for Binder transfer (~1MB limit). Try lower quality or smaller maxWidth.";
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in captureScreenScaled", e);
            ScreenshotResult response = new ScreenshotResult();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] captureScreenScaled() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    // ============== Screen Recording API ==============

    public ScreenRecordStatus startScreenRecord(ScreenRecordConfig config) {
        L.i("[API Request] startScreenRecord() - duration:", config.durationSeconds, "resolution:", config.resolution, "bitrate:",
                config.bitrateMbps);

        if (!isConnected()) {
            ScreenRecordStatus response = new ScreenRecordStatus();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] startScreenRecord() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ScreenRecordStatus response = mService.startScreenRecord(config);
            L.i("[API Response] startScreenRecord() - Code:", response.code, "Message:", response.message, "State:", response.state, "Progress:",
                    response.progressPercent + "%");
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in startScreenRecord", e);
            ScreenRecordStatus response = new ScreenRecordStatus();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] startScreenRecord() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ScreenRecordStatus getScreenRecordStatus() {
        L.i("[API Request] getScreenRecordStatus()");

        if (!isConnected()) {
            ScreenRecordStatus response = new ScreenRecordStatus();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] getScreenRecordStatus() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ScreenRecordStatus response = mService.getScreenRecordStatus();
            L.i("[API Response] getScreenRecordStatus() - Code:", response.code, "State:", response.state, "Progress:",
                    response.progressPercent + "%", "Size:", response.fileSizeBytes + " bytes");
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in getScreenRecordStatus", e);
            ScreenRecordStatus response = new ScreenRecordStatus();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] getScreenRecordStatus() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ScreenRecordChunk getScreenRecordChunk(long offset) {
        L.i("[API Request] getScreenRecordChunk() - offset:", offset);

        if (!isConnected()) {
            ScreenRecordChunk response = new ScreenRecordChunk();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] getScreenRecordChunk() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ScreenRecordChunk response = mService.getScreenRecordChunk(offset);
            L.i("[API Response] getScreenRecordChunk() - Code:", response.code, "ChunkSize:", response.chunkSize, "TotalSize:", response.totalSize,
                    "IsLast:", response.isLastChunk);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in getScreenRecordChunk", e);
            ScreenRecordChunk response = new ScreenRecordChunk();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] getScreenRecordChunk() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ApiResponse clearScreenRecord() {
        L.i("[API Request] clearScreenRecord()");

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] clearScreenRecord() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.clearScreenRecord();
            L.i("[API Response] clearScreenRecord() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in clearScreenRecord", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] clearScreenRecord() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    // ============== Network Configuration API ==============

    public ApiResponse configureWifi(WifiConfig config) {
        // Log config details without password
        L.i("[API Request] configureWifi() - SSID:", config != null ? config.ssid : "null", "SecurityType:",
                config != null ? config.securityType : "null", "Hidden:", config != null ? config.hidden : "null", "Priority:",
                config != null ? config.priority : "null");

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] configureWifi() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.configureWifi(config);
            L.i("[API Response] configureWifi() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in configureWifi", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] configureWifi() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    // ============== Maintenance APIs ==============

    public CacheClearResult clearCache(CacheClearOptions options) {
        L.i("[API Request] clearCache() - Options:", options);

        if (!isConnected()) {
            CacheClearResult response = new CacheClearResult();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] clearCache() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            CacheClearResult response = mService.clearCache(options);
            L.i("[API Response] clearCache() - Code:", response.code, "Message:", response.message, "Data:", response.data);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in clearCache", e);
            CacheClearResult response = new CacheClearResult();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] clearCache() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    // ============== Utility APIs ==============

    public String getApiVersion() {
        L.i("[API Request] getApiVersion()");

        if (!isConnected()) {
            String result = "N/A - Service not connected";
            L.w("[API Response] getApiVersion() - Result:", result);
            return result;
        }

        try {
            String version = mService.getApiVersion();
            L.i("[API Response] getApiVersion() - Version:", version);
            return version;
        } catch (RemoteException e) {
            L.e("RemoteException in getApiVersion", e);
            String result = "N/A - Remote exception";
            L.e("[API Response] getApiVersion() - Result:", result);
            return result;
        }
    }

    public boolean isFeatureSupported(String feature) {
        L.i("[API Request] isFeatureSupported() - feature:", feature);

        if (!isConnected()) {
            L.w("[API Response] isFeatureSupported() - Result: false (Service not connected)");
            return false;
        }

        try {
            boolean supported = mService.isFeatureSupported(feature);
            L.i("[API Response] isFeatureSupported() - Feature:", feature, "Supported:", supported);
            return supported;
        } catch (RemoteException e) {
            L.e("RemoteException in isFeatureSupported", e);
            L.e("[API Response] isFeatureSupported() - Result: false (Remote exception)");
            return false;
        }
    }

    // ============== Timezone Configuration APIs ==============

    public TimezoneListResult getTimezoneList() {
        L.i("[API Request] getTimezoneList()");

        if (!isConnected()) {
            TimezoneListResult response = new TimezoneListResult();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] getTimezoneList() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            TimezoneListResult response = mService.getTimezoneList();
            L.i("[API Response] getTimezoneList() - Code:", response.code, "Message:", response.message, "Current:", response.currentTimezoneId,
                    "Count:", (response.timezones != null ? response.timezones.size() : 0));
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in getTimezoneList", e);
            TimezoneListResult response = new TimezoneListResult();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] getTimezoneList() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ApiResponse setTimezone(String timezoneId) {
        L.i("[API Request] setTimezone() - timezoneId:", timezoneId);

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] setTimezone() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.setTimezone(timezoneId);
            L.i("[API Response] setTimezone() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in setTimezone", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] setTimezone() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    // ============== OTA Update APIs ==============

    public UpdateStatus getUpdateStatus() {
        L.i("[API Request] getUpdateStatus()");

        if (!isConnected()) {
            UpdateStatus response = new UpdateStatus();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] getUpdateStatus() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            UpdateStatus response = mService.getUpdateStatus();
            L.i("[API Response] getUpdateStatus() - Code:", response.code, "Message:", response.message,
                    "CMS:", response.cmsUpdateStatus, "OS:", response.osUpdateStatus);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in getUpdateStatus", e);
            UpdateStatus response = new UpdateStatus();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] getUpdateStatus() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ApiResponse checkCmsUpdate(boolean forceApply) {
        L.i("[API Request] checkCmsUpdate() - forceApply:", forceApply);

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] checkCmsUpdate() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.checkCmsUpdate(forceApply);
            L.i("[API Response] checkCmsUpdate() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in checkCmsUpdate", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] checkCmsUpdate() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ApiResponse checkOsUpdate(boolean forceApply) {
        L.i("[API Request] checkOsUpdate() - forceApply:", forceApply);

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] checkOsUpdate() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.checkOsUpdate(forceApply);
            L.i("[API Response] checkOsUpdate() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in checkOsUpdate", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] checkOsUpdate() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    // ============== Screen Rotation APIs ==============

    public ApiResponse getScreenRotation() {
        L.i("[API Request] getScreenRotation()");

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] getScreenRotation() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.getScreenRotation();
            L.i("[API Response] getScreenRotation() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in getScreenRotation", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] getScreenRotation() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ApiResponse setScreenRotation(String rotation) {
        L.i("[API Request] setScreenRotation() - rotation:", rotation);

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] setScreenRotation() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.setScreenRotation(rotation);
            L.i("[API Response] setScreenRotation() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in setScreenRotation", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] setScreenRotation() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    // ============== CMS App Control APIs ==============

    public ApiResponse restartCms() {
        L.i("[API Request] restartCms()");

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            L.w("[API Response] restartCms() - Code:", response.code, "Message:", response.message);
            return response;
        }

        try {
            ApiResponse response = mService.restartCms();
            L.i("[API Response] restartCms() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in restartCms", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            L.e("[API Response] restartCms() - Code:", response.code, "Message:", response.message);
            return response;
        }
    }

    public ScreenshotChunk getScreenshotChunk(long offset) {
        L.i("[API Request] getScreenshotChunk() - offset:", offset);

        if (!isConnected()) {
            ScreenshotChunk chunk = new ScreenshotChunk();
            chunk.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            chunk.message = "Service not connected";
            return chunk;
        }

        try {
            ScreenshotChunk chunk = mService.getScreenshotChunk(offset);
            L.i("[API Response] getScreenshotChunk() - Code:", chunk.code,
                    "chunkSize:", chunk.chunkSize, "totalSize:", chunk.totalSize,
                    "isLast:", chunk.isLastChunk);
            return chunk;
        } catch (RemoteException e) {
            L.e("RemoteException in getScreenshotChunk", e);
            ScreenshotChunk chunk = new ScreenshotChunk();
            chunk.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            chunk.message = "Remote exception: " + e.getMessage();
            return chunk;
        }
    }

    public ApiResponse clearScreenshot() {
        L.i("[API Request] clearScreenshot()");

        if (!isConnected()) {
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.SERVICE_UNAVAILABLE_503;
            response.message = "Service not connected";
            return response;
        }

        try {
            ApiResponse response = mService.clearScreenshot();
            L.i("[API Response] clearScreenshot() - Code:", response.code, "Message:", response.message);
            return response;
        } catch (RemoteException e) {
            L.e("RemoteException in clearScreenshot", e);
            ApiResponse response = new ApiResponse();
            response.code = HttpStatusCode.INTERNAL_SERVER_ERROR_500;
            response.message = "Remote exception: " + e.getMessage();
            return response;
        }
    }
}
