package com.pan_american.android.ui.group_management.group_info

import android.Manifest
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.util.Base64
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import com.google.gson.Gson
import com.pan_american.android.OASystem
import com.pan_american.android.R
import com.pan_american.android.base.BaseActivity
import com.pan_american.android.base.BaseResponse
import com.pan_american.android.data.model.common.entity.RequestCodeBean
import com.pan_american.android.data.model.common.network.QuerySetDataRequest
import com.pan_american.android.data.model.common.network.SelectorResponse
import com.pan_american.android.data.model.group_management.group_info.network.GetSellCodeResponse
import com.pan_american.android.data.model.group_management.group_info.network.GroupCustomerListRequest
import com.pan_american.android.data.model.group_management.group_info.network.GroupCustomerListResponse
import com.pan_american.android.data.model.group_management.group_info.network.GroupInfoDetailRequest
import com.pan_american.android.data.model.group_management.group_info.network.GroupInfoDetailResponse
import com.pan_american.android.data.model.group_management.group_info.network.GroupOperationRequest
import com.pan_american.android.data.network.APIService
import com.pan_american.android.data.network.ServiceCreator
import com.pan_american.android.databinding.ActivityAddGroupInfoBinding
import com.pan_american.android.databinding.LayoutTitleBinding
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileWriter

class AddGroupInfoActivity : BaseActivity<ActivityAddGroupInfoBinding>() {

    private lateinit var titleBinding: LayoutTitleBinding

    private var groupId = 0

    private var fromList = false

    //监听拍照事件回调
    private lateinit var result: ActivityResultLauncher<Intent>

    //名片识别，图片Uri
    private lateinit var imageUri: Uri

    //输出文件路径
    private lateinit var outputImage: File

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

    override fun getViewBinding() = ActivityAddGroupInfoBinding.inflate(layoutInflater)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        screenAdaptation(binding)

        intent.apply {
            groupId = getIntExtra("id", 0)
            fromList = getBooleanExtra("fromList", false)
        }

