package com.rugvedsarika.docscan.ui.home
import androidx.activity.OnBackPressedCallback

import android.app.Activity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.result.IntentSenderRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import com.google.mlkit.vision.documentscanner.GmsDocumentScannerOptions
import com.google.mlkit.vision.documentscanner.GmsDocumentScannerOptions.*
import com.google.mlkit.vision.documentscanner.GmsDocumentScanning
import com.google.mlkit.vision.documentscanner.GmsDocumentScanningResult
import com.rugvedsarika.docscan.data.entity.Document
import com.rugvedsarika.docscan.databinding.FragmentHomeBinding
import com.rugvedsarika.docscan.ui.adapter.DocumentAdapter
import com.rugvedsarika.docscan.util.SecurityManager
import com.rugvedsarika.docscan.viewmodel.MainViewModel
import kotlinx.coroutines.launch
import java.io.File
import java.io.FileOutputStream
import java.text.SimpleDateFormat

class HomeFragment : Fragment() {

    private var _binding: FragmentHomeBinding? = null
    private val binding get() = _binding!!

    private val viewModel: MainViewModel by viewModels()
    private lateinit var adapter: DocumentAdapter

    private val backPressedCallback = object : OnBackPressedCallback(false) {
        override fun handleOnBackPressed() {
            stopSelectionMode()
        }
    }

    private val scannerLauncher = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            val scanningResult = GmsDocumentScanningResult.fromActivityResultIntent(result.data)
            scanningResult?.let { handleScanningResult(it) }
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentHomeBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        setupRecyclerView()
        setupSearchView()
        setupFAB()
        observeDocuments()
        
        requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backPressedCallback)
    }

    private fun setupSearchView() {
        binding.searchView.setOnQueryTextListener(object : androidx.appcompat.widget.SearchView.OnQueryTextListener {
            override fun onQueryTextSubmit(query: String?): Boolean {
                viewModel.setSearchQuery(query ?: "")
                return true
            }

            override fun onQueryTextChange(newText: String?): Boolean {
                viewModel.setSearchQuery(newText ?: "")
                return true
            }
        })
    }

    private fun setupRecyclerView() {
        adapter = DocumentAdapter(
            onDocumentClick = { document ->
                if (document.isLocked) {
                    SecurityManager.authenticate(
                        requireActivity(),
                        onSuccess = {
                            val action = HomeFragmentDirections.actionHomeFragmentToPreviewFragment(document)
                            findNavController().navigate(action)
                        },
                        onError = { error ->
                            Toast.makeText(context, "Authentication failed: $error", Toast.LENGTH_SHORT).show()
                        }
                    )
                } else {
                    val action = HomeFragmentDirections.actionHomeFragmentToPreviewFragment(document)
                    findNavController().navigate(action)
                }
            },
            onMoreClick = { view, document ->
                showDocumentMenu(view, document)
            },
            onLongClick = { document ->
                startSelectionMode()
            },
            onSelectionChanged = { count ->
                updateSelectionUI(count)
            }
        )
        binding.rvDocuments.layoutManager = GridLayoutManager(context, 2)
        binding.rvDocuments.adapter = adapter
    }

    private fun startSelectionMode() {
        adapter.isSelectionMode = true
        backPressedCallback.isEnabled = true
        binding.toolbar.title = "0 Selected"
        binding.toolbar.navigationIcon = ContextCompat.getDrawable(requireContext(), android.R.drawable.ic_menu_close_clear_cancel)
        binding.toolbar.setNavigationOnClickListener { stopSelectionMode() }
        
        binding.toolbar.menu.clear()
        binding.toolbar.menu.add(0, 1, 0, "Merge").setShowAsAction(android.view.MenuItem.SHOW_AS_ACTION_ALWAYS)
        binding.toolbar.menu.add(0, 2, 1, "Export").setShowAsAction(android.view.MenuItem.SHOW_AS_ACTION_ALWAYS)
        binding.toolbar.menu.add(0, 3, 2, "Delete")
            .setIcon(android.R.drawable.ic_menu_delete)
            .setShowAsAction(android.view.MenuItem.SHOW_AS_ACTION_ALWAYS)
        
        binding.toolbar.setOnMenuItemClickListener { item ->
            val selectedDocs = adapter.getSelectedDocuments()
            when (item.itemId) {
                1 -> {
                    if (selectedDocs.size >= 2) {
                        viewModel.mergeDocuments("Merged Document", selectedDocs)
                        stopSelectionMode()
                    } else {
                        Toast.makeText(context, "Select at least 2 documents", Toast.LENGTH_SHORT).show()
                    }
                }
                2 -> {
                    if (selectedDocs.isNotEmpty()) {
                        showExportOptions(selectedDocs)
                    }
                }
                3 -> {
                    if (selectedDocs.isNotEmpty()) {
                        showDeleteConfirmation(selectedDocs)
                    }
                }
            }
            true
        }
    }

    private fun showDeleteConfirmation(documents: List<Document>) {
        android.app.AlertDialog.Builder(requireContext())
            .setTitle("Delete Documents")
            .setMessage("Are you sure you want to delete ${documents.size} document(s)?")
            .setPositiveButton("Delete") { _, _ ->
                viewModel.deleteDocuments(documents)
                Toast.makeText(context, "${documents.size} deleted", Toast.LENGTH_SHORT).show()
                if (adapter.isSelectionMode) {
                    stopSelectionMode()
                }
            }
            .setNegativeButton("Cancel", null)
            .show()
    }

    private fun showExportOptions(documents: List<Document>) {
        val options = arrayOf("Export as PDF", "Export as Text (OCR)", "Export as ZIP", "Save to Gallery")
        android.app.AlertDialog.Builder(requireContext())
            .setTitle("Export Options")
            .setItems(options) { _, which ->
                when (which) {
                    0 -> exportAsPdf(documents)
                    1 -> exportAsText(documents)
                    2 -> batchExportZip(documents)
                    3 -> exportToGallery(documents)
                }
                stopSelectionMode()
            }.show()
    }

    private fun exportAsPdf(documents: List<Document>) {
        lifecycleScope.launch {
            val pdfFile = File(requireContext().cacheDir, "Export_${System.currentTimeMillis()}.pdf")
            viewModel.generatePdfFile(documents, pdfFile)
            shareFile(pdfFile, "application/pdf")
        }
    }

    private fun exportAsText(documents: List<Document>) {
        lifecycleScope.launch {
            val text = viewModel.getFullTextForDocuments(documents)
            val textFile = File(requireContext().cacheDir, "Export_${System.currentTimeMillis()}.txt")
            textFile.writeText(text)
            shareFile(textFile, "text/plain")
        }
    }

    private fun exportToGallery(documents: List<Document>) {
        lifecycleScope.launch {
            val picturesDir = File(android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_PICTURES), "DocScan")
            if (!picturesDir.exists()) picturesDir.mkdirs()

            documents.forEach { doc ->
                val pages = viewModel.getPagesListForDocument(doc.id)
                pages.forEachIndexed { index, page ->
                    val outFile = File(picturesDir, "${doc.name}_${index + 1}.jpg")
                    File(page.imagePath).copyTo(outFile, overwrite = true)
                    
                    // Trigger media scanner
                    android.media.MediaScannerConnection.scanFile(requireContext(), arrayOf(outFile.absolutePath), null, null)
                }
            }
            Toast.makeText(context, "Saved to Pictures/DocScan", Toast.LENGTH_SHORT).show()
        }
    }

    private fun batchExportZip(documents: List<Document>) {
        lifecycleScope.launch {
            val zipFile = File(requireContext().cacheDir, "Export_${System.currentTimeMillis()}.zip")
            java.util.zip.ZipOutputStream(java.io.FileOutputStream(zipFile)).use { zos ->
                documents.forEach { doc ->
                    val pages = viewModel.getPagesListForDocument(doc.id)
                    pages.forEachIndexed { index, page ->
                        val entry = java.util.zip.ZipEntry("${doc.name}/page_${index + 1}.jpg")
                        zos.putNextEntry(entry)
                        File(page.imagePath).inputStream().use { it.copyTo(zos) }
                        zos.closeEntry()
                    }
                }
            }
            shareFile(zipFile, "application/zip")
        }
    }

    private fun shareFile(file: File, mimeType: String) {
        val uri = androidx.core.content.FileProvider.getUriForFile(
            requireContext(),
            "${requireActivity().packageName}.provider",
            file
        )
        val intent = android.content.Intent(android.content.Intent.ACTION_SEND).apply {
            type = mimeType
            putExtra(android.content.Intent.EXTRA_STREAM, uri)
            addFlags(android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION)
        }
        startActivity(android.content.Intent.createChooser(intent, "Share File"))
    }

    private fun stopSelectionMode() {
        adapter.isSelectionMode = false
        backPressedCallback.isEnabled = false
        binding.toolbar.title = "DocScan"
        binding.toolbar.navigationIcon = null
        binding.toolbar.menu.clear()
        setupToolbar() // Restore original toolbar
    }

    private fun setupToolbar() {
        binding.toolbar.title = "DocScan"
        binding.toolbar.setNavigationOnClickListener(null)
        
        binding.toolbar.menu.clear()
        val themeItem = binding.toolbar.menu.add(0, 101, 0, "Theme")
        themeItem.setShowAsAction(android.view.MenuItem.SHOW_AS_ACTION_ALWAYS)
        // Set icon programmatically or via XML if possible, here using a helper or just text if icon resource is ready
        // Since we created ic_theme.xml, let's use it. We need to get the drawable.
        themeItem.icon = ContextCompat.getDrawable(requireContext(), com.rugvedsarika.docscan.R.drawable.ic_theme)
        
        binding.toolbar.setOnMenuItemClickListener { item ->
            if (item.itemId == 101) {
                showThemeSelectionDialog()
                true
            } else {
                false
            }
        }
    }

    private fun showThemeSelectionDialog() {
        val themes = arrayOf("System Default", "Light", "Dark")
        val checkedItem = when (androidx.appcompat.app.AppCompatDelegate.getDefaultNightMode()) {
            androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO -> 1
            androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES -> 2
            else -> 0
        }

        android.app.AlertDialog.Builder(requireContext())
            .setTitle("Choose Theme")
            .setSingleChoiceItems(themes, checkedItem) { dialog, which ->
                val mode = when (which) {
                    0 -> androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
                    1 -> androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
                    2 -> androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
                    else -> androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
                }
                
                // Save preference
                val sharedPreferences = requireActivity().getSharedPreferences("DocScanPrefs", android.content.Context.MODE_PRIVATE)
                with(sharedPreferences.edit()) {
                    putInt("night_mode", mode)
                    apply()
                }
                
                // Apply theme
                androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode(mode)
                dialog.dismiss()
            }
            .setNegativeButton("Cancel", null)
            .show()
    }

    private fun updateSelectionUI(count: Int) {
        binding.toolbar.title = "$count Selected"
    }

    private fun showDocumentMenu(view: View, document: Document) {
        val popup = android.widget.PopupMenu(context, view)
        popup.menu.add(0, 1, 0, "Delete")
        popup.menu.add(0, 2, 1, if (document.isLocked) "Unlock" else "Lock")
        popup.menu.add(0, 3, 2, "Export")
        
        popup.setOnMenuItemClickListener { item ->
            when (item.itemId) {
                1 -> showDeleteConfirmation(listOf(document))
                2 -> viewModel.toggleLock(document)
                3 -> showExportOptions(listOf(document))
            }
            true
        }
        popup.show()
    }

    private fun setupFAB() {
        binding.fabScan.setOnClickListener {
            startScan()
        }
    }

    private fun startScan() {
        val options = GmsDocumentScannerOptions.Builder()
            .setScannerMode(SCANNER_MODE_FULL)
            .setResultFormats(RESULT_FORMAT_JPEG, RESULT_FORMAT_PDF)
            .setGalleryImportAllowed(true)
            .build()

        val scanner = GmsDocumentScanning.getClient(options)
        
        scanner.getStartScanIntent(requireActivity())
            .addOnSuccessListener { intentSender ->
                scannerLauncher.launch(IntentSenderRequest.Builder(intentSender).build())
            }
            .addOnFailureListener { e ->
                Toast.makeText(context, "Error starting scanner: ${e.message}", Toast.LENGTH_SHORT).show()
            }
    }

    private fun handleScanningResult(result: GmsDocumentScanningResult) {
        val pages = result.pages
        lifecycleScope.launch {
            val imagePaths = mutableListOf<String>()
            pages?.forEachIndexed { index, page ->
                val uri = page.imageUri
                val fileName = "scan_${System.currentTimeMillis()}_$index.jpg"
                val file = File(requireContext().filesDir, fileName)
                requireContext().contentResolver.openInputStream(uri)?.use { input ->
                    FileOutputStream(file).use { output ->
                        input.copyTo(output)
                    }
                }
                imagePaths.add(file.absolutePath)
            }

            if (imagePaths.isNotEmpty()) {
                val docName = "Scan ${SimpleDateFormat("yyyy-MM-dd HH:mm", java.util.Locale.getDefault()).format(java.util.Date())}"
                viewModel.insertDocument(docName, imagePaths)
            }
        }
    }

    private fun observeDocuments() {
        lifecycleScope.launch {
            viewModel.allDocuments.collect { documents ->
                adapter.submitList(documents)
                binding.emptyState.visibility = if (documents.isEmpty()) View.VISIBLE else View.GONE
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}
