package com.rosetta.messenger.network

import android.content.Context
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.MediaPlayer
import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator
import android.os.VibratorManager
import android.util.Log
import com.rosetta.messenger.R

/**
 * Manages call sounds (ringtone, calling, connected, end_call).
 * Matches desktop CallProvider.tsx sound behavior.
 */
object CallSoundManager {

    private const val TAG = "CallSoundManager"

    private var mediaPlayer: MediaPlayer? = null
    private var vibrator: Vibrator? = null
    private var currentSound: CallSound? = null

    enum class CallSound {
        RINGTONE,   // Incoming call — loops
        CALLING,    // Outgoing call — loops
        CONNECTED,  // Call connected — plays once
        END_CALL    // Call ended — plays once
    }

    fun initialize(context: Context) {
        vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            val vm = context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as? VibratorManager
            vm?.defaultVibrator
        } else {
            @Suppress("DEPRECATION")
            context.getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator
        }
    }

    /**
     * Play a call sound. Stops any currently playing sound first.
     * RINGTONE and CALLING loop. CONNECTED and END_CALL play once.
     */
    fun play(context: Context, sound: CallSound) {
        stop()
        currentSound = sound

        val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as? AudioManager
        val ringerMode = audioManager?.ringerMode ?: AudioManager.RINGER_MODE_NORMAL
        val allowAudible = ringerMode == AudioManager.RINGER_MODE_NORMAL
        val allowVibration =
            sound == CallSound.RINGTONE &&
                (ringerMode == AudioManager.RINGER_MODE_NORMAL ||
                    ringerMode == AudioManager.RINGER_MODE_VIBRATE)

        if (!allowAudible) {
            if (allowVibration) {
                startVibration()
            }
            Log.i(TAG, "Skip audible $sound due to ringerMode=$ringerMode")
            return
        }

        val resId = when (sound) {
            CallSound.RINGTONE -> R.raw.call_ringtone
            CallSound.CALLING -> R.raw.call_calling
            CallSound.CONNECTED -> R.raw.call_connected
            CallSound.END_CALL -> R.raw.call_end
        }

        val loop = sound == CallSound.RINGTONE || sound == CallSound.CALLING

        try {
            val player = MediaPlayer.create(context, resId)
            if (player == null) {
                Log.e(TAG, "Failed to create MediaPlayer for $sound")
                return
            }

            player.setAudioAttributes(
                AudioAttributes.Builder()
                    .setUsage(
                        if (sound == CallSound.RINGTONE)
                            AudioAttributes.USAGE_NOTIFICATION_RINGTONE
                        else
                            AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING
                    )
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .build()
            )

            player.isLooping = loop
            player.setOnCompletionListener {
                if (!loop) {
                    stop()
                }
            }
            player.start()
            mediaPlayer = player

            // Vibrate for incoming calls
            if (allowVibration) {
                startVibration()
            }

            Log.i(TAG, "Playing $sound (loop=$loop)")
        } catch (e: Exception) {
            Log.e(TAG, "Error playing $sound", e)
        }
    }

    /**
     * Stop any currently playing sound and vibration.
     */
    fun stop() {
        try {
            mediaPlayer?.let { player ->
                if (player.isPlaying) player.stop()
                player.release()
            }
        } catch (_: Exception) {}
        mediaPlayer = null
        currentSound = null
        stopVibration()
    }

    private fun startVibration() {
        try {
            val v = vibrator ?: return
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val pattern = longArrayOf(0, 500, 300, 500, 300, 500, 1000)
                v.vibrate(VibrationEffect.createWaveform(pattern, 0))
            } else {
                @Suppress("DEPRECATION")
                v.vibrate(longArrayOf(0, 500, 300, 500, 300, 500, 1000), 0)
            }
        } catch (_: Exception) {}
    }

    private fun stopVibration() {
        try {
            vibrator?.cancel()
        } catch (_: Exception) {}
    }
}
