package com.miraclegarden.smsmessage.service;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;

import com.miraclegarden.smsmessage.Activity.NotificationActivity;
import com.miraclegarden.smsmessage.App;
import com.miraclegarden.smsmessage.AppConfig;
import com.miraclegarden.smsmessage.KeepAliveSettings;
import com.miraclegarden.smsmessage.MessageInfo;
import com.miraclegarden.smsmessage.R;
import com.miraclegarden.smsmessage.model.ApiError;
import com.miraclegarden.smsmessage.model.UploadNotificationResponse;
import com.miraclegarden.smsmessage.network.ApiService;
import com.miraclegarden.smsmessage.network.DebugForwarder;
import com.miraclegarden.smsmessage.network.TokenManager;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class NotificationService extends NotificationListenerService {
    private static final String TAG = "NotificationService";
    private static final int FOREGROUND_NOTIFICATION_ID = 9001;
    private static final String CHANNEL_ID = "notification_listener_channel";
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final String WAKELOCK_TAG = "NotificationService:WakeLock";

    private static final OkHttpClient HTTP_CLIENT = new OkHttpClient.Builder()
            .connectTimeout(15, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
            .readTimeout(15, TimeUnit.SECONDS)
            .build();

    private RetryManager retryManager;
    private PowerManager.WakeLock wakeLock;
    private static boolean isMonitoring = false;
    private static final String PREF_SERVER = "server";
    private static final String KEY_MONITORING_ACTIVE = "monitoring_active";
    private ApiService apiService;
    private TokenManager tokenManager;

    @Override
    public void onCreate() {
        super.onCreate();
        createNotificationChannel();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
            startForeground(FOREGROUND_NOTIFICATION_ID, buildForegroundNotification(0, false), ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            startForeground(FOREGROUND_NOTIFICATION_ID, buildForegroundNotification(0, false), ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
        } else {
            startForeground(FOREGROUND_NOTIFICATION_ID, buildForegroundNotification(0, false));
        }

        apiService = new ApiService(this);
        tokenManager = TokenManager.getInstance(this);

        retryManager = new RetryManager(this);
        if (AppConfig.ENABLE_SERVER_UPLOAD) {
            retryManager.setUploadCallback(this::performUpload);
            retryManager.restoreFromPersistence();
        }
    }

    private static final String ACTION_HOOK_MESSAGE = "ACTION_HOOK_MESSAGE";

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            if ("ACTION_START_MONITORING".equals(intent.getAction())) {
                startMonitoring();
            } else if (ACTION_HOOK_MESSAGE.equals(intent.getAction())) {
                handleHookMessageIntent(intent);
            }
        } else if (isMonitoringActive(this)) {
            MonitoredAppKeepAliveScheduler.schedule(this);
        }
        NotificationActivity.sendMessage("监听服务成功!");
        return START_STICKY;
    }

    public static void submitFromHook(Context context, MessageInfo messageInfo,
                                      String title, String content, long timestamp, String source) {
        Intent intent = new Intent(context, NotificationService.class);
        intent.setAction(ACTION_HOOK_MESSAGE);
        intent.putExtra("hook_package", messageInfo.getPackageName());
        intent.putExtra("hook_title", title);
        intent.putExtra("hook_content", content);
        intent.putExtra("hook_timestamp", timestamp);
        intent.putExtra("hook_source", source);
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(intent);
            } else {
                context.startService(intent);
            }
            Log.d(TAG, "submitFromHook: service started for " + messageInfo.getPackageName());
        } catch (Exception e) {
            Log.e(TAG, "submitFromHook failed: " + e.getMessage(), e);
            NotificationActivity.sendMessage("[Hook] 服务启动失败: " + e.getMessage());
        }
    }

    private void handleHookMessageIntent(Intent intent) {
        String packageName = intent.getStringExtra("hook_package");
        MessageInfo messageInfo = App.getMessageByNotiList(this, packageName);
        if (messageInfo == null) {
            return;
        }
        String source = intent.getStringExtra("hook_source");
        NotificationExtractor.Result result = new NotificationExtractor.Result(
                intent.getStringExtra("hook_title"),
                intent.getStringExtra("hook_content"),
                intent.getLongExtra("hook_timestamp", System.currentTimeMillis())
        );
        submitNotification(messageInfo, result, source != null ? source : "hook");
    }

    public static boolean isMonitoring() {
        return isMonitoring;
    }

    public static boolean isMonitoringActive(Context context) {
        if (isMonitoring) {
            return true;
        }
        return context.getSharedPreferences(PREF_SERVER, Context.MODE_PRIVATE)
                .getBoolean(KEY_MONITORING_ACTIVE, false);
    }

    private static void setMonitoringActive(Context context, boolean active) {
        isMonitoring = active;
        context.getSharedPreferences(PREF_SERVER, Context.MODE_PRIVATE)
                .edit()
                .putBoolean(KEY_MONITORING_ACTIVE, active)
                .apply();
    }

    private void startMonitoring() {
        if (isMonitoring) return;
        setMonitoringActive(this, true);

        toggleNotificationListenerService(this);
        MonitoredAppKeepAliveScheduler.schedule(this);
        if (KeepAliveSettings.isEnabled(this)) {
            MonitoredAppActivator.activateAllAsync(this);
        }
        updateForegroundNotification(retryManager != null
                ? (AppConfig.ENABLE_SERVER_UPLOAD ? retryManager.getUploadedCount() : retryManager.getTotalCount())
                : 0);
        NotificationActivity.sendMessage("已开启持续监听模式（含 App 保活）");
        NotificationActivity.updateUI();
    }

    public static void stopMonitoring(Context context) {
        setMonitoringActive(context, false);
        MonitoredAppKeepAliveScheduler.cancel(context);
        NotificationActivity.sendMessage("已停止监听服务");
        NotificationActivity.updateUI();
        Toast.makeText(context, "监听服务已停止", Toast.LENGTH_SHORT).show();
    }

    private void acquireWakeLockForUpload() {
        if (wakeLock != null && wakeLock.isHeld()) return;
        PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
        if (pm != null) {
            wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
            wakeLock.acquire(30_000);
        }
    }

    private void releaseWakeLockAfterUpload() {
        if (wakeLock != null && wakeLock.isHeld()) {
            wakeLock.release();
        }
    }

    public static void requestStartMonitoring(Context context) {
        toggleNotificationListenerService(context);
        try {
            Intent intent = new Intent(context, NotificationService.class);
            intent.setAction("ACTION_START_MONITORING");
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(intent);
            } else {
                context.startService(intent);
            }
        } catch (Exception e) {
            Log.e(TAG, "启动监听失败", e);
        }
    }

    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        if (sbn == null) return;

        if (sbn.getPackageName().equals(getPackageName())) return;

        MessageInfo messageInfo = App.getMessageByNotiList(this, sbn.getPackageName());
        if (messageInfo == null) return;

        NotificationExtractor.Result result = NotificationExtractor.extract(sbn);
        Log.i(TAG, "onNotificationPosted: pkg=" + sbn.getPackageName()
                + " title=" + result.title + " content=" + result.content);

        if (TextUtils.isEmpty(result.title) && TextUtils.isEmpty(result.content)) {
            Log.w(TAG, "skip empty notification: " + sbn.getPackageName()
                    + " extras=" + (sbn.getNotification().extras != null
                    ? sbn.getNotification().extras.keySet() : "null"));
            NotificationActivity.sendMessage("[" + messageInfo.getAppName() + "] 通知内容为空，跳过");
            return;
        }

        if (result.title.contains("正在运行") || result.title.contains("正在监听")) {
            return;
        }

        NotificationActivity.sendMessage(result.title + " " + result.content);
        submitNotification(messageInfo, result, "notification");
    }

    private void submitNotification(MessageInfo messageInfo, NotificationExtractor.Result result,
                                    String debugSource) {
        DebugForwarder.forward(this, messageInfo, result.title, result.content,
                result.timestamp, debugSource);

        if (!AppConfig.ENABLE_SERVER_UPLOAD) {
            recordLocalCapture();
            return;
        }

        if (!tokenManager.isLoggedIn()) {
            NotificationActivity.sendMessage("未登录，请先登录");
            return;
        }

        if (TextUtils.isEmpty(messageInfo.getBankInfoId())) {
            NotificationActivity.sendMessage("该应用未关联银行账户，请先配置");
            return;
        }

        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("bankInfoId", messageInfo.getBankInfoId());

            JSONObject dataObject = new JSONObject();
            dataObject.put("title", result.title);
            dataObject.put("context", result.content);
            dataObject.put("timestamp", result.timestamp);
            jsonObject.put("data", dataObject);

            jsonObject.put("name", messageInfo.getName());
            jsonObject.put("code", messageInfo.getCode());
            jsonObject.put("remark", messageInfo.getRemark());
            jsonObject.put("appName", messageInfo.getAppName());
            jsonObject.put("packageName", messageInfo.getPackageName());

            retryManager.enqueue(jsonObject.toString());
        } catch (JSONException e) {
            Log.e(TAG, "JSON构建失败", e);
            NotificationActivity.sendMessage("JSON构建失败: " + e.getMessage());
        }
    }

    private void recordLocalCapture() {
        if (retryManager != null) {
            retryManager.recordLocalCapture();
            updateForegroundNotification(retryManager.getTotalCount());
        }
        NotificationActivity.updateUI();
    }

    private void performUpload(String jsonPayload, RetryManager.UploadResultListener listener) {
        acquireWakeLockForUpload();

        // 使用新的API服务上传
        apiService.uploadNotification(jsonPayload, new ApiService.ApiCallback<UploadNotificationResponse>() {
            @Override
            public void onSuccess(UploadNotificationResponse result) {
                releaseWakeLockAfterUpload();
                String message = "提交成功";
                if (result.getId() != null) {
                    message += " (ID: " + result.getId().substring(0, Math.min(8, result.getId().length())) + "...)";
                }
                if (result.getDuplicateOfEmailSyncRecordId() != null) {
                    message += " [已去重]";
                }
                NotificationActivity.sendMessage(message);
                listener.onSuccess();
                updateForegroundNotification(retryManager.getUploadedCount());
            }

            @Override
            public void onError(ApiError error) {
                releaseWakeLockAfterUpload();
                String errorMsg = error.getMessage();
                if (error.isTokenExpired()) {
                    errorMsg = "登录已失效，请重新登录";
                    tokenManager.clear();
                }
                NotificationActivity.sendMessage("提交失败: " + errorMsg);
                listener.onFailure(errorMsg);
            }
        });
    }

    @Override
    public void onListenerDisconnected() {
        Log.w(TAG, "通知监听断开，尝试恢复");
        NotificationActivity.sendMessage("通知监听断开，尝试恢复...");
        toggleNotificationListenerService(this);

        new Handler(Looper.getMainLooper()).postDelayed(() -> {
            if (!isNotificationListenerEnabled()) {
                notifyNlsDisabled();
            }
        }, 2000);
    }

    private boolean isNotificationListenerEnabled() {
        String flat = Settings.Secure.getString(
                getContentResolver(),
                "enabled_notification_listeners");
        if (TextUtils.isEmpty(flat)) {
            return false;
        }
        return flat.contains(getPackageName());
    }

    private void notifyNlsDisabled() {
        Log.w(TAG, "通知监听已被禁用，向用户发出警告");
        NotificationActivity.sendMessage("警告：通知监听已被禁用，请重新开启！");

        Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        NotificationActivity.updateUI();
        if (wakeLock != null && wakeLock.isHeld()) {
            wakeLock.release();
            wakeLock = null;
        }
        if (retryManager != null) {
            retryManager.destroy();
        }
    }

    public static void toggleNotificationListenerService(Context context) {
        ComponentName thisComponent = new ComponentName(context, NotificationService.class);
        PackageManager pm = context.getPackageManager();
        pm.setComponentEnabledSetting(thisComponent,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
        pm.setComponentEnabledSetting(thisComponent,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID,
                    "通知监听服务",
                    NotificationManager.IMPORTANCE_LOW
            );
            channel.setDescription("保持通知监听服务运行");
            channel.setShowBadge(false);
            NotificationManager nm = getSystemService(NotificationManager.class);
            if (nm != null) {
                nm.createNotificationChannel(channel);
            }
        }
    }

    private Notification buildForegroundNotification(int count, boolean monitoring) {
        String title = monitoring ? "持续监听中" : "通知监听服务";
        String countLabel = AppConfig.ENABLE_SERVER_UPLOAD ? "已上传" : "已抓取";
        String text = monitoring
                ? countLabel + " " + count + " 条 · 持续运行中"
                : countLabel + " " + count + " 条";

        return new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle(title)
                .setContentText(text)
                .setSmallIcon(R.mipmap.app_logo)
                .setOngoing(true)
                .setPriority(NotificationCompat.PRIORITY_LOW)
                .setCategory(NotificationCompat.CATEGORY_SERVICE)
                .build();
    }

    private void updateForegroundNotification(int count) {
        NotificationManager nm = getSystemService(NotificationManager.class);
        if (nm != null) {
            nm.notify(FOREGROUND_NOTIFICATION_ID, buildForegroundNotification(count, isMonitoring));
        }
    }
}
