package `in`.webgrid.generp

import android.app.DownloadManager
import android.content.Context
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.webkit.CookieManager
import android.widget.Toast
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import java.io.File
import java.util.Base64

class MainActivity : FlutterActivity() {
    private val CHANNEL = "in.webgrid.generp/download"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            if (call.method == "startDownload") {
                val url = call.argument<String>("url")
                val userAgent = call.argument<String>("userAgent")
                val contentDisposition = call.argument<String>("contentDisposition")
                val mimeType = call.argument<String>("mimeType")
                val suggestedFilename = call.argument<String>("suggestedFilename")
                val isBase64 = call.argument<Boolean>("isBase64") ?: false

                if (url != null && userAgent != null && mimeType != null) {
                    val success = startDownload(url, userAgent, contentDisposition ?: "", mimeType, suggestedFilename ?: "", isBase64)
                    if (success) {
                        result.success("Download started")
                    } else {
                        result.error("DOWNLOAD_FAILED", "Failed to start download", null)
                    }
                } else {
                    result.error("INVALID_ARGUMENTS", "Missing required arguments", null)
                }
            } else {
                result.notImplemented()
            }
        }
    }

    private fun startDownload(
        url: String,
        userAgent: String,
        contentDisposition: String,
        mimeType: String,
        suggestedFilename: String,
        isBase64: Boolean
    ): Boolean {
        return try {
            // Show toast
            Toast.makeText(this, "File is being downloaded", Toast.LENGTH_SHORT).show()

            // Map MIME type to file extension
            val extension = when (mimeType.lowercase()) {
                "application/pdf" -> ".pdf"
                "image/jpeg" -> ".jpg"
                "image/png" -> ".png"
                "application/msword" -> ".doc"
                "application/vnd.openxmlformats-officedocument.wordprocessingml.document" -> ".docx"
                "application/vnd.ms-excel" -> ".xls"
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" -> ".xlsx"
                "text/csv" -> ".csv"
                else -> "" // Fallback for unknown types
            }

            // Determine file name
            var fileName = contentDisposition.takeIf { it.isNotEmpty() }?.let {
                val regex = Regex("filename=\"?([^\"\\s;]+)\"?")
                regex.find(it)?.groupValues?.get(1)
            } ?: suggestedFilename.takeIf { it.isNotEmpty() } ?: url.split("/").last()

            // Ensure the file name has the correct extension
            if (!fileName.endsWith(extension, ignoreCase = true)) {
                fileName = if (fileName.contains(".")) {
                    fileName.substringBeforeLast(".") + extension
                } else {
                    fileName + extension
                }
            }
            // Sanitize file name
            fileName = fileName.replace("[^a-zA-Z0-9._-]".toRegex(), "_")

            // Log for debugging
            println("Download File: $fileName, ContentDisposition: $contentDisposition, SuggestedFilename: $suggestedFilename, MimeType: $mimeType, IsBase64: $isBase64")

            if (isBase64 && url.startsWith("data:")) {
                // Handle base64 data URL
                val base64Data = url.substringAfter("base64,")
                val file = File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), fileName)
                val decodedBytes = Base64.getDecoder().decode(base64Data)
                file.writeBytes(decodedBytes)

                // Optionally, use DownloadManager to notify the user
                val request = DownloadManager.Request(Uri.fromFile(file))
                request.setMimeType(mimeType)
                request.setDescription("Downloading requested file....")
                request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
                request.setTitle(fileName)
                request.setAllowedOverMetered(true)
                request.setAllowedOverRoaming(false)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    request.setRequiresCharging(false)
                    request.setRequiresDeviceIdle(false)
                }
                request.setVisibleInDownloadsUi(true)

                val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
                downloadManager.enqueue(request)
            } else {
                // Handle regular URL
                val request = DownloadManager.Request(Uri.parse(url.trim()))
                val cookies = CookieManager.getInstance().getCookie(url) ?: ""
                request.addRequestHeader("Cookie", cookies)
                request.addRequestHeader("User-Agent", userAgent)
                request.setDescription("Downloading requested file....")
                request.setMimeType(mimeType)
                request.allowScanningByMediaScanner()
                request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
                request.setTitle(fileName)
                request.setAllowedOverMetered(true)
                request.setAllowedOverRoaming(false)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    request.setRequiresCharging(false)
                    request.setRequiresDeviceIdle(false)
                }
                request.setVisibleInDownloadsUi(true)

                val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
                downloadManager.enqueue(request)
            }
            true
        } catch (e: Exception) {
            e.printStackTrace()
            false
        }
    }
}