package com.seyalix.hr.ui.approvals

import android.os.Bundle
import android.view.*
import android.widget.*
import androidx.appcompat.app.AlertDialog
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.*
import com.seyalix.hr.utils.PrefsManager
import kotlinx.coroutines.launch
import kotlinx.coroutines.CancellationException

/**
 * Approval hierarchy:
 *
 *  EMPLOYEE  → applies (leave / permission / late) → goes to their MANAGER (HEAD)
 *  MANAGER   → approves team's requests            → HEAD sees own team only
 *  HR        → approves everything from managers   → SENIOR HEAD
 *  ADMIN     → approves everything org-wide        → MANAGEMENT
 *  SUPERADMIN→ approves everything org-wide        → MANAGEMENT
 *
 * This single fragment adapts based on role.
 */
class ApprovalsFragment : Fragment() {

    private lateinit var prefs: PrefsManager

    // Pending data
    private val pendingLeaves       = mutableListOf<LeaveApplication>()
    private val pendingPermissions  = mutableListOf<PermissionRecord>()
    private val pendingLateMarks    = mutableListOf<LateMarkRecord>()
    private val pendingMusterMods   = mutableListOf<MusterModificationRecord>()
    private val pendingOnDuty       = mutableListOf<OnDutyRequest>()

    override fun onCreateView(inflater: LayoutInflater, c: ViewGroup?, s: Bundle?): View? =
        inflater.inflate(R.layout.fragment_approvals, c, false)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        prefs = PrefsManager(requireContext())

        val tvTitle = view.findViewById<TextView>(R.id.tvApprovalTitle)
        tvTitle.text = when {
            prefs.isManagement() -> "Management – All Pending Approvals"
            prefs.isSeniorHead() -> "Senior Head – Org-wide Approvals"
            prefs.isManager()    -> "Head – Team Approvals"
            else                 -> "Approvals"
        }

        // Tab buttons
        view.findViewById<Button>(R.id.btnTabLeaves).setOnClickListener     { showLeaves(view) }
        view.findViewById<Button>(R.id.btnTabPermissions).setOnClickListener { showPermissions(view) }
        view.findViewById<Button>(R.id.btnTabLate).setOnClickListener        { showLateMarks(view) }
        view.findViewById<Button>(R.id.btnTabMuster).setOnClickListener      { showMusterMods(view) }
        view.findViewById<Button>(R.id.btnTabOnDuty).setOnClickListener      { showOnDuty(view) }

