package com.example.defenseapplication.view

import android.app.Dialog
import android.os.Bundle
import android.text.InputType
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.LinearLayout
import android.widget.EditText
import android.widget.TextView
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import com.example.defenseapplication.R

class CustomDialogFragment : androidx.fragment.app.DialogFragment() {

    data class Config(
        val title: String,
        val message: String = "",
        val positiveText: String = "确定",
        val negativeText: String? = "取消",
        val cancelOnTouchOutside: Boolean = true,
        val showInput: Boolean = false,
        val inputHint: String = "",
        val inputText: String = "",
        val inputType: Int = InputType.TYPE_CLASS_TEXT
    )

    private var onPositiveClick: ((String) -> Unit)? = null
    private var onNegativeClick: (() -> Unit)? = null
    private lateinit var config: Config

    fun setOnPositiveClick(block: (String) -> Unit): CustomDialogFragment = apply {
        onPositiveClick = block
    }

    fun setOnNegativeClick(block: () -> Unit): CustomDialogFragment = apply {
        onNegativeClick = block
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        config = Config(
            title = requireArguments().getString(ARG_TITLE).orEmpty(),
            message = requireArguments().getString(ARG_MESSAGE).orEmpty(),
            positiveText = requireArguments().getString(ARG_POSITIVE_TEXT).orEmpty(),
            negativeText = requireArguments().getString(ARG_NEGATIVE_TEXT),
            cancelOnTouchOutside = requireArguments().getBoolean(ARG_CANCEL_ON_TOUCH_OUTSIDE),
            showInput = requireArguments().getBoolean(ARG_SHOW_INPUT),
            inputHint = requireArguments().getString(ARG_INPUT_HINT).orEmpty(),
            inputText = requireArguments().getString(ARG_INPUT_TEXT).orEmpty(),
            inputType = requireArguments().getInt(ARG_INPUT_TYPE)
        )
        isCancelable = config.cancelOnTouchOutside
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return super.onCreateDialog(savedInstanceState).apply {
            setCanceledOnTouchOutside(config.cancelOnTouchOutside)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return inflater.inflate(R.layout.dialog_custom, container, false)
    }

    override fun onStart() {
        super.onStart()
        dialog?.window?.let { window ->
            window.setLayout(
                (resources.displayMetrics.widthPixels * 0.88f).toInt(),
                WindowManager.LayoutParams.WRAP_CONTENT
            )
            window.setBackgroundDrawableResource(android.R.color.transparent)
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val tvTitle = view.findViewById<TextView>(R.id.tv_title)
        val tvMessage = view.findViewById<TextView>(R.id.tv_message)
        val etInput = view.findViewById<EditText>(R.id.et_input)
        val btnNegative = view.findViewById<TextView>(R.id.btn_negative)
        val btnPositive = view.findViewById<TextView>(R.id.btn_positive)
        val dividerCenter = view.findViewById<View>(R.id.v_divider_center)

        tvTitle.text = config.title
        tvMessage.text = config.message
        tvMessage.visibility = if (config.message.isBlank()) View.GONE else View.VISIBLE

        etInput.visibility = if (config.showInput) View.VISIBLE else View.GONE
        etInput.hint = config.inputHint
        etInput.setText(config.inputText)
        etInput.inputType = config.inputType

        btnPositive.text = config.positiveText

        val hasNegative = !config.negativeText.isNullOrBlank()
        btnNegative.visibility = if (hasNegative) View.VISIBLE else View.GONE
        dividerCenter.visibility = if (hasNegative) View.VISIBLE else View.GONE
        if (hasNegative) {
            btnNegative.text = config.negativeText
        } else {
            btnPositive.layoutParams = LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )
        }

        btnNegative.setOnClickListener {
            onNegativeClick?.invoke()
            dismissAllowingStateLoss()
        }
        btnPositive.setOnClickListener {
            onPositiveClick?.invoke(etInput.text?.toString().orEmpty())
            dismissAllowingStateLoss()
        }
    }

    companion object {
        private const val ARG_TITLE = "arg_title"
        private const val ARG_MESSAGE = "arg_message"
        private const val ARG_POSITIVE_TEXT = "arg_positive_text"
        private const val ARG_NEGATIVE_TEXT = "arg_negative_text"
        private const val ARG_CANCEL_ON_TOUCH_OUTSIDE = "arg_cancel_on_touch_outside"
        private const val ARG_SHOW_INPUT = "arg_show_input"
        private const val ARG_INPUT_HINT = "arg_input_hint"
        private const val ARG_INPUT_TEXT = "arg_input_text"
        private const val ARG_INPUT_TYPE = "arg_input_type"

        fun newInstance(config: Config): CustomDialogFragment {
            return CustomDialogFragment().apply {
                arguments = bundleOf(
                    ARG_TITLE to config.title,
                    ARG_MESSAGE to config.message,
                    ARG_POSITIVE_TEXT to config.positiveText,
                    ARG_NEGATIVE_TEXT to config.negativeText,
                    ARG_CANCEL_ON_TOUCH_OUTSIDE to config.cancelOnTouchOutside,
                    ARG_SHOW_INPUT to config.showInput,
                    ARG_INPUT_HINT to config.inputHint,
                    ARG_INPUT_TEXT to config.inputText,
                    ARG_INPUT_TYPE to config.inputType
                )
            }
        }
    }
}

object DefenseDialogs {
    private const val DEFAULT_TAG = "custom_dialog_fragment"

