package ca.terraskies.missionbridge;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.widget.EditText;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/** Read-only cloud plan browser; uses the app's existing JSON import and preview. */
public final class MyPlans {
    public interface PlanOpener { void open(Uri uri); }
    private static final String BASE = "https://terraskies-nl.tbmarch79.chatgpt.site/api/plans";
    private static final ExecutorService IO = Executors.newSingleThreadExecutor();
    private static final Handler MAIN = new Handler(Looper.getMainLooper());
    private MyPlans() { }
    public static void show(Activity activity, PlanOpener opener) {
        SharedPreferences prefs = activity.getSharedPreferences("terraskies-cloud", Activity.MODE_PRIVATE);
        String key = prefs.getString("connection", "");
        if (key.isEmpty()) { connect(activity, opener); return; }
        new AlertDialog.Builder(activity).setTitle("My Plans")
                .setItems(new String[] {"Refresh cloud plans", "Downloaded plans (offline)", "Change phone connection", "Disconnect phone"}, (d, i) -> {
                    if (i == 0) refresh(activity, opener, key);
                    else if (i == 1) cached(activity, opener);
                    else if (i == 2) connect(activity, opener);
                    else { prefs.edit().clear().apply(); clearCache(activity); message(activity, "Phone disconnected", "The cloud copies are still saved."); }
                }).setNegativeButton("Close", null).show();
    }
    private static void connect(Activity activity, PlanOpener opener) {
        EditText field = new EditText(activity);
        field.setHint("Paste the private connection code");
        field.setSingleLine(true);
        new AlertDialog.Builder(activity).setTitle("Connect cloud plans")
                .setMessage("On your computer: Cloud plans → Connect Mission Bridge. Paste that code here once.")
                .setView(field).setPositiveButton("Connect", (d, which) -> {
                    String key = field.getText().toString().trim();
                    if (!key.matches("[a-f0-9]{64}")) { message(activity, "Check the code", "Paste the complete 64-character phone connection code."); return; }
                    IO.execute(() -> { try {
                        JSONObject list = request("", key);
                        MAIN.post(() -> {
                            if (activity.isFinishing() || activity.isDestroyed()) return;
                            SharedPreferences prefs = activity.getSharedPreferences("terraskies-cloud", Activity.MODE_PRIVATE);
                            if (!key.equals(prefs.getString("connection", ""))) clearCache(activity);
                            prefs.edit().putString("connection", key).apply();
                            choose(activity, opener, key, list.optJSONArray("plans"));
                        });
                    } catch (Exception error) { failure(activity, error); } });
                }).setNegativeButton("Cancel", null).show();
    }
    private static void refresh(Activity activity, PlanOpener opener, String key) {
        message(activity, "Refreshing plans", "Fetching your latest cloud plans. The list will open when ready.");
        IO.execute(() -> { try {
            JSONArray plans = request("", key).getJSONArray("plans");
            MAIN.post(() -> choose(activity, opener, key, plans));
        } catch (Exception error) { failure(activity, error); } });
    }
    private static void choose(Activity activity, PlanOpener opener, String key, JSONArray plans) {
        if (activity.isFinishing() || activity.isDestroyed()) return;
        if (plans == null || plans.length() == 0) { message(activity, "No cloud plans", "On your computer, name your plan and choose Save to cloud."); return; }
        String[] labels = new String[plans.length()];
        for (int i = 0; i < labels.length; i++) { JSONObject p = plans.optJSONObject(i); labels[i] = p.optString("folder") + " / " + p.optString("name") + "\n" + p.optString("updated"); }
        new AlertDialog.Builder(activity).setTitle("My cloud plans").setItems(labels, (d, index) -> {
            JSONObject entry = plans.optJSONObject(index);
            String id = entry.optString("id");
            if (!id.matches("[a-f0-9-]{36}")) { message(activity, "Invalid plan", "Refresh the plan list."); return; }
            IO.execute(() -> { try {
                JSONObject plan = request("/" + id, key);
                if (!"ca.terraskies.flight-plan".equals(plan.optString("schema")) || plan.optInt("schemaVersion") != 1) throw new Exception("Unrecognized plan format.");
                File file = new File(cacheDir(activity), id + ".json");
                try (FileOutputStream out = new FileOutputStream(file)) { out.write(plan.toString().getBytes(StandardCharsets.UTF_8)); }
                MAIN.post(() -> { if (!activity.isFinishing() && !activity.isDestroyed()) opener.open(Uri.fromFile(file)); });
            } catch (Exception error) { failure(activity, error); } });
        }).setNegativeButton("Close", null).show();
    }
    private static JSONObject request(String path, String key) throws Exception {
        HttpURLConnection connection = (HttpURLConnection) new URL(BASE + path).openConnection();
        connection.setConnectTimeout(15000); connection.setReadTimeout(15000);
        connection.setInstanceFollowRedirects(false);
        connection.setRequestProperty("X-TerraSkies-Device-Key", key);
        connection.setRequestProperty("Accept", "application/json");
        try {
            int status = connection.getResponseCode();
            if (status == 401) throw new Exception("Phone connection expired or was revoked. Create a new code in the planner and choose Change phone connection.");
            if (status != 200) throw new Exception("Cloud plans are unavailable right now. Try again, or open a downloaded plan offline.");
            try (InputStream in = connection.getInputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream()) {
                byte[] buffer = new byte[8192]; int count;
                while ((count = in.read(buffer)) != -1) { if (out.size() + count > 550000) throw new Exception("Plan is too large."); out.write(buffer, 0, count); }
                return new JSONObject(out.toString("UTF-8"));
            }
        } finally { connection.disconnect(); }
    }
    private static File cacheDir(Activity activity) { File dir = new File(activity.getFilesDir(), "cloud-plans"); dir.mkdirs(); return dir; }
    private static void clearCache(Activity activity) { File[] files = cacheDir(activity).listFiles(); if (files != null) for (File file : files) file.delete(); }
    private static void cached(Activity activity, PlanOpener opener) {
        File[] files = cacheDir(activity).listFiles((dir, name) -> name.endsWith(".json"));
        if (files == null || files.length == 0) { message(activity, "No downloaded plans", "Open a cloud plan while online to keep an offline copy."); return; }
        String[] names = new String[files.length];
        for (int i = 0; i < files.length; i++) names[i] = files[i].getName();
        new AlertDialog.Builder(activity).setTitle("Downloaded plans").setItems(names, (d, i) -> opener.open(Uri.fromFile(files[i]))).setNegativeButton("Close", null).show();
    }
    private static void failure(Activity activity, Exception error) { MAIN.post(() -> message(activity, "Could not load plans", error.getMessage())); }
    private static void message(Activity activity, String title, String body) { if (!activity.isFinishing() && !activity.isDestroyed()) new AlertDialog.Builder(activity).setTitle(title).setMessage(body).setPositiveButton("OK", null).show(); }
}
