package com.seyalix.hr.ui.notifications

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.CheckBox
import android.widget.ImageButton
import android.widget.ListView
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.seyalix.hr.R
import com.seyalix.hr.api.ApiClient
import com.seyalix.hr.models.AppNotification
import kotlinx.coroutines.launch

class NotificationsFragment : Fragment() {

    // FIX (15 Jul 2026): this screen now behaves like an "unread inbox" —
    // it only shows unread notifications. Checking a row's checkbox marks
    // that one as read and it disappears from the list immediately;
    // "Mark all read" marks everything as read and clears the whole list.
    // (Marking something back to unread from here doesn't apply anymore
    // since read items aren't shown — there's nothing left to uncheck.)
    private val items = mutableListOf<AppNotification>()
    private lateinit var adapter: ArrayAdapter<AppNotification>

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
        inflater.inflate(R.layout.fragment_notifications, container, false)

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

        view.findViewById<ImageButton>(R.id.btnBack).setOnClickListener {
            parentFragmentManager.popBackStack()
        }

        view.findViewById<TextView>(R.id.btnMarkAllRead).setOnClickListener {
            lifecycleScope.launch {
                try {
                    ApiClient.apiService.markAllNotificationsRead(mapOf())
                    // FIX: everything just got marked read -> the unread
                    // list is now empty, clear it immediately rather than
                    // waiting for the next reload.
                    items.clear()
                    adapter.notifyDataSetChanged()
                    updateEmptyState(view)
                } catch (_: Exception) { }
            }
        }

        view.findViewById<TextView?>(R.id.btnMarkAllUnread)?.setOnClickListener {
            lifecycleScope.launch {
                try {
                    ApiClient.apiService.markAllNotificationsUnread(mapOf())
                    // Marking everything unread means the full backlog
                    // should now show up here — reload from the server.
                    loadNotifications(view)
                } catch (_: Exception) { }
            }
        }

        setupList(view)
        loadNotifications(view)
    }

    private fun setupList(view: View) {
        adapter = object : ArrayAdapter<AppNotification>(requireContext(), 0, items) {
            // FIX (15 Jul 2026): ArrayAdapter keeps its own internal COPY
            // of the list passed to its constructor — mutating `items`
            // externally (remove-on-read, clear-on-mark-all) would not
            // actually change what the adapter thinks it has, causing
            // stale/mismatched rows. Overriding these two makes the
            // adapter always read live from `items` instead.
            override fun getCount(): Int = items.size
            override fun getItem(position: Int): AppNotification = items[position]

            override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
                val row = convertView ?: layoutInflater.inflate(R.layout.item_notification_row, parent, false)
                val n = items[position]
                row.findViewById<TextView>(R.id.tvNotifTitle).text = n.title
                row.findViewById<TextView>(R.id.tvNotifMessage).text = n.message
                row.findViewById<TextView>(R.id.tvNotifTime).text = n.createdAt
                row.findViewById<View>(R.id.vUnreadDot).visibility =
                    if (n.isRead == 0) View.VISIBLE else View.INVISIBLE

                val checkbox = row.findViewById<CheckBox>(R.id.cbNotifRead)
                // Clear any listener from a recycled row before setting
                // checked state, so we don't fire a stale mark_read call.
                checkbox.setOnCheckedChangeListener(null)
                checkbox.isChecked = n.isRead != 0
                checkbox.setOnCheckedChangeListener { _, isChecked ->
                    if (isChecked) markReadAndRemove(view, n)
                    else markUnread(view, n)
                }
                return row
            }
        }
        view.findViewById<ListView>(R.id.lvNotifications).adapter = adapter
    }

    // FIX (15 Jul 2026): checking the box marks it read on the server AND
    // removes it from this unread list right away — this is the
    // "disappear once marked read" behavior that was asked for.
    private fun markReadAndRemove(view: View, n: AppNotification) {
        lifecycleScope.launch {
            try {
                ApiClient.apiService.markNotificationRead(mapOf("notification_id" to n.id.toString()))
                items.remove(n)
                adapter.notifyDataSetChanged()
                updateEmptyState(view)
            } catch (_: Exception) { }
        }
    }

    private fun markUnread(view: View, n: AppNotification) {
        lifecycleScope.launch {
            try {
                ApiClient.apiService.markNotificationUnread(mapOf("notification_id" to n.id.toString()))
                // It's already visible in this list (unread items only) —
                // just refresh the dot/state, no need to reload from server.
                adapter.notifyDataSetChanged()
            } catch (_: Exception) { }
        }
    }

    private fun loadNotifications(view: View) {
        lifecycleScope.launch {
            try {
                val resp = ApiClient.apiService.getNotifications()
                if (resp.isSuccessful && resp.body()?.success == true) {
                    val all = resp.body()!!.data ?: emptyList()
                    activity?.runOnUiThread {
                        items.clear()
                        // Only show unread ones — this screen is an unread inbox.
                        items.addAll(all.filter { it.isRead == 0 })
                        adapter.notifyDataSetChanged()
                        updateEmptyState(view)
                    }
                }
            } catch (_: Exception) { }
        }
    }

    private fun updateEmptyState(view: View) {
        view.findViewById<TextView>(R.id.tvEmptyNotifications).visibility =
            if (items.isEmpty()) View.VISIBLE else View.GONE
    }
}
