package com.erwan.revwatch

import android.Manifest
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Size
import android.view.HapticFeedbackConstants
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.erwan.revwatch.util.dp
import com.google.zxing.BinaryBitmap
import com.google.zxing.MultiFormatReader
import com.google.zxing.PlanarYUVLuminanceSource
import com.google.zxing.common.HybridBinarizer
import java.util.concurrent.Executors

class QrScanActivity : BaseActivity() {

    companion object {
        const val EXTRA_QR_TEXT = "qr_text"
        private const val REQ_CAMERA = 601
    }

    private val cameraExecutor = Executors.newSingleThreadExecutor()
    private var scanned = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val root = FrameLayout(this).apply {
            setBackgroundColor(0xFF000000.toInt())
        }

        // Camera preview
        val previewView = PreviewView(this).apply {
            layoutParams = FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT
            )
        }
        root.addView(previewView)

        // Title
        val title = TextView(this).apply {
            text = "Scanner un QR code"
            textSize = 11f
            setTextColor(0xFFFFFFFF.toInt())
            gravity = android.view.Gravity.CENTER
            layoutParams = FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.WRAP_CONTENT
            ).apply {
                topMargin = dp(12)
                gravity = android.view.Gravity.TOP
            }
        }
        root.addView(title)

        // Close button
        val closeBtn = ImageView(this).apply {
            setImageResource(R.drawable.ic_close)
            val s = dp(32)
            layoutParams = FrameLayout.LayoutParams(s, s).apply {
                gravity = android.view.Gravity.BOTTOM or android.view.Gravity.CENTER_HORIZONTAL
                bottomMargin = dp(16)
            }
            setBackgroundResource(R.drawable.bg_nav_button)
            val p = dp(6)
            setPadding(p, p, p, p)
            setOnClickListener {
                it.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
                finish()
            }
        }
        root.addView(closeBtn)

        setContentView(root)
        enableImmersiveMode()

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
            == PackageManager.PERMISSION_GRANTED) {
            startCamera(previewView)
        } else {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQ_CAMERA)
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQ_CAMERA && grantResults.isNotEmpty()
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            val pv = (window.decorView as FrameLayout).getChildAt(0) as? FrameLayout
            val previewView = pv?.getChildAt(0) as? PreviewView
            if (previewView != null) startCamera(previewView)
        } else {
            Toast.makeText(this, "Permission caméra requise", Toast.LENGTH_SHORT).show()
            finish()
        }
    }

    @androidx.annotation.OptIn(androidx.camera.core.ExperimentalGetImage::class)
    private fun startCamera(previewView: PreviewView) {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            val cameraProvider = cameraProviderFuture.get()

            val preview = Preview.Builder().build().also {
                it.setSurfaceProvider(previewView.surfaceProvider)
            }

            val analysis = ImageAnalysis.Builder()
                .setTargetResolution(Size(480, 480))
                .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                .build()

            val reader = MultiFormatReader()

            analysis.setAnalyzer(cameraExecutor) { imageProxy ->
                if (!scanned) {
                    val text = decodeQr(imageProxy, reader)
                    if (text != null && looksLikeFaceDsl(text)) {
                        scanned = true
                        runOnUiThread {
                            window.decorView.performHapticFeedback(HapticFeedbackConstants.CONFIRM)
                        }
                        setResult(Activity.RESULT_OK, Intent().apply {
                            putExtra(EXTRA_QR_TEXT, text)
                        })
                        finish()
                    }
                }
                imageProxy.close()
            }

            try {
                cameraProvider.unbindAll()
                cameraProvider.bindToLifecycle(this, CameraSelector.DEFAULT_BACK_CAMERA, preview, analysis)
            } catch (_: Exception) {
                Toast.makeText(this, "Erreur caméra", Toast.LENGTH_SHORT).show()
                finish()
            }
        }, ContextCompat.getMainExecutor(this))
    }

    /** Decode a QR code from a CameraX frame using ZXing (pure Java). */
    private fun decodeQr(imageProxy: ImageProxy, reader: MultiFormatReader): String? {
        val plane = imageProxy.planes.firstOrNull() ?: return null
        val buffer = plane.buffer
        val bytes = ByteArray(buffer.remaining())
        buffer.get(bytes)

        val width = imageProxy.width
        val height = imageProxy.height
        val source = PlanarYUVLuminanceSource(
            bytes, width, height,
            0, 0, width, height,
            false
        )
        val bitmap = BinaryBitmap(HybridBinarizer(source))
        return try {
            reader.decodeWithState(bitmap).text
        } catch (_: Exception) {
            null
        } finally {
            reader.reset()
        }
    }

    private fun looksLikeFaceDsl(text: String): Boolean =
        text.contains("@name") || text.contains("bg ") ||
                text.contains("circle ") || text.contains("rect ") ||
                text.contains("progress_")

    override fun onDestroy() {
        cameraExecutor.shutdown()
        super.onDestroy()
    }
}