        result = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            if (it.resultCode == Activity.RESULT_OK) {
                getCustomerList()
            }
        }

        OASystem.groupOperationRequest = GroupOperationRequest()
        OASystem.groupInfoGroupCustomerList.clear()

        if (fromList) {
            getGroupInfoDetail()
        } else {
            getSellCode()
        }

        initTitle()
    }

    override fun onStart() {
        super.onStart()

        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this)
        }
    }

    override fun onStop() {
        super.onStop()

        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this)
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int, permissions: Array<out String>, grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == OASystem.CAMERA_REQUEST_CODE) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startGetPhoto()
            } else {
                showMessage(resources.getString(R.string.camera_permission_hint))
            }
        }
    }

    override fun initTitle() {
        titleBinding = LayoutTitleBinding.bind(binding.root).apply {
            if (fromList) {
                titleText.text = resources.getString(R.string.group_info_detail)
            } else {
                titleText.text = resources.getString(R.string.add_group_info)
            }

            backButton.setOnClickListener {
                back()
            }
        }
    }

    private fun getSellCode() {
        apiService.getSellCode().enqueue(object : Callback<GetSellCodeResponse> {
            override fun onResponse(
                call: Call<GetSellCodeResponse>, response: Response<GetSellCodeResponse>
            ) {
                val codeResponse = response.body()

                if (codeResponse != null) {
                    if (codeResponse.code == 200) {
                        OASystem.groupOperationRequest.salesQuoteNo = codeResponse.data.salesQuoteNo

                        getOpPercentageLevel()
                    } else {
                        showMessage(codeResponse.msg)
                    }
                }
            }

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

    private fun getOpPercentageLevel() {
        apiService.querySetData(QuerySetDataRequest(70))
            .enqueue(object : Callback<SelectorResponse> {
                override fun onResponse(
                    call: Call<SelectorResponse>, response: Response<SelectorResponse>
                ) {

                    val selectorResponse = response.body()

                    if (selectorResponse != null) {
                        if (selectorResponse.code == 200) {
                            OASystem.groupInfoOpPercentageLevel = selectorResponse.data

                            getBerthType()

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

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

    private fun getBerthType() {
        apiService.querySetData(QuerySetDataRequest(44))
            .enqueue(object : Callback<SelectorResponse> {
                override fun onResponse(
                    call: Call<SelectorResponse>, response: Response<SelectorResponse>
                ) {
                    val selectorResponse = response.body()

                    if (selectorResponse != null) {
                        if (selectorResponse.code == 200) {
                            OASystem.groupInfoBerthType = selectorResponse.data

                            supportFragmentManager.beginTransaction().addToBackStack(null)
                                .add(binding.addGroupInfoContainer.id, GroupInfoBaseFragment())
                                .commit()

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

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

    private fun getGroupInfoDetail() {

        apiService.getGroupInfoDetail(GroupInfoDetailRequest(groupId))
            .enqueue(object : Callback<GroupInfoDetailResponse> {
                override fun onResponse(
                    call: Call<GroupInfoDetailResponse>, response: Response<GroupInfoDetailResponse>
                ) {
                    val detailResponse = response.body()

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

                            OASystem.groupOperationRequest = detailResponse.data

                            OASystem.groupInfoGroupCustomerList =
                                OASystem.groupOperationRequest.tourClientListInfos

                            OASystem.groupOperationRequest.userId = OASystem.userInfo.userId

                            OASystem.groupOperationRequest.status = 2

                            getOpPercentageLevel()

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

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

    //fragment 申请相机权限，打开相机并拍照
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun fragmentCameraRequest(requestCode: RequestCodeBean) {
        if (requestCode.code == OASystem.CAMERA_REQUEST_CODE) {
            if (ContextCompat.checkSelfPermission(
                    OASystem.context, Manifest.permission.CAMERA
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                ActivityCompat.requestPermissions(
                    this, arrayOf(Manifest.permission.CAMERA), OASystem.CAMERA_REQUEST_CODE
                )
            } else {
                startGetPhoto()
            }
        }
    }

    private fun startGetPhoto() {
        //创建File对象，用于存储拍照后的图片
        outputImage = File(externalCacheDir, "output_image.jpg")

        if (outputImage.exists()) {
            outputImage.delete()
        }

        outputImage.createNewFile()
        imageUri =
            FileProvider.getUriForFile(this, "com.pan_american.android.file_provider", outputImage)

        //启动相机程序
        val intent = Intent("android.media.action.IMAGE_CAPTURE")
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
        result.launch(intent)
    }

    private fun getCustomerList() {

        var base64Adjusted = false

        var bitmapSampleSize = 2

        var bitmapQuality = 100

        val byteArrayOutputStream = ByteArrayOutputStream()

        var transferBase64: String

        do {
            val options = BitmapFactory.Options()
            options.inSampleSize = bitmapSampleSize

            val bitmap =
                BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri), null, options)

            bitmap!!.compress(Bitmap.CompressFormat.JPEG, bitmapQuality, byteArrayOutputStream)

            transferBase64 = "image/jpeg;base64," + Base64.encodeToString(
                byteArrayOutputStream.toByteArray(), Base64.NO_WRAP
            )

            if (transferBase64.length < 1024 * 1024 * 2) {
                if (transferBase64.length < 1024 * 1024) {
                    base64Adjusted = true
                    byteArrayOutputStream.close()
                } else {
                    bitmapQuality -= 10
                }
            } else {
                bitmapSampleSize *= 2
            }

            byteArrayOutputStream.reset()
            bitmap.recycle()

        } while (!base64Adjusted)

        val file = File(filesDir, "data.txt")
        if (file.exists()) {
            file.delete()
        }
        file.createNewFile()
        val writer = FileWriter(file)
        writer.append(Gson().toJson(GroupCustomerListRequest(transferBase64)))
        writer.flush()
        writer.close()

        apiService.getGroupCustomerList(GroupCustomerListRequest(transferBase64))
            .enqueue(object : Callback<GroupCustomerListResponse> {

                override fun onResponse(
                    call: Call<GroupCustomerListResponse>,
                    response: Response<GroupCustomerListResponse>
                ) {

                    val listResponse = response.body()

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

                            if (listResponse.data.size == 0) {
                                showMessage(resources.getString(R.string.recognition_failed))
                                return
                            }

                            for (item in listResponse.data) {
                                OASystem.groupInfoGroupCustomerList.add(item)
                            }

                            EventBus.getDefault().post(OASystem.groupInfoGroupCustomerList)

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

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

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun groupOperate(groupOperationRequest: GroupOperationRequest) {

        val file = File(filesDir, "data.txt")
        if (file.exists()) {
            file.delete()
        }
        file.createNewFile()
        val writer = FileWriter(file)
        writer.append(Gson().toJson(groupOperationRequest))
        writer.flush()
        writer.close()

        apiService.groupOperation(groupOperationRequest).enqueue(object : Callback<BaseResponse> {
            override fun onResponse(call: Call<BaseResponse>, response: Response<BaseResponse>) {

                val operateResponse = response.body()

                if (operateResponse != null) {
                    if (operateResponse.code == 200) {
                        if (fromList) {
                            showMessage(resources.getString(R.string.update_success))
                        } else {
                            showMessage(resources.getString(R.string.insert_success))
                        }

                        OASystem.needRefresh = true

                        finish()

                        OASystem.groupInfoGroupCustomerList.clear()

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

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