package com.miraclegarden.smsmessage.xposed.hook;

import android.util.Base64;

import java.nio.charset.StandardCharsets;

import de.robv.android.xposed.XposedBridge;

/**
 * 分段 logcat 输出，避免单条超过 ~4KB 被截断。
 */
final class MariBankCaptureUtil {

    static final String TAG = "notiMessageHook/MariBankCapture";
    private static final int CHUNK = 3500;
    private static final int HEX_PREVIEW = 96;

    private MariBankCaptureUtil() {
    }

    static void logText(String section, String text) {
        if (text == null) {
            XposedBridge.log(TAG + " [" + section + "] null");
            return;
        }
        if (text.length() <= CHUNK) {
            XposedBridge.log(TAG + " [" + section + "] len=" + text.length() + " " + text);
            return;
        }
        int parts = (text.length() + CHUNK - 1) / CHUNK;
        XposedBridge.log(TAG + " [" + section + "] len=" + text.length() + " parts=" + parts);
        for (int i = 0; i < parts; i++) {
            int start = i * CHUNK;
            int end = Math.min(start + CHUNK, text.length());
            XposedBridge.log(TAG + " [" + section + "] " + (i + 1) + "/" + parts + " "
                    + text.substring(start, end));
        }
    }

    static void logBytes(String section, byte[] bytes) {
        if (bytes == null) {
            XposedBridge.log(TAG + " [" + section + "] null");
            return;
        }
        String utf8 = tryUtf8(bytes);
        if (isMostlyPrintable(utf8)) {
            logText(section + " utf8", utf8);
        } else {
            XposedBridge.log(TAG + " [" + section + "] byte[" + bytes.length + "] hex="
                    + hexPreview(bytes) + " b64=" + base64(bytes));
        }
    }

    static void logArg(String section, Object arg) {
        if (arg == null) {
            XposedBridge.log(TAG + " [" + section + "] null");
            return;
        }
        if (arg instanceof String) {
            logText(section, (String) arg);
            return;
        }
        if (arg instanceof byte[]) {
            logBytes(section, (byte[]) arg);
            return;
        }
        if (arg instanceof String[]) {
            String[] arr = (String[]) arg;
            XposedBridge.log(TAG + " [" + section + "] String[" + arr.length + "]");
            for (int i = 0; i < arr.length; i++) {
                logText(section + "[" + i + "]", arr[i]);
            }
            return;
        }
        if (arg instanceof byte[][]) {
            byte[][] arr = (byte[][]) arg;
            XposedBridge.log(TAG + " [" + section + "] byte[][] len=" + arr.length);
            for (int i = 0; i < arr.length; i++) {
                logBytes(section + "[" + i + "]", arr[i]);
            }
            return;
        }
        XposedBridge.log(TAG + " [" + section + "] " + arg.getClass().getName()
                + " = " + String.valueOf(arg));
    }

    static boolean isBankUrl(String url) {
        if (url == null || url.isEmpty()) {
            return false;
        }
        String lower = url.toLowerCase();
        return lower.contains("maribank.com")
                || lower.contains("seabank.ph")
                || lower.contains("/uapi/");
    }

    private static String tryUtf8(byte[] bytes) {
        try {
            return new String(bytes, StandardCharsets.UTF_8);
        } catch (Throwable t) {
            return "";
        }
    }

    static boolean isMostlyPrintable(String s) {
        if (s == null || s.isEmpty()) {
            return false;
        }
        int printable = 0;
        int sample = Math.min(s.length(), 512);
        for (int i = 0; i < sample; i++) {
            char c = s.charAt(i);
            if (c == '\n' || c == '\r' || c == '\t' || (c >= 32 && c < 127)) {
                printable++;
            }
        }
        return printable * 100 / sample >= 85;
    }

    private static String hexPreview(byte[] bytes) {
        int n = Math.min(bytes.length, HEX_PREVIEW);
        StringBuilder sb = new StringBuilder(n * 2);
        for (int i = 0; i < n; i++) {
            sb.append(String.format("%02x", bytes[i] & 0xff));
        }
        if (bytes.length > n) {
            sb.append("...");
        }
        return sb.toString();
    }

    private static String base64(byte[] bytes) {
        try {
            return Base64.encodeToString(bytes, Base64.NO_WRAP);
        } catch (Throwable t) {
            return "<b64 err>";
        }
    }
}
