package com.example.mlkitocr

import android.Manifest
import android.content.ActivityNotFoundException
import android.content.ContentValues
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.*
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import com.google.mlkit.vision.common.InputImage
import com.google.mlkit.vision.text.TextRecognition
import com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions
import com.google.mlkit.vision.text.latin.TextRecognizerOptions
import com.google.mlkit.nl.languageid.LanguageIdentification
import com.google.mlkit.nl.languageid.LanguageIdentifier
import com.google.mlkit.common.model.DownloadConditions
import com.google.mlkit.nl.translate.TranslateLanguage
import com.google.mlkit.nl.translate.Translation
import com.google.mlkit.nl.translate.Translator
import com.google.mlkit.nl.translate.TranslatorOptions
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

class MainActivity : AppCompatActivity() {

    private lateinit var previewView: PreviewView
    private lateinit var tvOcr: TextView
    private lateinit var tvTrans: TextView
    private var imageCapture: ImageCapture? = null
    private lateinit var cameraExecutor: ExecutorService

    private var translator: Translator? = null
    private var languageIdentifier: LanguageIdentifier? = null

    private val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { perms ->
        val granted = perms[Manifest.permission.CAMERA] == true
        if (granted) startCamera() else Toast.makeText(this, "需要相机权限", Toast.LENGTH_SHORT).show()
    }

    private val pickMedia = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
        uri?.let { handleImageUri(it) }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        previewView = findViewById(R.id.previewView)
        tvOcr = findViewById(R.id.tvOcr)
        tvTrans = findViewById(R.id.tvTrans)

        findViewById<Button>(R.id.btnCapture).setOnClickListener { capturePhoto() }
        findViewById<Button>(R.id.btnPick).setOnClickListener {
            pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
        }

        cameraExecutor = Executors.newSingleThreadExecutor()
        ensurePermissionsAndStartCamera()

        languageIdentifier = LanguageIdentification.getClient()
    }

    private fun ensurePermissionsAndStartCamera() {
        val cameraGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
        if (cameraGranted) startCamera() else requestPermissionLauncher.launch(arrayOf(Manifest.permission.CAMERA))
    }

    private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            val cameraProvider = cameraProviderFuture.get()

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

            val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
            try {
                cameraProvider.unbindAll()
                cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture)
            } catch (exc: Exception) {
                Toast.makeText(this, "启动相机失败: ${exc.message}", Toast.LENGTH_SHORT).show()
            }
        }, ContextCompat.getMainExecutor(this))
    }

    private fun capturePhoto() {
        val imageCapture = imageCapture ?: return
        val name = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(System.currentTimeMillis())
        val photoFile = File.createTempFile(name, ".jpg", cacheDir)
        val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
        imageCapture.takePicture(outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback {
            override fun onError(exc: ImageCaptureException) {
                Toast.makeText(this@MainActivity, "拍照失败: ${exc.message}", Toast.LENGTH_SHORT).show()
            }

            override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
                handleImageUri(Uri.fromFile(photoFile))
            }
        })
    }

    private fun handleImageUri(uri: Uri) {
        try {
            val image = InputImage.fromFilePath(this, uri)
            recognizeText(image)
        } catch (e: Exception) {
            Toast.makeText(this, "读取图片失败: ${e.message}", Toast.LENGTH_SHORT).show()
        }
    }

    private fun recognizeText(image: InputImage) {
        // 优先中文识别，否则回退 Latin
        val zhRecognizer = TextRecognition.getClient(ChineseTextRecognizerOptions.Builder().build())
        zhRecognizer.process(image)
            .addOnSuccessListener { text ->
                val raw = text.text
                if (raw.isNotBlank()) {
                    tvOcr.text = raw
                    autoDetectAndTranslate(raw)
                } else {
                    recognizeLatin(image)
                }
            }
            .addOnFailureListener {
                recognizeLatin(image)
            }
    }

    private fun recognizeLatin(image: InputImage) {
        val latinRecognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS)
        latinRecognizer.process(image)
            .addOnSuccessListener { text ->
                val raw = text.text
                tvOcr.text = raw
                autoDetectAndTranslate(raw)
            }
            .addOnFailureListener { e ->
                Toast.makeText(this, "OCR 失败: ${e.message}", Toast.LENGTH_SHORT).show()
            }
    }

    private fun autoDetectAndTranslate(text: String) {
        if (text.isBlank()) return
        val identifier = languageIdentifier ?: return
        identifier.identifyLanguage(text)
            .addOnSuccessListener { code ->
                val source = if (code == "und") TranslateLanguage.CHINESE else mapLang(code)
                val target = TranslateLanguage.CHINESE
                setupTranslatorAndTranslate(source, target, text)
            }
            .addOnFailureListener {
                setupTranslatorAndTranslate(TranslateLanguage.ENGLISH, TranslateLanguage.CHINESE, text)
            }
    }

    private fun mapLang(bcp47: String): String {
        return try { TranslateLanguage.fromLanguageTag(bcp47) ?: TranslateLanguage.ENGLISH } catch (e: Exception) { TranslateLanguage.ENGLISH }
    }

    private fun setupTranslatorAndTranslate(source: String, target: String, text: String) {
        translator?.close()
        val options = TranslatorOptions.Builder()
            .setSourceLanguage(source)
            .setTargetLanguage(target)
            .build()
        translator = Translation.getClient(options)

        val conditions = DownloadConditions.Builder().build()
        translator!!.downloadModelIfNeeded(conditions)
            .addOnSuccessListener {
                translator!!.translate(text)
                    .addOnSuccessListener { out -> tvTrans.text = out }
                    .addOnFailureListener { e -> Toast.makeText(this, "翻译失败: ${e.message}", Toast.LENGTH_SHORT).show() }
            }
            .addOnFailureListener { e ->
                Toast.makeText(this, "翻译模型下载失败（需联网一次）: ${e.message}", Toast.LENGTH_LONG).show()
            }
    }

    override fun onDestroy() {
        super.onDestroy()
        translator?.close()
        cameraExecutor.shutdown()
    }
}