    fun showDialog(
        activity: FragmentActivity,
        config: CustomDialogFragment.Config,
        tag: String = DEFAULT_TAG,
        onPositiveClick: (String) -> Unit = {},
        onNegativeClick: () -> Unit = {}
    ): CustomDialogFragment {
        return CustomDialogFragment.newInstance(config)
            .setOnPositiveClick(onPositiveClick)
            .setOnNegativeClick(onNegativeClick)
            .also { it.show(activity.supportFragmentManager, tag) }
    }

    fun showDialog(
        fragment: Fragment,
        config: CustomDialogFragment.Config,
        tag: String = DEFAULT_TAG,
        onPositiveClick: (String) -> Unit = {},
        onNegativeClick: () -> Unit = {}
    ): CustomDialogFragment {
        return CustomDialogFragment.newInstance(config)
            .setOnPositiveClick(onPositiveClick)
            .setOnNegativeClick(onNegativeClick)
            .also { it.show(fragment.parentFragmentManager, tag) }
    }

    fun intrusionAlertConfig(ctx: android.content.Context, deviceName: String, timeText: String): CustomDialogFragment.Config {
        return CustomDialogFragment.Config(
            title = ctx.getString(R.string.intrusion_alarm),
            message = "${timeText}${ctx.getString(R.string.someone_invaded)}\n【${deviceName}】",
            positiveText = ctx.getString(R.string.go_check),
            negativeText = ctx.getString(R.string.cancel)
        )
    }

    fun warmPromptConfig(ctx: android.content.Context, deviceName: String, runDays: Int): CustomDialogFragment.Config {
        return CustomDialogFragment.Config(
            title = ctx.getString(R.string.notice),
            message = "【${deviceName}】${ctx.getString(R.string.device_running_days, runDays)}",
            positiveText = ctx.getString(R.string.got_it),
            negativeText = null
        )
    }

    fun deviceOfflineConfig(ctx: android.content.Context): CustomDialogFragment.Config {
        return CustomDialogFragment.Config(
            title = ctx.getString(R.string.device_offline),
            message = ctx.getString(R.string.device_offline_message),
            positiveText = ctx.getString(R.string.got_it),
            negativeText = null
        )
    }

    fun strikeDistanceConfig(ctx: android.content.Context, defaultDistance: String): CustomDialogFragment.Config {
        return CustomDialogFragment.Config(
            title = ctx.getString(R.string.strike_distance),
            message = "",
            positiveText = ctx.getString(R.string.confirm),
            negativeText = ctx.getString(R.string.cancel),
            showInput = true,
            inputHint = ctx.getString(R.string.enter_strike_distance),
            inputText = defaultDistance,
            inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
        )
    }
}

fun FragmentActivity.showDefenseDialog(
    config: CustomDialogFragment.Config,
    tag: String = "custom_dialog_fragment",
    onPositiveClick: (String) -> Unit = {},
    onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
    return DefenseDialogs.showDialog(this, config, tag, onPositiveClick, onNegativeClick)
}

fun Fragment.showDefenseDialog(
    config: CustomDialogFragment.Config,
    tag: String = "custom_dialog_fragment",
    onPositiveClick: (String) -> Unit = {},
    onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
    return DefenseDialogs.showDialog(this, config, tag, onPositiveClick, onNegativeClick)
}

fun FragmentManager.showDefenseDialog(
    config: CustomDialogFragment.Config,
    tag: String = "custom_dialog_fragment",
    onPositiveClick: (String) -> Unit = {},
    onNegativeClick: () -> Unit = {}
): CustomDialogFragment {
    return CustomDialogFragment.newInstance(config)
        .setOnPositiveClick(onPositiveClick)
        .setOnNegativeClick(onNegativeClick)
        .also { it.show(this, tag) }
}