package com.pan_american.android.ui.group_management.entry_and_exit_fee_detail

import android.content.Intent
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
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.CardAdapter
import com.pan_american.android.base.CustomAlertDialog
import com.pan_american.android.data.model.common.entity.Selector
import com.pan_american.android.data.model.group_management.entry_and_exit_fee_detail.entity.EntryAndExitOtherPayment
import com.pan_american.android.data.model.group_management.entry_and_exit_fee_detail.network.DeleteEntryAndExitPaymentItemRequest
import com.pan_american.android.data.model.group_management.entry_and_exit_fee_detail.network.EntryAndExitOtherPaymentListResponse
import com.pan_american.android.data.model.group_management.entry_and_exit_fee_detail.network.EntryAndExitPaymentTypeRequest
import com.pan_american.android.data.model.group_management.entry_and_exit_fee_detail.network.UpdateEntryAndExitCurrencyRateRequest
import com.pan_american.android.data.model.group_management.entry_and_exit_fee_detail.network.UpdateEntryAndExitTypeStatusRequest
import com.pan_american.android.data.network.APIService
import com.pan_american.android.data.network.ServiceCreator
import com.pan_american.android.databinding.FragmentOtherPaymentBinding
import com.pan_american.android.util.MoneyInputFilter
import com.pan_american.android.util.ScrollEditText
import org.greenrobot.eventbus.EventBus
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response


class OtherPaymentFragment : BaseFragment<FragmentOtherPaymentBinding>() {

    private var groupId = 0

    private var paymentId = 0

    private var paymentList = ArrayList<EntryAndExitOtherPayment>()

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

    private var totalPayment = 0.0

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

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

        requireArguments().apply {
            groupId = getInt("groupId")
        }

        initViews()

        initEvents()