        loadAll()
        showLeaves(view)
    }

    // ── Load all pending based on role ─────────────────────────
    private fun loadAll() {
        lifecycleScope.launch {
            try {
                // Leave
                val leaveResp = if (prefs.isManagement())
                    ApiClient.apiService.getAllPendingApprovals()
                else
                    ApiClient.apiService.getPendingApprovals()

                if (!prefs.isManagement()) {
                    val resp = ApiClient.apiService.getPendingApprovals()
                    if (resp.isSuccessful && resp.body()?.success == true) {
                        pendingLeaves.clear()
                        pendingLeaves.addAll(resp.body()!!.data ?: emptyList())
                    }
                }

                // Permissions
                val permResp = ApiClient.apiService.getPendingPermissions()
                if (permResp.isSuccessful && permResp.body()?.success == true) {
                    pendingPermissions.clear()
                    pendingPermissions.addAll(permResp.body()!!.data ?: emptyList())
                }

                // Late marks
                val lateResp = ApiClient.apiService.getPendingLateMarks()
                if (lateResp.isSuccessful && lateResp.body()?.success == true) {
                    pendingLateMarks.clear()
                    pendingLateMarks.addAll(lateResp.body()!!.data ?: emptyList())
                }

                // Muster modifications
                val musterResp = ApiClient.apiService.getPendingMusterModifications()
                if (musterResp.isSuccessful && musterResp.body()?.success == true) {
                    pendingMusterMods.clear()
                    pendingMusterMods.addAll(musterResp.body()!!.data ?: emptyList())
                }

                // On Duty
                val onDutyResp = ApiClient.apiService.getPendingOnDuty()
                if (onDutyResp.isSuccessful && onDutyResp.body()?.success == true) {
                    pendingOnDuty.clear()
                    pendingOnDuty.addAll(onDutyResp.body()!!.data ?: emptyList())
                }

                // Update badge counts
                activity?.runOnUiThread {
                    view?.let { v ->
                        v.findViewById<Button>(R.id.btnTabLeaves)?.text      = "Leave (${pendingLeaves.size})"
                        v.findViewById<Button>(R.id.btnTabPermissions)?.text = "Permission (${pendingPermissions.size})"
                        v.findViewById<Button>(R.id.btnTabLate)?.text        = "Late (${pendingLateMarks.size})"
                        v.findViewById<Button>(R.id.btnTabMuster)?.text      = "Muster (${pendingMusterMods.size})"
                        v.findViewById<Button>(R.id.btnTabOnDuty)?.text      = "On Duty (${pendingOnDuty.size})"
                    }
                }
            } catch (_: Exception) {}
        }
    }

    // ── Leaves ────────────────────────────────────────────────
    private fun showLeaves(view: View) {
        val lv = view.findViewById<ListView>(R.id.lvApprovals)
        val items = pendingLeaves.map { l ->
            buildString {
                append("${l.firstName ?: ""} ${l.lastName ?: ""} (${l.empCode ?: ""})\n")
                append("${l.leaveTypeName}  ${l.startDate} → ${l.endDate}  (${l.days.toInt()}d)\n")
                append("Reason: ${l.reason}")
            }
        }
        lv.adapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, items)
        lv.setOnItemClickListener { _, _, pos, _ ->
            showLeaveApprovalDialog(pendingLeaves[pos])
        }
    }

    private fun showLeaveApprovalDialog(leave: LeaveApplication) {
        val ctx = requireContext()
        val etRemarks = EditText(ctx).apply { hint = "Remarks (optional)" }
        AlertDialog.Builder(ctx)
            .setTitle("${leave.firstName} ${leave.lastName} – ${leave.leaveTypeName}")
            .setMessage("${leave.startDate} to ${leave.endDate} (${leave.days.toInt()} days)\nReason: ${leave.reason}")
            .setView(etRemarks)
            .setPositiveButton("Approve") { _, _ -> processLeave(leave.id, "approved", etRemarks.text.toString()) }
            .setNegativeButton("Reject")  { _, _ -> processLeave(leave.id, "rejected", etRemarks.text.toString()) }
            .setNeutralButton("Cancel", null)
            .show()
    }

    private fun processLeave(id: Int, status: String, remarks: String) {
        val action  = if (prefs.isManagement()) "management_approve" else "approve_leave"
        lifecycleScope.launch {
            try {
                val body = mapOf(
                    "application_id" to id.toString(),
                    "type"           to "leave",
                    "status"         to status,
                    "remarks"        to remarks
                )
                val resp = if (prefs.isManagement())
                    ApiClient.apiService.managementApprove(body)
                else
                    ApiClient.apiService.approveLeave(body)

                val msg = resp.body()?.message ?: "Done"
                Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
                pendingLeaves.removeAll { it.id == id }
                view?.let { showLeaves(it) }
            } catch (e: CancellationException) {
                throw e  // normal when the screen changes mid-request — not a real error
            } catch (e: Exception) {
                Toast.makeText(context, "Error: ${e.message}", Toast.LENGTH_SHORT).show()
            }
        }
    }

    // ── Permissions ───────────────────────────────────────────
    private fun showPermissions(view: View) {
        val lv = view.findViewById<ListView>(R.id.lvApprovals)
        val items = pendingPermissions.map { p ->
            buildString {
                append("${p.firstName ?: ""} ${p.lastName ?: ""} (${p.empCode ?: ""})\n")
                append("Date: ${p.permissionDate}  ${p.fromTime} → ${p.toTime}  (${p.durationMinutes}min)\n")
                append("Reason: ${p.reason}")
            }
        }
        lv.adapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, items)
        lv.setOnItemClickListener { _, _, pos, _ ->
            showPermissionApprovalDialog(pendingPermissions[pos])
        }
    }

    private fun showPermissionApprovalDialog(perm: PermissionRecord) {
        val ctx = requireContext()
        val etRemarks = EditText(ctx).apply { hint = "Remarks (optional)" }
        AlertDialog.Builder(ctx)
            .setTitle("${perm.firstName} ${perm.lastName} – Permission")
            .setMessage("${perm.permissionDate}  ${perm.fromTime} → ${perm.toTime}\nReason: ${perm.reason}")
            .setView(etRemarks)
            .setPositiveButton("Approve") { _, _ -> processPermission(perm.id, "approved", etRemarks.text.toString()) }
            .setNegativeButton("Reject")  { _, _ -> processPermission(perm.id, "rejected", etRemarks.text.toString()) }
            .setNeutralButton("Cancel", null)
            .show()
    }

    private fun processPermission(id: Int, status: String, remarks: String) {
        lifecycleScope.launch {
            try {
                val body = mapOf("request_id" to id.toString(), "status" to status, "remarks" to remarks)
                val resp = if (prefs.isManagement())
                    ApiClient.apiService.managementApprove(body + mapOf("type" to "permission"))
                else
                    ApiClient.apiService.approvePermission(body)
                Toast.makeText(context, resp.body()?.message ?: "Done", Toast.LENGTH_SHORT).show()
                pendingPermissions.removeAll { it.id == id }
                view?.let { showPermissions(it) }
            } catch (e: CancellationException) {
                throw e  // normal when the screen changes mid-request — not a real error
            } catch (e: Exception) {
                Toast.makeText(context, "Error: ${e.message}", Toast.LENGTH_SHORT).show()
            }
        }
    }

    // ── Late Marks ─────────────────────────────────────────────
    private fun showLateMarks(view: View) {
        val lv = view.findViewById<ListView>(R.id.lvApprovals)
        val items = pendingLateMarks.map { l ->
            buildString {
                append("${l.firstName ?: ""} ${l.lastName ?: ""} (${l.empCode ?: ""})\n")
                append("Date: ${l.date}  Late by: ${l.lateMinutes} min\n")
                append("Reason: ${l.reason}")
            }
        }
        lv.adapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, items)
        lv.setOnItemClickListener { _, _, pos, _ ->
            showLateApprovalDialog(pendingLateMarks[pos])
        }
    }

    private fun showLateApprovalDialog(late: LateMarkRecord) {
        val ctx = requireContext()
        val etRemarks = EditText(ctx).apply { hint = "Remarks (optional)" }
        AlertDialog.Builder(ctx)
            .setTitle("${late.firstName} ${late.lastName} – Late Mark")
            .setMessage("Date: ${late.date}  |  Late by ${late.lateMinutes} min\nReason: ${late.reason}")
            .setView(etRemarks)
            .setPositiveButton("Approve") { _, _ -> processLate(late.id, "approved", etRemarks.text.toString()) }
            .setNegativeButton("Reject")  { _, _ -> processLate(late.id, "rejected", etRemarks.text.toString()) }
            .setNeutralButton("Cancel", null)
            .show()
    }

    private fun processLate(id: Int, status: String, remarks: String) {
        lifecycleScope.launch {
            try {
                val body = mapOf("late_id" to id.toString(), "status" to status, "remarks" to remarks)
                val resp = if (prefs.isManagement())
                    ApiClient.apiService.managementApprove(body + mapOf("type" to "late"))
                else
                    ApiClient.apiService.approveLateMarks(body)
                Toast.makeText(context, resp.body()?.message ?: "Done", Toast.LENGTH_SHORT).show()
                pendingLateMarks.removeAll { it.id == id }
                view?.let { showLateMarks(it) }
            } catch (e: CancellationException) {
                throw e  // normal when the screen changes mid-request — not a real error
            } catch (e: Exception) {
                Toast.makeText(context, "Error: ${e.message}", Toast.LENGTH_SHORT).show()
            }
        }
    }

    // ── Muster Modifications ─────────────────────────────────────
    private val musterIssueLabels = mapOf(
        "forgot_signin" to "Forgot to Sign In",
        "forgot_signout" to "Forgot to Sign Out",
        "network_issue" to "Network Issue",
        "system_problem" to "System Problem",
        "others" to "Others"
    )

    private fun showMusterMods(view: View) {
        val lv = view.findViewById<ListView>(R.id.lvApprovals)
        val items = pendingMusterMods.map { m ->
            buildString {
                append("${m.firstName ?: ""} ${m.lastName ?: ""} (${m.empCode ?: ""})\n")
                append("${musterIssueLabels[m.issueType] ?: m.issueType}  ${m.date}  ${m.time?.take(5) ?: ""}\n")
                if (!m.reason.isNullOrBlank()) append("Note: ${m.reason}")
            }
        }
        lv.adapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, items)
        lv.setOnItemClickListener { _, _, pos, _ ->
            showMusterApprovalDialog(pendingMusterMods[pos])
        }
    }

    private fun showMusterApprovalDialog(m: MusterModificationRecord) {
        val ctx = requireContext()
        val etRemarks = EditText(ctx).apply { hint = "Remarks (optional)" }
        AlertDialog.Builder(ctx)
            .setTitle("${m.firstName} ${m.lastName} – Muster Modification")
            .setMessage(
                "${musterIssueLabels[m.issueType] ?: m.issueType}\n" +
                "Date: ${m.date}   Time: ${m.time?.take(5) ?: "—"}\n" +
                (if (!m.reason.isNullOrBlank()) "Note: ${m.reason}\n" else "") +
                "\nApproving will update the employee's attendance record for this date."
            )
            .setView(etRemarks)
            .setPositiveButton("Approve") { _, _ -> processMusterMod(m.id, "approved", etRemarks.text.toString()) }
            .setNegativeButton("Reject")  { _, _ -> processMusterMod(m.id, "rejected", etRemarks.text.toString()) }
            .setNeutralButton("Cancel", null)
            .show()
    }

    private fun processMusterMod(id: Int, decision: String, remarks: String) {
        lifecycleScope.launch {
            try {
                val resp = ApiClient.apiService.approveMusterModification(
                    mapOf("request_id" to id.toString(), "decision" to decision, "remarks" to remarks)
                )
                Toast.makeText(context, resp.body()?.message ?: "Done", Toast.LENGTH_SHORT).show()
                pendingMusterMods.removeAll { it.id == id }
                view?.let { showMusterMods(it) }
            } catch (e: CancellationException) {
                throw e  // normal when the screen changes mid-request — not a real error
            } catch (e: Exception) {
                Toast.makeText(context, "Error: ${e.message}", Toast.LENGTH_SHORT).show()
            }
        }
    }

    // ── On Duty ───────────────────────────────────────────────
    private fun showOnDuty(view: View) {
        val lv = view.findViewById<ListView>(R.id.lvApprovals)
        val items = pendingOnDuty.map { o ->
            buildString {
                append("${o.firstName ?: ""} ${o.lastName ?: ""} (${o.empCode ?: ""})\n")
                if (o.isFullDay == 1) {
                    append("${o.purpose}  ${o.startDate} → ${o.endDate}  (${o.days.toInt()}d, Full Day)\n")
                } else {
                    append("${o.purpose}  ${o.startDate}  ${o.fromTime?.take(5) ?: ""}–${o.toTime?.take(5) ?: ""} (Part Day)\n")
                }
                if (!o.location.isNullOrBlank()) append("Location: ${o.location}\n")
                if (!o.reason.isNullOrBlank()) append("Reason: ${o.reason}")
            }
        }
        lv.adapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, items)
        lv.setOnItemClickListener { _, _, pos, _ ->
            showOnDutyApprovalDialog(pendingOnDuty[pos])
        }
    }

    private fun showOnDutyApprovalDialog(o: OnDutyRequest) {
        val ctx = requireContext()
        val etRemarks = EditText(ctx).apply { hint = "Remarks (optional)" }
        val whenText = if (o.isFullDay == 1)
            "${o.startDate} to ${o.endDate} (${o.days.toInt()} days, Full Day)"
        else
            "${o.startDate}, ${o.fromTime?.take(5) ?: ""}–${o.toTime?.take(5) ?: ""} (Part Day)"
        AlertDialog.Builder(ctx)
            .setTitle("${o.firstName} ${o.lastName} – On Duty")
            .setMessage(
                "${o.purpose}\n" +
                "$whenText\n" +
                (if (!o.location.isNullOrBlank()) "Location: ${o.location}\n" else "") +
                (if (!o.reason.isNullOrBlank()) "Reason: ${o.reason}\n" else "") +
                "\nApproving will mark these as On Duty (Present) in the employee's attendance."
            )
            .setView(etRemarks)
            .setPositiveButton("Approve") { _, _ -> processOnDuty(o.id, "approved", etRemarks.text.toString()) }
            .setNegativeButton("Reject")  { _, _ -> processOnDuty(o.id, "rejected", etRemarks.text.toString()) }
            .setNeutralButton("Cancel", null)
            .show()
    }

    private fun processOnDuty(id: Int, status: String, remarks: String) {
        lifecycleScope.launch {
            try {
                val body = mapOf("request_id" to id.toString(), "status" to status, "remarks" to remarks)
                val resp = if (prefs.isManagement())
                    ApiClient.apiService.managementApprove(body + mapOf("type" to "on_duty"))
                else
                    ApiClient.apiService.approveOnDuty(body)
                Toast.makeText(context, resp.body()?.message ?: "Done", Toast.LENGTH_SHORT).show()
                pendingOnDuty.removeAll { it.id == id }
                view?.let { showOnDuty(it) }
            } catch (e: CancellationException) {
                throw e  // normal when the screen changes mid-request — not a real error
            } catch (e: Exception) {
                Toast.makeText(context, "Error: ${e.message}", Toast.LENGTH_SHORT).show()
            }
        }
    }
}
