package com.foxx.androidcast.dev;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.foxx.androidcast.INetworkChangeListener;
import com.foxx.androidcast.INetworkSelfTestService;
import com.foxx.androidcast.NetworkConditions;
import com.foxx.androidcast.R;
import com.foxx.androidcast.network.selftest.NetworkSelfTestService;

/** Developer network self-test panel driven by standalone AIDL service cache. */
public final class DevNetworkSelfTestController {
    private final AppCompatActivity activity;
    private final View panel;
    private final TextView report;
    private final ProgressBar spinner;
    private final Handler main = new Handler(Looper.getMainLooper());
    private INetworkSelfTestService service;
    private boolean bound;

    private final INetworkChangeListener listener = new INetworkChangeListener.Stub() {
        @Override
        public void onNetworkConditionChange(NetworkConditions aidlNetworkConditions) {
            if (aidlNetworkConditions == null) {
                return;
            }
            main.post(() -> {
                spinner.setVisibility(View.GONE);
                report.setText(render(aidlNetworkConditions));
            });
        }
    };

    private final Runnable refreshPoll = new Runnable() {
        @Override
        public void run() {
            INetworkSelfTestService s = service;
            if (s == null) {
                spinner.setVisibility(View.GONE);
                return;
            }
            try {
                if (s.isRefreshing()) {
                    main.postDelayed(this, 700);
                    return;
                }
                NetworkConditions cached = s.getCachedConditions();
                spinner.setVisibility(View.GONE);
                if (cached != null && cached.reportText != null && !cached.reportText.isEmpty()) {
                    report.setText(render(cached));
                } else {
                    report.setText(activity.getString(R.string.dev_network_selftest_pending));
                }
            } catch (RemoteException e) {
                spinner.setVisibility(View.GONE);
                report.setText("Self-test service error: " + e.getMessage());
            }
        }
    };

    private final ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            service = INetworkSelfTestService.Stub.asInterface(binder);
            try {
                service.addListener(listener);
                loadCachedOrRequest();
            } catch (RemoteException e) {
                report.setText("Self-test bind failed: " + e.getMessage());
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            service = null;
            bound = false;
        }
    };

    public DevNetworkSelfTestController(AppCompatActivity activity) {
        this.activity = activity;
        this.panel = activity.findViewById(R.id.dev_panel_network_selftest);
        this.report = panel.findViewById(R.id.text_dev_network_selftest_report);
        this.spinner = panel.findViewById(R.id.progress_dev_network_selftest);
        Button run = panel.findViewById(R.id.btn_dev_network_selftest_force);
        run.setOnClickListener(v -> requestForceRefresh());
    }

    public void onSelfTestTabShown() {
        if (report.length() == 0) {
            report.setText(activity.getString(R.string.dev_network_selftest_pending));
        }
        ensureBound();
        loadCachedOrRequest();
    }

    public void onDestroy() {
        main.removeCallbacks(refreshPoll);
        if (service != null) {
            try {
                service.removeListener(listener);
            } catch (RemoteException ignored) {
            }
        }
        if (bound) {
            try {
                activity.unbindService(connection);
            } catch (Exception ignored) {
            }
            bound = false;
        }
        service = null;
    }

    private void ensureBound() {
        if (bound) {
            return;
        }
        Intent i = new Intent(activity, NetworkSelfTestService.class);
        activity.startService(i);
        bound = activity.bindService(i, connection, Context.BIND_AUTO_CREATE);
    }

    private void loadCachedOrRequest() {
        INetworkSelfTestService s = service;
        if (s == null) {
            return;
        }
        try {
            NetworkConditions cached = s.getCachedConditions();
            if (cached != null && cached.reportText != null && !cached.reportText.isEmpty()) {
                report.setText(render(cached));
                return;
            }
            requestForceRefresh();
        } catch (RemoteException e) {
            report.setText("Self-test service error: " + e.getMessage());
        }
    }

    private void requestForceRefresh() {
        INetworkSelfTestService s = service;
        if (s == null) {
            ensureBound();
            s = service;
            if (s == null) {
                return;
            }
        }
        spinner.setVisibility(View.VISIBLE);
        report.setText(activity.getString(R.string.dev_network_selftest_running));
        try {
            s.requestRefresh();
        } catch (RemoteException e) {
            spinner.setVisibility(View.GONE);
            report.setText("Self-test service error: " + e.getMessage());
            return;
        }
        main.removeCallbacks(refreshPoll);
        main.postDelayed(refreshPoll, 700);
    }

    private String render(NetworkConditions c) {
        StringBuilder sb = new StringBuilder();
        long ageMs = Math.max(0L, System.currentTimeMillis() - c.collectedAtMs);
        String age = ageMs < 60_000L
                ? (ageMs / 1000L) + "s ago"
                : (ageMs / 60_000L) + "m ago";
        String fp = c.fingerprint != null ? c.fingerprint : "";
        if (fp.length() > 10) {
            fp = fp.substring(0, 10) + "…";
        }
        sb.append("snapshot ").append(age).append(" · fp ").append(fp);
        if (c.refreshing) {
            sb.append(" · refreshing");
        }
        sb.append("\n—\n");
        sb.append(c.reportText != null ? c.reportText : "");
        return sb.toString();
    }
}
