package com.pxkj.jwzs;

import android.app.DownloadManager;
import android.content.Context;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.SslErrorHandler;
import android.webkit.URLUtil;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import android.app.Activity;
import android.content.Intent;          // ← 文件选择核心类
import android.database.Cursor;        // ← 解析文件信息
import android.provider.OpenableColumns; // ← 获取文件名、大小

import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

public class FirstActivity extends BaseActivity {
    private static final String TAG = "FirstActivity";
    private WebView webView;
    protected WebViewLogger webViewLogger;
    private final Handler handler = new Handler(Looper.getMainLooper());

    // 扩展的 MIME 类型映射
    private static final Map<String, String> MIME_TYPES = new HashMap<>();

    static {
        MIME_TYPES.put("js", "text/javascript");
        MIME_TYPES.put("mjs", "text/javascript");
        MIME_TYPES.put("css", "text/css");
        MIME_TYPES.put("html", "text/html");
        MIME_TYPES.put("png", "image/png");
        MIME_TYPES.put("jpg", "image/jpeg");
        MIME_TYPES.put("jpeg", "image/jpeg");
        MIME_TYPES.put("gif", "image/gif");
        MIME_TYPES.put("svg", "image/svg+xml");
        MIME_TYPES.put("json", "application/json");
        MIME_TYPES.put("woff", "font/woff");
        MIME_TYPES.put("woff2", "font/woff2");
        MIME_TYPES.put("ttf", "font/ttf");
        MIME_TYPES.put("wasm", "application/wasm");

        MIME_TYPES.put("pdf", "application/pdf");
        MIME_TYPES.put("zip", "application/zip");
        MIME_TYPES.put("rar", "application/x-rar-compressed");
        MIME_TYPES.put("7z", "application/x-7z-compressed");
        MIME_TYPES.put("csv", "text/csv");
        MIME_TYPES.put("txt", "text/plain");
        MIME_TYPES.put("mp3", "audio/mpeg");
        MIME_TYPES.put("mp4", "video/mp4");
        MIME_TYPES.put("mov", "video/quicktime");
        MIME_TYPES.put("webm", "video/webm");
        MIME_TYPES.put("ogg", "audio/ogg");
        MIME_TYPES.put("wav", "audio/wav");
        MIME_TYPES.put("eot", "application/vnd.ms-fontobject");
        MIME_TYPES.put("otf", "font/otf");
        MIME_TYPES.put("doc", "application/msword");
        MIME_TYPES.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        MIME_TYPES.put("xls", "application/vnd.ms-excel");
        MIME_TYPES.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        MIME_TYPES.put("ppt", "application/vnd.ms-powerpoint");
        MIME_TYPES.put("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initWebView();
        loadLocalH5();
        verifyAssets();
    }

    @Override
    public void onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack();
        } else {
            super.onBackPressed();
        }
    }

    private void verifyAssets() {
        try {
            String[] files = getAssets().list("web");
            Log.d(TAG, "Assets/web 目录内容: " + java.util.Arrays.toString(files));
        } catch (IOException e) {
            Log.e(TAG, "无法读取 assets 目录", e);
        }
    }

    private void initWebView() {
        webView = findViewById(R.id.webview);
        WebSettings settings = webView.getSettings();

        settings.setJavaScriptEnabled(true);
        settings.setDomStorageEnabled(true);
        settings.setDatabaseEnabled(true);
        settings.setAllowFileAccess(true);
        settings.setAllowContentAccess(true);
        settings.setJavaScriptCanOpenWindowsAutomatically(true);
        settings.setLoadsImagesAutomatically(true);
        settings.setBlockNetworkImage(false);
        settings.setBlockNetworkLoads(false);
        settings.setCacheMode(WebSettings.LOAD_DEFAULT);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            settings.setAllowFileAccessFromFileURLs(true);
            settings.setAllowUniversalAccessFromFileURLs(true);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            settings.setForceDark(WebSettings.FORCE_DARK_OFF);
        }

        webView.addJavascriptInterface(new JsBridge(this), "AndroidBridge");

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WebView.setWebContentsDebuggingEnabled(true);
        }

        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                log(TAG, "H5页面加载完成: " + url);
                injectDebugScript();
            }

            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed();
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                if (isDownloadUrl(url)) {
                    downloadFile(url);
                    return true;
                }
                return super.shouldOverrideUrlLoading(view, url);
            }

            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
                String url = request.getUrl().toString();
                log(TAG, "拦截请求: " + url);
                return handleResourceRequest(url);
            }

            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                    log(TAG, "拦截请求(旧版本): " + url);
                    return handleResourceRequest(url);
                }
                return super.shouldInterceptRequest(view, url);
            }

            private WebResourceResponse handleResourceRequest(String url) {
                if (url.startsWith("file:///android_asset/")) {
                    try {
                        String assetPath = url.replace("file:///android_asset/", "");
                        assetPath = assetPath.replace("web/./", "web/").replace("/./", "/");
                        if (!assetPath.startsWith("web/")) assetPath = "web/" + assetPath;

                        InputStream inputStream = getAssets().open(assetPath);
                        String mimeType = getMimeTypeForUrl(url);
                        log(TAG, "成功加载资源: " + assetPath + " | MIME: " + mimeType);
                        return new WebResourceResponse(mimeType, "UTF-8", inputStream);
                    } catch (IOException e) {
                        log(TAG, "资源加载失败: " + url + ", 错误: " + e.getMessage());
                        return null;
                    }
                }
                return null;
            }
        });

        // DownloadListener 备用
        webView.setDownloadListener((url, userAgent, contentDisposition, mimeType, contentLength) -> {
            downloadFile(url);
        });
    }

    private String getMimeTypeForUrl(String url) {
        if (url.contains("index-DJSXJc-t.js") || url.contains(".mjs") || (url.contains("module") && url.endsWith(".js"))) {
            return "text/javascript";
        }
        String cleanUrl = url.split("[?#]")[0];
        String extension = "";
        int dotIndex = cleanUrl.lastIndexOf('.');
        if (dotIndex > 0) extension = cleanUrl.substring(dotIndex + 1).toLowerCase();
        String mimeType = MIME_TYPES.get(extension);
        return mimeType != null ? mimeType : "text/plain";
    }

    private void injectDebugScript() {
        String js = "function appendLog(msg) { console.log(msg); }" +
                "if (!window.console) window.console = { log: appendLog };";
        webView.evaluateJavascript(js, null);
    }

    private void loadLocalH5() {
        runOnUiThread(() -> {
            String localUrl = "file:///android_asset/web/index.html";
            log(TAG, "使用 loadUrl 加载: " + localUrl);
            webView.loadUrl(localUrl);
        });
    }

    private boolean isDownloadUrl(String url) {
        if (TextUtils.isEmpty(url)) return false;
        return true;
//        return url.endsWith(".pdf")
//                || url.endsWith(".doc")
//                || url.endsWith(".docx")
//                || url.endsWith(".xls")
//                || url.endsWith(".xlsx")
//                || url.contains("/api/file/");
    }

    private void previewFile(String url) {
        try {
            if (webView != null) {
                webView.loadUrl(url);
            }

            Toast.makeText(this, "正在打开文件预览...", Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(this, "预览文件失败: " + e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }

    private long currentDownloadId = -1; // 保存当前下载任务ID

    private void downloadFile(String url) {
        try {
            if (TextUtils.isEmpty(url)) {
                Toast.makeText(this, "下载地址为空", Toast.LENGTH_SHORT).show();
                return;
            }

            if (url.startsWith("blob:") || url.startsWith("data:")) {
                Toast.makeText(this, "无法直接下载 Blob 文件，请检查前端下载逻辑", Toast.LENGTH_SHORT).show();
                return;
            }

            Uri uri = Uri.parse(url);
            DownloadManager.Request request = new DownloadManager.Request(uri);

            String fileName = URLUtil.guessFileName(url, null, null);
            request.setTitle(fileName);
            request.setDescription("正在下载文件...");
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
            request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
            request.allowScanningByMediaScanner();
            request.addRequestHeader("User-Agent", System.getProperty("http.agent"));

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                request.setRequiresCharging(false);
                request.setAllowedOverMetered(true);
                request.setAllowedOverRoaming(true);
            }

            String mimeType = getMimeTypeForUrl(url);
            request.setMimeType(!TextUtils.isEmpty(mimeType) ? mimeType : "application/octet-stream");

            DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
            if (dm != null) {
                Toast.makeText(this, "文件已开始下载，请等待", Toast.LENGTH_SHORT).show();
                currentDownloadId = dm.enqueue(request);
                startDownloadProgressMonitor(dm, currentDownloadId);
            } else {
                Toast.makeText(this, "系统下载服务不可用", Toast.LENGTH_SHORT).show();
            }

        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(this, "下载失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * ✅ 监控下载进度，每秒回调一次到前端
     */
    private void startDownloadProgressMonitor(DownloadManager dm, long downloadId) {

        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterById(downloadId);
        boolean downloading = true;

        while (downloading) {
            try {
                Thread.sleep(1000);
                android.database.Cursor cursor = dm.query(query);
                if (cursor != null && cursor.moveToFirst()) {
                    int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
                    long total = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                    long downloaded = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                    if (status == DownloadManager.STATUS_RUNNING && total > 0) {
                        int progress = (int) ((downloaded * 100L) / total);
                        Toast.makeText(this, "下载中，当前进度为" + progress + "%", Toast.LENGTH_SHORT).show();
                        handler.post(() -> sendProgressToJs(progress));
                    } else if (status == DownloadManager.STATUS_SUCCESSFUL) {
                        Toast.makeText(this, "下载完成，请到文件管理查看", Toast.LENGTH_SHORT).show();
                        downloading = false;
                        handler.post(() -> sendProgressToJs(100));
                    } else if (status == DownloadManager.STATUS_FAILED) {
                        Toast.makeText(this, "下载失败" + status + "," + total + "," + downloaded, Toast.LENGTH_SHORT).show();
                        downloading = false;
                        handler.post(() -> sendProgressToJs(-1));
                    }
                    cursor.close();
                }
            } catch (Exception ignored) {
                Toast.makeText(this, "文件已开始下载，请等待报错", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void sendProgressToJs(int progress) {
        try {
            if (webView != null) {
                String js = String.format("if(window.onDownloadProgress){window.onDownloadProgress(%d);}", progress);
                webView.evaluateJavascript(js, null);
            }
        } catch (Exception ignored) {
            Toast.makeText(this, "文件已开始下载，请等待报错sendProgressToJs", Toast.LENGTH_SHORT).show();
        }
    }

// ==============================
// 文件选择与上传逻辑（新增部分）
// ==============================

    private static final int REQUEST_CODE_FILE_CHOOSER = 2001;

    /**
     * JS 调用此方法选择文件
     */
    @JavascriptInterface
    public void chooseFile() {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("*/*");
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        startActivityForResult(Intent.createChooser(intent, "选择要上传的文件"), REQUEST_CODE_FILE_CHOOSER);
    }

    /**
     * 文件选择结果回调
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_FILE_CHOOSER && resultCode == RESULT_OK && data != null) {
            Uri uri = data.getData();
            if (uri != null) {
                Toast.makeText(this, "文件已选择，开始上传...", Toast.LENGTH_SHORT).show();
                uploadFile(uri);  // 自动上传文件
            }
        }
    }

    /**
     * 上传文件到服务器
     */
    private void uploadFile(Uri uri) {
        new Thread(() -> {
            try {
                // ✅ 修改为你的文件上传接口地址
//                String uploadUrl = "http://218.92.207.242:9678/file/upload"; // TODO: 替换为后端真实接口

                String uploadUrl = "http://20.47.196.98:40080/fwzx/v1.0.0/getServiceInfoByServiceId/32092423SJNB12202507111046530001/320924230000-3-0800-5CDEC9969D674E1CBB7E2F86A697B0D7/api/file/upload";

                String token = getToken(); // ✅ 从本地获取前端传来的 token
                if (TextUtils.isEmpty(token)) {
                    runOnUiThread(() -> Toast.makeText(this, "请先登录后再上传", Toast.LENGTH_SHORT).show());
                    return;
                }

                // 获取文件名
                String fileName = getFileNameFromUri(uri);
                if (TextUtils.isEmpty(fileName)) fileName = "upload_file";

                // 读取文件内容
                InputStream inputStream = getContentResolver().openInputStream(uri);
                byte[] fileBytes = new byte[inputStream.available()];
                inputStream.read(fileBytes);
                inputStream.close();

                // 使用 OkHttp 上传
                okhttp3.OkHttpClient client = new okhttp3.OkHttpClient();
                okhttp3.RequestBody fileBody = okhttp3.RequestBody.create(
                        okhttp3.MediaType.parse("application/octet-stream"),
                        fileBytes
                );
                okhttp3.MultipartBody requestBody = new okhttp3.MultipartBody.Builder()
                        .setType(okhttp3.MultipartBody.FORM)
                        .addFormDataPart("file", fileName, fileBody)
                        .build();

                okhttp3.Request request = new okhttp3.Request.Builder()
                        .url(uploadUrl)
                        .addHeader("accesstoken", token)  // ✅ 添加 token 认证头
                        .post(requestBody)
                        .build();

                okhttp3.Response response = client.newCall(request).execute();

                if (response.isSuccessful()) {
                    String result = response.body().string();
                    Log.d(TAG, "文件上传成功: " + result);

                    // ✅ 提取 fileName 与后端返回的 data
                    String safeResult = result.replace("'", "\\'"); // 避免 JS 语法错误
                    String safeFileName = fileName.replace("'", "\\'");

                    runOnUiThread(() -> {
                        Toast.makeText(this, "上传成功", Toast.LENGTH_SHORT).show();

                        if (webView != null) {
                            // ✅ 传 fileName 与 data 到前端
                            String jsCode = String.format(
                                    "window.onFileUploadSuccess && window.onFileUploadSuccess({fileName: '%s', data: %s})",
                                    safeFileName, safeResult
                            );
                            webView.evaluateJavascript(jsCode, null);
                        }
                    });
                } else {
                    runOnUiThread(() ->
                            Toast.makeText(this, "上传失败: " + response.code(), Toast.LENGTH_LONG).show()
                    );
                }

            } catch (Exception e) {
                e.printStackTrace();
                runOnUiThread(() ->
                        Toast.makeText(this, "上传异常: " + e.getMessage(), Toast.LENGTH_LONG).show()
                );
            }
        }).start();
    }

    /**
     * 从 Uri 获取文件名
     */
    private String getFileNameFromUri(Uri uri) {
        String result = null;
        if ("content".equals(uri.getScheme())) {
            try (android.database.Cursor cursor = getContentResolver().query(uri, null, null, null, null)) {
                if (cursor != null && cursor.moveToFirst()) {
                    result = cursor.getString(cursor.getColumnIndexOrThrow(android.provider.OpenableColumns.DISPLAY_NAME));
                }
            }
        }
        if (result == null) {
            result = uri.getPath();
            int cut = result.lastIndexOf('/');
            if (cut != -1) result = result.substring(cut + 1);
        }
        return result;
    }

// ==============================
// ✅ 新增：存储与获取 token 的方法
// ==============================

    private static final String KEY_TOKEN = "USER_TOKEN";

    // JS 传入 token
    @JavascriptInterface
    public void setToken(String token) {
        if (!TextUtils.isEmpty(token)) {
            SpUtils.putString(this, KEY_TOKEN, token);
            Log.d(TAG, "已保存 token: " + token);
        }
    }

    // 获取本地 token
    private String getToken() {
        return SpUtils.getString(this, KEY_TOKEN, "");
    }


    public static class JsBridge {
        private final WeakReference<FirstActivity> activityRef;

        public JsBridge(FirstActivity activity) {
            this.activityRef = new WeakReference<>(activity);
        }

        @JavascriptInterface
        public String fetchResourceAddress() {
            FirstActivity activity = activityRef.get();
            if (activity != null) {
                showLog("[Android] 开始获取资源地址...");
                String baseUrl = SpUtils.getString(activity, "TARGET_URL", "");
                showLog("[Android] 获取到资源地址: " + baseUrl);
                return baseUrl;
            }
            return null;
        }

        @JavascriptInterface
        public void callApiWithAddress(String apiPath) {
            // 保持空实现
        }

        // 新增：供前端H5调用下载
        @JavascriptInterface
        public void downloadFile(String url) {
            FirstActivity activity = activityRef.get();
            if (activity != null && !TextUtils.isEmpty(url)) {
                activity.runOnUiThread(() -> activity.downloadFile(url));
            }
        }

        // ✅ 供前端调用的文件选择方法
        @JavascriptInterface
        public void chooseFile() {
            FirstActivity activity = activityRef.get();
            if (activity != null) {
                activity.runOnUiThread(activity::chooseFile);
            }
        }

        // ✅ 供前端调用的文件选择方法
        @JavascriptInterface
        public void previewFile(String url) {
            FirstActivity activity = activityRef.get();
            if (activity != null && !TextUtils.isEmpty(url)) {
                activity.runOnUiThread(() -> activity.previewFile(url));
            }
        }

        // ✅ 供前端调用的文件选择方法
        @JavascriptInterface
        public void setToken(String token) {
            FirstActivity activity = activityRef.get();
            if (activity != null && !TextUtils.isEmpty(token)) {
                activity.runOnUiThread(() -> activity.setToken(token));
            }
        }
        @JavascriptInterface
        public void showLog(String message) {
            FirstActivity activity = activityRef.get();
            if (activity != null) {
                activity.runOnUiThread(() -> {
                    String escapedMessage = message.replace("\\", "\\\\")
                            .replace("'", "\\'")
                            .replace("\"", "\\\"")
                            .replace("\n", "\\n")
                            .replace("\r", "\\r");

                    String js = "javascript:try{if(window.appendLog){appendLog('" + escapedMessage + "');}}catch(e){console.error(e);}";
                    activity.webView.evaluateJavascript(js, null);
                });
            }
        }
    }

    @Override
    protected void refresh() {
        // 空实现
    }
//
//    private void log(String tag, String message) {
//        Log.d(tag, message);
//        if (webViewLogger != null) {
//            webViewLogger.d(tag, message);
//        }
//    }
}

class WebViewLogger {
    private final WebView webView;
    private final FirstActivity.JsBridge bridge;
    private final Handler handler = new Handler(Looper.getMainLooper());

    public WebViewLogger(WebView webView, FirstActivity.JsBridge bridge) {
        this.webView = webView;
        this.bridge = bridge;
    }

    public void d(String tag, String message) {
        Log.d(tag, message);
        handler.post(() -> bridge.showLog("[" + tag + "] " + message));
    }
}
