package com.recordatorios.app

import android.content.Context
import android.graphics.Bitmap
import androidx.core.content.ContextCompat
import android.graphics.Color
import android.view.View
import android.view.ViewGroup
import android.view.LayoutInflater
import android.view.animation.DecelerateInterpolator
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import com.recordatorios.app.databinding.ItemNoteBinding
import com.recordatorios.app.databinding.ItemSectionHeaderBinding
import java.lang.ref.WeakReference
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale

class NoteAdapter(
    private val onEdit: (Note) -> Unit,
    private val onDelete: (Note) -> Unit,
    private val onToggleComplete: (Note) -> Unit,
    private val onRestore: (Note) -> Unit,
    private val onPermanentDelete: (Note) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private var notes = mutableListOf<Note>()
    private var showDeleted = false
    private var categoryFilter: String? = null
    private var categories: List<Category> = emptyList()
    private val expandedIds = mutableSetOf<Long>()
    private var showTodaySection = false
    private var staggerPending = false
    private var rvRef: WeakReference<RecyclerView>? = null

    companion object {
        private const val TYPE_NOTE = 0
        private const val TYPE_HEADER = 1
    }

    private val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.getDefault())
    private val timeFormat = SimpleDateFormat("HH:mm", Locale.getDefault())
    private val headerDateFormat = SimpleDateFormat("EEEE dd/MM/yyyy", Locale.getDefault())

    init {
        setHasStableIds(true)
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        super.onAttachedToRecyclerView(recyclerView)
        rvRef = WeakReference(recyclerView)
    }

    override fun getItemId(position: Int): Long {
        if (!showTodaySection) return notes[position].id
        if (getItemViewType(position) == TYPE_HEADER) {
            return -1L - position
        }
        val note = getNoteAtPosition(position)
        return note.id
    }

    fun submitList(list: List<Note>, isTodayTab: Boolean = false, animate: Boolean = false) {
        showTodaySection = isTodayTab
        staggerPending = animate
        notes = list.toMutableList()
        notifyDataSetChanged()
        if (animate) {
            rvRef?.get()?.addOnLayoutChangeListener(object : View.OnLayoutChangeListener {
                override fun onLayoutChange(v: View, left: Int, top: Int, right: Int, bottom: Int,
                                            oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {
                    v.removeOnLayoutChangeListener(this)
                    performStaggerAnimation()
                }
            })
        }
    }

    fun setShowDeleted(show: Boolean) {
        if (showDeleted != show) {
            showDeleted = show
            expandedIds.clear()
        }
    }

    fun setCategories(cats: List<Category>) {
        categories = cats
    }

    override fun getItemCount(): Int {
        if (!showTodaySection) return notes.size
        val todayNotes = notes.filter { isToday(it) }
        val overdueNotes = notes.filter { !isToday(it) }
        return when {
            todayNotes.isNotEmpty() && overdueNotes.isNotEmpty() -> todayNotes.size + 1 + overdueNotes.size + 1
            todayNotes.isNotEmpty() -> todayNotes.size + 1
            overdueNotes.isNotEmpty() -> overdueNotes.size + 1
            else -> 0
        }
    }

    override fun getItemViewType(position: Int): Int {
        if (!showTodaySection) return TYPE_NOTE
        val todayNotes = notes.filter { isToday(it) }
        val overdueNotes = notes.filter { !isToday(it) }
        
        var currentIndex = 0
        if (todayNotes.isNotEmpty()) {
            if (position == currentIndex) return TYPE_HEADER
            currentIndex++
            if (position < currentIndex + todayNotes.size) return TYPE_NOTE
            currentIndex += todayNotes.size
        }
        if (overdueNotes.isNotEmpty()) {
            if (position == currentIndex) return TYPE_HEADER
            currentIndex++
            if (position < currentIndex + overdueNotes.size) return TYPE_NOTE
        }
        return TYPE_NOTE
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return if (viewType == TYPE_HEADER) {
            val binding = ItemSectionHeaderBinding.inflate(
                LayoutInflater.from(parent.context), parent, false
            )
            SectionHeaderViewHolder(binding)
        } else {
            val binding = ItemNoteBinding.inflate(
                LayoutInflater.from(parent.context), parent, false
            )
            NoteViewHolder(binding)
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if (holder is SectionHeaderViewHolder) {
            holder.bind(position)
        } else if (holder is NoteViewHolder) {
            holder.bind(getNoteAtPosition(position))
        }
    }

    override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
        super.onViewAttachedToWindow(holder)
        if (staggerPending) {
            val pos = holder.layoutPosition.coerceAtLeast(0)
            holder.itemView.alpha = 0f
            holder.itemView.translationY = 200f
            holder.itemView.animate()
                .alpha(1f)
                .translationY(0f)
                .translationZ(10f)
                .setDuration(500)
                .setStartDelay((pos * 100L).coerceAtMost(800L))
                .setInterpolator(DecelerateInterpolator())
                .withEndAction {
                    holder.itemView.translationZ = 0f
                }
                .start()
        }
    }

    override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
        super.onViewDetachedFromWindow(holder)
        holder.itemView.animate().cancel()
        holder.itemView.alpha = 1f
        holder.itemView.translationY = 0f
        holder.itemView.translationZ = 0f
    }

    private fun performStaggerAnimation() {
        staggerPending = false
        val rv = rvRef?.get() ?: return
        for (i in 0 until rv.childCount) {
            val child = rv.getChildAt(i)
            if (child.alpha < 0.01f) continue
            val holder = rv.getChildViewHolder(child)
            val pos = holder.layoutPosition.coerceAtLeast(0)
            child.alpha = 0f
            child.translationY = 200f
            child.animate()
                .alpha(1f)
                .translationY(0f)
                .translationZ(10f)
                .setDuration(500)
                .setStartDelay((pos * 100L).coerceAtMost(800L))
                .setInterpolator(DecelerateInterpolator())
                .withEndAction { child.translationZ = 0f }
                .start()
        }
    }

    private fun isToday(note: Note): Boolean {
        val todayStart = Calendar.getInstance().apply {
            set(Calendar.HOUR_OF_DAY, 0); set(Calendar.MINUTE, 0)
            set(Calendar.SECOND, 0); set(Calendar.MILLISECOND, 0)
        }.timeInMillis
        val todayEnd = todayStart + 86400000L
        return note.reminderDate != null && note.reminderDate!! >= todayStart && note.reminderDate!! < todayEnd
    }

    private fun getNoteAtPosition(position: Int): Note {
        if (!showTodaySection) return notes[position]
        val todayNotes = notes.filter { isToday(it) }
        val overdueNotes = notes.filter { !isToday(it) }
        
        var currentIndex = 0
        if (todayNotes.isNotEmpty()) {
            currentIndex++ // skip header
            if (position < currentIndex + todayNotes.size) {
                return todayNotes[position - currentIndex]
            }
            currentIndex += todayNotes.size
        }
        if (overdueNotes.isNotEmpty()) {
            currentIndex++ // skip header
            if (position < currentIndex + overdueNotes.size) {
                return overdueNotes[position - currentIndex]
            }
        }
        return notes.firstOrNull() ?: notes[0]
    }

    inner class SectionHeaderViewHolder(private val binding: ItemSectionHeaderBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(position: Int) {
            val todayNotes = notes.filter { isToday(it) }
            if (todayNotes.isNotEmpty() && position == 0) {
                binding.textSectionTitle.text = "Hoy"
                binding.textSectionDate.text = headerDateFormat.format(Date(System.currentTimeMillis()))
                binding.textSectionDate.visibility = View.VISIBLE
            } else {
                binding.textSectionTitle.text = "Vencidos"
                binding.textSectionDate.visibility = View.GONE
            }
        }
    }

    inner class NoteViewHolder(private val binding: ItemNoteBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(note: Note) {
            binding.textTitle.text = note.title.ifBlank { "Sin t\u00edtulo" }
            val ta = binding.root.context.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColorPrimary))
            binding.textTitle.setTextColor(ta.getColor(0, Color.WHITE))
            ta.recycle()

            val cat = categories.find { it.id == note.category }
            if (cat != null) {
                binding.categoryDot.visibility = View.VISIBLE
                binding.categoryDot.setBackgroundResource(R.drawable.circle_category)
                binding.categoryDot.background.setTint(cat.color)
                binding.root.strokeColor = cat.color
                binding.root.strokeWidth = 4
            } else {
                binding.categoryDot.visibility = View.GONE
                binding.root.strokeColor = Color.TRANSPARENT
                binding.root.strokeWidth = 0
            }

            if (note.reminderDate != null) {
                binding.textDate.text = dateFormat.format(Date(note.reminderDate!!))
                binding.textDate.visibility = View.VISIBLE
            } else {
                binding.textDate.visibility = View.GONE
            }

            val isExpanded = expandedIds.contains(note.id)
            binding.btnExpand.rotation = if (isExpanded) 180f else 0f
            val toggleExpand = {
                if (expandedIds.contains(note.id)) expandedIds.remove(note.id)
                else expandedIds.add(note.id)
                notifyItemChanged(layoutPosition)
            }
            binding.btnExpand.setOnClickListener { toggleExpand() }
            binding.textTitle.setOnClickListener { toggleExpand() }

            if (showDeleted) {
                binding.btnMarkComplete.visibility = View.GONE
                binding.chipRecurrence.visibility = View.GONE
                binding.textTitle.alpha = 0.5f
                binding.root.alpha = 1.0f

                binding.textContent.visibility = View.VISIBLE
                binding.textReminder.visibility = View.GONE

                binding.detailsSection.visibility = if (isExpanded) View.VISIBLE else View.GONE
                binding.textContent.text = note.content.ifBlank { "Sin contenido" }

                binding.btnEdit.visibility = View.GONE
                binding.btnDelete.visibility = View.GONE
                binding.btnRestore.visibility = View.VISIBLE
                binding.btnPermanentDelete.visibility = View.VISIBLE
                binding.btnMarkComplete.setOnClickListener { onToggleComplete(note) }
                binding.btnEdit.setOnClickListener { onEdit(note) }
                binding.btnDelete.setOnClickListener { onDelete(note) }

                binding.btnRestore.setOnClickListener { onRestore(note) }
                binding.btnPermanentDelete.setOnClickListener { onPermanentDelete(note) }

                hidePhoto()
            } else {
                binding.btnMarkComplete.visibility = View.VISIBLE
                binding.btnEdit.visibility = View.VISIBLE
                binding.btnDelete.visibility = View.VISIBLE
                binding.btnRestore.visibility = View.GONE
                binding.btnPermanentDelete.visibility = View.GONE
                binding.textTitle.alpha = 1.0f

                binding.detailsSection.visibility = if (isExpanded) View.VISIBLE else View.GONE

                binding.btnMarkComplete.alpha =
                    if (note.isCompleted) 1.0f else 0.5f
                binding.root.alpha = if (note.isCompleted) 0.4f else 1.0f

                binding.textContent.text = note.content.ifBlank { "Sin contenido" }

                if (note.reminderDate != null) {
                    val timeStr = timeFormat.format(Date(note.reminderDate!!))
                    binding.textReminder.text = "$timeStr"
                    binding.textReminder.visibility = View.VISIBLE
                    binding.textReminder.setCompoundDrawablesWithIntrinsicBounds(
                        com.recordatorios.app.R.drawable.ic_bell, 0, 0, 0
                    )
                    binding.textReminder.compoundDrawablePadding = 6

                    binding.chipRecurrence.visibility = View.VISIBLE
                    binding.chipRecurrence.text = when (note.recurrence) {
                        RecurrenceType.DAILY -> "Diario"
                        RecurrenceType.WEEKLY -> "Semanal"
                        RecurrenceType.MONTHLY -> "Mensual"
                        RecurrenceType.YEARLY -> "Anual"
                        RecurrenceType.NONE -> null
                    }
                    if (note.recurrence == RecurrenceType.NONE) {
                        binding.chipRecurrence.visibility = View.GONE
                    }
                } else {
                    binding.textReminder.visibility = View.GONE
                    binding.chipRecurrence.visibility = View.GONE
                }

                binding.btnMarkComplete.setOnClickListener { onToggleComplete(note) }
                binding.btnEdit.setOnClickListener { onEdit(note) }
                binding.btnDelete.setOnClickListener { onDelete(note) }

                loadPhoto(note.photoPath)
            }
        }

        private fun loadPhoto(photoPath: String) {
            if (photoPath.isBlank()) {
                hidePhoto()
                return
            }
            val ctx = binding.root.context
            val blurred = PhotoUtils.loadBlurredBitmap(ctx, photoPath)
            if (blurred != null) {
                binding.ivPhotoBlur.setImageBitmap(blurred)
                binding.ivPhotoBlur.visibility = View.VISIBLE
                binding.photoScrim.visibility = View.VISIBLE
                val isDark = (ctx.resources.configuration.uiMode and android.content.res.Configuration.UI_MODE_NIGHT_MASK) == android.content.res.Configuration.UI_MODE_NIGHT_YES
                binding.photoScrim.setBackgroundColor(if (isDark) 0x44000000.toInt() else 0x55FFFFFF.toInt())
            } else {
                hidePhoto()
            }
        }

        private fun hidePhoto() {
            binding.ivPhotoBlur.visibility = View.GONE
            binding.photoScrim.visibility = View.GONE
            binding.ivPhotoBlur.setImageBitmap(null)
        }
    }
}
