package com.pan_american.android.ui.financial_module.expense_approval

import android.os.Bundle
import android.text.Html
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckedTextView
import android.widget.PopupWindow
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import com.pan_american.android.OASystem
import com.pan_american.android.R
import com.pan_american.android.base.BaseFragment
import com.pan_american.android.base.BaseResponse
import com.pan_american.android.base.CustomAlertDialog
import com.pan_american.android.base.ListAdapter
import com.pan_american.android.data.model.common.entity.SiftListItem
import com.pan_american.android.data.model.financial_module.expense_approval.adapter.ExpenseApprovalPaymentListAdapter
import com.pan_american.android.data.model.financial_module.expense_approval.entity.ExpenseApprovalPaymentItem
import com.pan_american.android.data.model.financial_module.expense_approval.network.BaseGroupInfoRequest
import com.pan_american.android.data.model.financial_module.expense_approval.network.BaseGroupInfoResponse
import com.pan_american.android.data.model.financial_module.expense_approval.network.ExpenseApprovalPaymentListRequest
import com.pan_american.android.data.model.financial_module.expense_approval.network.ExpenseApprovalPaymentListResponse
import com.pan_american.android.data.model.financial_module.expense_approval.network.ExpenseApprovalPaymentTypeResponse
import com.pan_american.android.data.model.financial_module.expense_approval.network.UpdatePaymentListExpenseApprovalRequest
import com.pan_american.android.data.network.APIService
import com.pan_american.android.data.network.ServiceCreator
import com.pan_american.android.databinding.FragmentExpenseApprovalBinding
import com.pan_american.android.util.CommitButton
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class ExpenseApprovalFragment : BaseFragment<FragmentExpenseApprovalBinding>() {

    private val apiService = ServiceCreator.create<APIService>()

    private val filterList = ArrayList<SiftListItem>()

    private val paymentList = ArrayList<ExpenseApprovalPaymentItem>()

    private var expenseApprovalPaymentListRequest = ExpenseApprovalPaymentListRequest()

    private var groupId = 0

    private var labelId = 0

    private var groupBaseInfoInit = false

    private var groupBaseInfoShown = false

    private var paymentIdList = ArrayList<Int>()

    override fun getViewBinding(
        inflater: LayoutInflater,
        container: ViewGroup?,
        bundle: Bundle?
    ) = FragmentExpenseApprovalBinding.inflate(inflater, container, false)

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

        requireArguments().getInt("id").also {
            expenseApprovalPaymentListRequest.diId = it
            groupId = it
        }

        getPaymentType()

        initEvents()
    }

    override fun initEvents() {
        binding.baseInfoSwitch.setOnClickListener {
            if (groupBaseInfoShown) {
                binding.groupBaseInfo.visibility = View.GONE
                binding.baseInfoSwitch.text = resources.getString(R.string.show)
                groupBaseInfoShown = false
            } else {
                if (!groupBaseInfoInit) {
                    getGroupBaseInfo()
                } else {
                    binding.groupBaseInfo.visibility = View.VISIBLE
                }

                binding.baseInfoSwitch.text = resources.getString(R.string.hide)
                groupBaseInfoShown = true
            }
        }

        binding.revoke.setOnClickListener {
            showListUpdateAlertDialog(2)
        }

        binding.pass.setOnClickListener {
            showListUpdateAlertDialog(1)
        }

        binding.reject.setOnClickListener {
            showListUpdateAlertDialog(2)
        }
    }

    private fun getPaymentType() {
        apiService.getExpenseApprovalPaymentType().enqueue(object : Callback<ExpenseApprovalPaymentTypeResponse> {
            override fun onResponse(
                call: Call<ExpenseApprovalPaymentTypeResponse>,
                response: Response<ExpenseApprovalPaymentTypeResponse>
            ) {
                val resourceResponse = response.body()

                if (resourceResponse != null) {
                    if (resourceResponse.code == 200) {

                        for (item in resourceResponse.data) {
                            if (item.id != 1081) {
                                filterList.add(item)
                            }
                        }

                        filterList[0].apply {
                            isChecked = true
                            labelId = id
                            expenseApprovalPaymentListRequest.label = labelId
                        }

                        initFilterList()

                        getPaymentItemByLabel()

                    } else {
                        showMessage(resourceResponse.msg)
                    }
                }
            }

            override fun onFailure(call: Call<ExpenseApprovalPaymentTypeResponse>, t: Throwable) {
                showErrorInfo(R.string.expense_approval_payment_type_get_error)
            }
        })
    }

    private fun initFilterList() {

        val layoutManager = LinearLayoutManager(OASystem.context)
        binding.filterList.layoutManager = layoutManager

        val adapter = ListAdapter.Builder<SiftListItem>().apply {
            setData(filterList)
            setLayoutId(R.layout.item_expense_approval_sift)
            addBindView { itemView, data ->
                itemView.findViewById<CheckedTextView>(R.id.expense_sift).apply {
                    text = data.name
                    isChecked = data.isChecked
                }
            }
        }.create()

        binding.filterList.adapter = adapter

        adapter.onRecyclerViewItemClick = object : ListAdapter.OnRecyclerViewItemClick<SiftListItem> {
            override fun onItemClick(position: Int) {
                if (!filterList[position].isChecked) {

                    for ((i, item) in filterList.withIndex()) {
                        if (item.id == labelId) {
                            item.isChecked = false
                            adapter.notifyItemChanged(i)
                        }
                    }

                    filterList[position].apply {
                        isChecked = true
                        labelId = id
                    }

                    adapter.notifyItemChanged(position)

                    if (paymentList.size != 0) {
                        binding.segmentPaymentList.adapter!!.notifyItemRangeRemoved(0, paymentList.size)
                        paymentList.clear()
                    }

                    if (paymentIdList.size != 0) {
                        paymentIdList.clear()
                    }

                    expenseApprovalPaymentListRequest.label = labelId

                    getPaymentItemByLabel()
                }
            }
        }

        binding.filterList.setHasFixedSize(true)
    }

    private fun getPaymentItemByLabel() {
        apiService.getExpenseApprovalPaymentByLabel(expenseApprovalPaymentListRequest).enqueue(object : Callback<ExpenseApprovalPaymentListResponse> {
            override fun onResponse(
                call: Call<ExpenseApprovalPaymentListResponse>,
                response: Response<ExpenseApprovalPaymentListResponse>
            ) {
                val listResponse = response.body()
                if (listResponse != null) {
                    if (listResponse.code == 200) {

                        for (item in listResponse.data.data.detailList) {
                            paymentList.add(item)
                        }

                        if (paymentList.size == 0) {
                            showMessage(resources.getString(R.string.no_data))
                            return
                        }

                        initPaymentList()

                    } else {
                        showMessage(listResponse.msg)
                    }
                }
            }

            override fun onFailure(call: Call<ExpenseApprovalPaymentListResponse>, t: Throwable) {
                showErrorInfo(R.string.expense_approval_list_get_error)
            }
        })
    }

    private fun initPaymentList() {
        val layoutManager = LinearLayoutManager(OASystem.context)
        binding.segmentPaymentList.layoutManager = layoutManager

        val adapter = ExpenseApprovalPaymentListAdapter(paymentList)

        binding.segmentPaymentList.adapter = adapter

        adapter.onItemClick = object : ExpenseApprovalPaymentListAdapter.OnItemClick {
            override fun onItemCheck(position: Int) {
                paymentList[position].apply {
                    if (isChecked) {
                        paymentIdList.add(id)
                    } else {
                        paymentIdList.remove(id)
                    }
                }
            }

            override fun onItemClick(position: Int) {
                val detailPopup = View.inflate(OASystem.context, R.layout.popup_expense_approval_paayment_detail, null)
                popupWindow = PopupWindow(detailPopup, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)

                showPopupWindow {
                    val detailText = detailPopup.findViewById<TextView>(R.id.payment_detail)
                    val commitButton = detailPopup.findViewById<CommitButton>(R.id.commit)

                    detailText.text = Html.fromHtml(paymentList[position].priceMsgContent.trimIndent(), Html.FROM_HTML_MODE_LEGACY)
                    commitButton.apply {
                        setText(resources.getString(R.string.confirm))

                        setOnClickListener {
                            popupWindow.dismiss()
                        }
                    }

                    popupWindow.showAtLocation(binding.root, Gravity.CENTER, 0, 0)
                }
            }

            override fun onItemReject(position: Int) {
                showSingleUpdateAlertDialog(
                    String.format(resources.getString(R.string.approval_reject_hint), paymentList[position].priceNameContent),
                    position, 2
                )
            }

            override fun onItemPass(position: Int) {
                showSingleUpdateAlertDialog(
                    String.format(resources.getString(R.string.approval_pass_hint), paymentList[position].priceNameContent),
                    position, 1
                )

            }

            override fun onItemRevoke(position: Int) {
                showSingleUpdateAlertDialog(
                    String.format(resources.getString(R.string.approval_revoke_hint), paymentList[position].priceNameContent),
                    position, 2
                )
            }
        }
    }

    private fun getGroupBaseInfo() {

        apiService.getBaseGroupInfo(BaseGroupInfoRequest(groupId)).enqueue(object : Callback<BaseGroupInfoResponse> {
            override fun onResponse(
                call: Call<BaseGroupInfoResponse>,
                response: Response<BaseGroupInfoResponse>
            ) {
                val baseInfoResponse = response.body()

                if (baseInfoResponse != null) {
                    if (baseInfoResponse.code == 200) {

                        baseInfoResponse.data.apply {
                            binding.groupName.text = teamName
                            binding.groupCustomer.text = clientName
                            binding.visitCountry.text = visitCountry
                            binding.visitDays.text = visitDays.toString()
                            binding.visitMembers.text = visitPNumber.toString()
                            binding.duringTime.text = String.format(resources.getString(R.string.during_format), visitStartDate.substring(0, 10), visitEndDate.substring(0, 10))
                        }

                        binding.groupBaseInfo.visibility = View.VISIBLE

                    } else {
                        showMessage(baseInfoResponse.msg)
                    }
                }
            }

            override fun onFailure(call: Call<BaseGroupInfoResponse>, t: Throwable) {
                showErrorInfo(R.string.group_base_info_get_error)
            }
        })
    }

    private fun showSingleUpdateAlertDialog(string: String, position: Int, auditStatus: Int) {
        CustomAlertDialog.Builder().apply {
            setTitle(resources.getString(R.string.alert))
            setMessage(string)
            setNegativeButtonAndListener(resources.getString(R.string.cancel)) { dialog, _ ->
                dialog.dismiss()
            }
            setPositiveButtonAndListener(resources.getString(R.string.confirm)) { dialog, _ ->
                updateExpenseApproval(position, auditStatus)
                dialog.dismiss()
            }
        }.show()
    }

    private fun updateExpenseApproval(position: Int, auditStatus: Int) {
        apiService.updatePaymentListApproval(UpdatePaymentListExpenseApprovalRequest(paymentList[position].id.toString(), auditStatus)).enqueue(object : Callback<BaseResponse> {
            override fun onResponse(call: Call<BaseResponse>, response: Response<BaseResponse>) {
                val updateResponse = response.body()

                if (updateResponse != null) {
                    if (updateResponse.code == 200) {

                        binding.segmentPaymentList.adapter!!.notifyItemRangeRemoved(0, paymentList.size)

                        paymentList.clear()

                        getPaymentItemByLabel()

                        showMessage(resources.getString(R.string.update_success))

                    } else {
                        showMessage(updateResponse.msg)
                    }
                }
            }

            override fun onFailure(call: Call<BaseResponse>, t: Throwable) {
                showErrorInfo(R.string.update_error)
            }
        })
    }

    private fun showListUpdateAlertDialog(auditStatus: Int) {

        var paymentNameList = ""

        for (id in paymentIdList) {
            for (item in paymentList) {
                if (id == item.id) {
                    paymentNameList += item.priceNameContent
                    paymentNameList += "\n"
                }
            }
        }

        paymentNameList.trim()

        var modelName = ""

        for (item in filterList) {
            if (labelId == item.id) {
                modelName = item.name
            }
        }

        val groupName = binding.groupName.text

        CustomAlertDialog.Builder().apply {
            setTitle(resources.getString(R.string.alert))
            setMessage(String.format(resources.getString(R.string.approval_payment_list_update_hint), groupName, modelName, paymentNameList))
            setNegativeButtonAndListener(resources.getString(R.string.cancel)) { dialog, _ ->
                dialog.dismiss()
            }
            setPositiveButtonAndListener(resources.getString(R.string.confirm)) { dialog, _ ->
                updatePaymentListApproval(paymentIdList, auditStatus)
                dialog.dismiss()
            }
        }.show()
    }

    private fun updatePaymentListApproval(idList: ArrayList<Int>, auditStatus: Int) {

        val creditString = idList.toString().replace("[", "").replace("]", "")

        apiService.updatePaymentListApproval(UpdatePaymentListExpenseApprovalRequest(creditString, auditStatus)).enqueue(object : Callback<BaseResponse> {
            override fun onResponse(call: Call<BaseResponse>, response: Response<BaseResponse>) {
                val updateResponse = response.body()

                if (updateResponse != null) {
                    if (updateResponse.code == 200) {

                        binding.segmentPaymentList.adapter!!.notifyItemRangeRemoved(0, paymentList.size)

                        paymentList.clear()

                        getPaymentItemByLabel()

                        showMessage(resources.getString(R.string.update_success))

                    } else {
                        showMessage(updateResponse.msg)
                    }
                }
            }

            override fun onFailure(call: Call<BaseResponse>, t: Throwable) {
                showErrorInfo(R.string.update_error)
            }
        })

        paymentIdList.clear()
    }
}