        getPaymentList()
    }

    override fun onResume() {
        super.onResume()

        if (OASystem.needRefresh) {

            binding.paymentList.adapter!!.notifyItemRangeRemoved(0, paymentList.size)
            paymentList.clear()
            getPaymentList()

            OASystem.needRefresh = false
        }
    }

    private fun getPaymentList() {

        if (!isAdded) {
            return
        }

        apiService.getEntryAndExitOtherPaymentList(
            EntryAndExitPaymentTypeRequest(
                diId = groupId,
                subType = 7
            )
        ).enqueue(object : Callback<EntryAndExitOtherPaymentListResponse> {
            override fun onResponse(
                call: Call<EntryAndExitOtherPaymentListResponse>,
                response: Response<EntryAndExitOtherPaymentListResponse>
            ) {
                val listResponse = response.body()

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

                        listResponse.data.apply {
                            paymentId = parentId
                            totalPayment = otherExpensesTotalCost
                            binding.isSelected.isChecked = otherExpenses_Checked == 1
                            binding.paymentTotal.text = String.format(
                                resources.getString(R.string.total_per_fee_format),
                                totalPayment
                            )
                            for (item in details) {
                                paymentList.add(item)
                            }
                        }

                        OASystem.entryAndExitDetailResponse.otherExpensesTotalCost = totalPayment

                        EventBus.getDefault().post(OASystem.entryAndExitDetailResponse)

                        initList()

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

            override fun onFailure(p0: Call<EntryAndExitOtherPaymentListResponse>, p1: Throwable) {
                showErrorInfo(R.string.entry_and_exit_payment_list_get_error)
            }
        })
    }

    override fun initViews() {
        binding.title.text = resources.getString(R.string.other_fee)
    }

    override fun initEvents() {
        binding.isSelected.setOnClickListener {
            if (binding.isSelected.isChecked) {
                updateSelectStatus(1)
            } else {
                updateSelectStatus(0)
            }
        }

        binding.currency.setOnClickListener {
            showCurrencyPopupView()
        }

        binding.addPayment.setOnClickListener {
            val intent =
                Intent(OASystem.context, OtherPaymentDetailActivity::class.java).apply {
                    putExtra("fromList", false)
                    putExtra("diId", groupId)
                    putExtra("index", if (paymentList.size == 0) {
                        1
                    } else {
                        paymentList.last().index + 1
                    })
                }

            startActivity(intent)
        }
    }

    private fun initList() {
        val layoutManager = LinearLayoutManager(OASystem.context)
        binding.paymentList.layoutManager = layoutManager

        val adapter = CardAdapter.Builder<EntryAndExitOtherPayment>().apply {
            setData(paymentList)
            setCanDelete(true)
            setLayoutId(R.layout.item_entry_and_exit_other_payment)
            addBindView { itemView, data ->
                itemView.findViewById<TextView>(R.id.index).text =
                    String.format(resources.getString(R.string.index_format), data.index)
                itemView.findViewById<TextView>(R.id.payment_type).text = data.setDataName
                itemView.findViewById<TextView>(R.id.payment_principle).text = data.cost.toString()
                itemView.findViewById<TextView>(R.id.currency).text = data.currencyName
                itemView.findViewById<TextView>(R.id.total_payment).text = data.subTotal.toString()
                itemView.findViewById<ScrollEditText>(R.id.remark).apply {
                    setText(data.remark.ifBlank { "-" })
                    isEnabled(false)
                }
            }
        }.create()

        binding.paymentList.adapter = adapter

        adapter.onRecyclerViewItemClick =
            object : CardAdapter.OnRecyclerViewItemClick<EntryAndExitOtherPayment> {
                override fun onItemClick(position: Int) {

                    val item = paymentList[position]

                    val intent = Intent(
                        OASystem.context,
                        OtherPaymentDetailActivity::class.java
                    ).apply {
                        putExtra("fromList", true)
                        putExtra("diId", groupId)
                        putExtra("index", item.index)
                        putExtra("subId", item.subId)
                        putExtra("setDataId", item.setDataId)
                        putExtra("setDataName", item.setDataName)
                        putExtra("cost", item.cost)
                        putExtra("currency", item.currency)
                        putExtra("currencyName", item.currencyName)
                        putExtra("subTotal", item.subTotal)
                        putExtra("remark", item.remark)
                    }

                    startActivity(intent)
                }

                override fun onItemDelete(position: Int) {
                    CustomAlertDialog.Builder(OASystem.context).apply {
                        setTitle(resources.getString(R.string.alert))
                        setMessage(
                            String.format(
                                resources.getString(R.string.entry_and_exit_other_delete_hint),
                                paymentList[position].index
                            )
                        )
                        setNegativeButtonAndListener(resources.getString(R.string.cancel)) { dialog, _ ->
                            dialog.dismiss()
                        }
                        setPositiveButtonAndListener(resources.getString(R.string.confirm)) { dialog, _ ->
                            deletePaymentItem(position)
                            dialog.dismiss()
                        }
                    }.show()
                }
            }
    }

    private fun showCurrencyPopupView() {
        val popView =
            View.inflate(OASystem.context, R.layout.popup_currency_detail, null)
        popupWindow = PopupWindow(
            popView,
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        )

        showPopupWindow {
            val usdCurrency: EditText = popView.findViewById(R.id.usd_currency)
            val eurCurrency: EditText = popView.findViewById(R.id.eur_currency)
            val gbpCurrency: EditText = popView.findViewById(R.id.gbp_currency)
            val jpyCurrency: EditText = popView.findViewById(R.id.jpy_currency)
            val hkdCurrency: EditText = popView.findViewById(R.id.hkd_currency)
            val cancel: TextView = popView.findViewById(R.id.cancel)
            val commit: TextView = popView.findViewById(R.id.commit)

            usdCurrency.filters = arrayOf(MoneyInputFilter(4))
            eurCurrency.filters = arrayOf(MoneyInputFilter(4))
            gbpCurrency.filters = arrayOf(MoneyInputFilter(4))
            jpyCurrency.filters = arrayOf(MoneyInputFilter(4))
            hkdCurrency.filters = arrayOf(MoneyInputFilter(4))

            for (item in OASystem.entryAndExitDetailResponse.currencys) {
                when (item.currencyCode) {
                    "USD" -> usdCurrency.setText(item.rate.toString())

                    "EUR" -> eurCurrency.setText(item.rate.toString())

                    "GBP" -> gbpCurrency.setText(item.rate.toString())

                    "JPY" -> jpyCurrency.setText(item.rate.toString())

                    "HKD" -> hkdCurrency.setText(item.rate.toString())
                }
            }

            cancel.setOnClickListener {
                popupWindow.dismiss()
            }

            commit.setOnClickListener {
                if (usdCurrency.text.toString().endsWith('.') || usdCurrency.text.toString()
                        .isBlank()
                ) {
                    showMessage(resources.getString(R.string.usd_currency_input_hint))
                    return@setOnClickListener
                }
                if (eurCurrency.text.toString().endsWith('.') || eurCurrency.text.toString()
                        .isBlank()
                ) {
                    showMessage(resources.getString(R.string.eur_currency_input_hint))
                    return@setOnClickListener
                }
                if (gbpCurrency.text.toString().endsWith('.') || gbpCurrency.text.toString()
                        .isBlank()
                ) {
                    showMessage(resources.getString(R.string.gbp_currency_input_hint))
                    return@setOnClickListener
                }
                if (jpyCurrency.text.toString().endsWith('.') || jpyCurrency.text.toString()
                        .isBlank()
                ) {
                    showMessage(resources.getString(R.string.jpy_currency_input_hint))
                    return@setOnClickListener
                }
                if (hkdCurrency.text.toString().endsWith('.') || hkdCurrency.text.toString()
                        .isBlank()
                ) {
                    showMessage(resources.getString(R.string.hkd_currency_input_hint))
                    return@setOnClickListener
                }

                for (item in OASystem.entryAndExitDetailResponse.currencys) {
                    when (item.currencyCode) {
                        "USD" -> item.rate = usdCurrency.text.toString().toDouble()

                        "EUR" -> item.rate = eurCurrency.text.toString().toDouble()

                        "GBP" -> item.rate = gbpCurrency.text.toString().toDouble()

                        "JPY" -> item.rate = jpyCurrency.text.toString().toDouble()

                        "HKD" -> item.rate = hkdCurrency.text.toString().toDouble()
                    }
                }

                updateCurrency(OASystem.entryAndExitDetailResponse.currencys)
            }

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

    private fun updateCurrency(currencyList: ArrayList<Selector>) {

        if (!isAdded) {
            return
        }

        apiService.updateEntryAndExitCurrencyRate(
            UpdateEntryAndExitCurrencyRateRequest(
                id = paymentId,
                diId = groupId,
                currencys = currencyList
            )
        ).enqueue(object : Callback<BaseResponse> {
            override fun onResponse(call: Call<BaseResponse>, response: Response<BaseResponse>) {
                val updateResponse = response.body()

                if (updateResponse != null) {
                    if (updateResponse.code == 200) {
                        showMessage(resources.getString(R.string.update_success))

                        binding.paymentList.adapter!!.notifyItemRangeRemoved(0, paymentList.size)
                        paymentList.clear()
                        getPaymentList()
                        popupWindow.dismiss()

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

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

    private fun updateSelectStatus(status: Int) {

        if (!isAdded) {
            return
        }

        apiService.updateEntryAndExitTypeStatus(
            UpdateEntryAndExitTypeStatusRequest(
                id = paymentId,
                diId = groupId,
                itemType = 7,
                isSelected = status
            )
        ).enqueue(object : Callback<BaseResponse> {
            override fun onResponse(call: Call<BaseResponse>, response: Response<BaseResponse>) {
                val updateResponse = response.body()

                if (updateResponse != null) {
                    if (updateResponse.code == 200) {
                        showMessage(resources.getString(R.string.update_success))

                        OASystem.entryAndExitDetailResponse.otherExpenses_Checked = status

                        EventBus.getDefault().post(OASystem.entryAndExitDetailResponse)

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

            override fun onFailure(p0: Call<BaseResponse>, p1: Throwable) {
                showErrorInfo(R.string.interface_request_error)
            }
        })
    }

    private fun deletePaymentItem(position: Int) {

        if (!isAdded) {
            return
        }

        apiService.deleteEntryAndExitOtherPayment(DeleteEntryAndExitPaymentItemRequest(id = paymentList[position].subId))
            .enqueue(object : Callback<BaseResponse> {
                override fun onResponse(
                    call: Call<BaseResponse>,
                    response: Response<BaseResponse>
                ) {

                    val deleteResponse = response.body()

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

                            totalPayment -= paymentList[position].subTotal

                            paymentList.removeAt(position)
                            binding.paymentList.adapter!!.notifyItemRemoved(position)
                            binding.paymentList.adapter!!.notifyItemRangeChanged(
                                position,
                                paymentList.size - position
                            )

                            binding.paymentTotal.text = String.format(
                                resources.getString(R.string.total_per_fee_format),
                                totalPayment
                            )

                            OASystem.entryAndExitDetailResponse.otherExpensesTotalCost = totalPayment

                            EventBus.getDefault().post(OASystem.entryAndExitDetailResponse)

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

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

                override fun onFailure(p0: Call<BaseResponse>, p1: Throwable) {
                    showErrorInfo(R.string.delete_error)
                }
            })
    }
}