package com.aves.google_cast

import android.app.Activity
import android.app.Application
import android.content.Context
import android.os.Bundle
import androidx.annotation.NonNull
import com.aves.google_cast.cast.*
import com.aves.google_cast.fast.FastCastEngine
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel

class FlutterCastFrameworkPlugin : FlutterPlugin,
    MethodChannel.MethodCallHandler,
    Application.ActivityLifecycleCallbacks,
    ActivityAware {

    companion object {
        @JvmStatic
        var enabled: Boolean = true
    }

    private lateinit var appContext: Context
    private lateinit var channel: MethodChannel
    private var currentActivity: Activity? = null

    private lateinit var contextManager: CastContextManager
    private lateinit var sessionHandler: CastSessionHandler
    private lateinit var mediaClient: CastMediaClient
    private lateinit var queueManager: CastQueueManager
    private lateinit var dialogLauncher: CastDialogLauncher
    private lateinit var customReceiver: CastCustomReceiver

    // ⭐ FAST basato su Google Cast (CAF)
    private lateinit var fastEngine: FastCastEngine

    override fun onAttachedToEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
        appContext = binding.applicationContext

        channel = MethodChannel(binding.binaryMessenger, "google_cast")
        channel.setMethodCallHandler(this)

        sessionHandler = CastSessionHandler(channel)
        contextManager = CastContextManager(appContext, sessionHandler)
        mediaClient = CastMediaClient(contextManager, channel)
        sessionHandler.setMediaClient(mediaClient)
        queueManager = CastQueueManager(contextManager, channel)
        dialogLauncher = CastDialogLauncher(channel)
        customReceiver = CastCustomReceiver(contextManager, channel)

        fastEngine = FastCastEngine(contextManager, mediaClient, channel)

        if (appContext is Application) {
            (appContext as Application).registerActivityLifecycleCallbacks(this)
        }
    }

    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)

        if (appContext is Application) {
            (appContext as Application).unregisterActivityLifecycleCallbacks(this)
        }
    }

    // ActivityAware
    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        currentActivity = binding.activity
        if (!enabled) return

        contextManager.attachActivity(binding.activity)
        contextManager.ensureCastContext()
        mediaClient.attachCurrentClientIfNeeded()
    }

    override fun onDetachedFromActivity() {
        currentActivity = null
        if (!enabled) return
        contextManager.detachActivity()
    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
        currentActivity = binding.activity
        if (!enabled) return

        contextManager.attachActivity(binding.activity)
        contextManager.ensureCastContext()
        mediaClient.attachCurrentClientIfNeeded()
    }

    override fun onDetachedFromActivityForConfigChanges() {
        currentActivity = null
        if (!enabled) return
        contextManager.detachActivity()
    }

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {

        // ------------------------------------------------------------
        // ⭐ FAST (Google Cast / CAF)
        // ------------------------------------------------------------
        when (call.method) {
            "fast.loadQueue" -> {
                fastEngine.loadQueue(call.arguments as Map<*, *>)
                result.success(null)
                return
            }
            "fast.next" -> {
                fastEngine.next()
                result.success(null)
                return
            }
            "fast.prev" -> {
                fastEngine.prev()
                result.success(null)
                return
            }
            "fast.stop" -> {
                fastEngine.stop()
                result.success(null)
                return
            }
        }

        // ------------------------------------------------------------
        // Abilitazione/disabilitazione Google Cast
        // ------------------------------------------------------------
        if (call.method == "setEnabled") {
            val newValue = call.argument<Boolean>("value") ?: true
            enabled = newValue

            if (!enabled) {
                try {
                    mediaClient.resetClientTracking()
                    contextManager.ensureCastContext()
                        ?.sessionManager
                        ?.endCurrentSession(true)
                } catch (_: Exception) {
                }
            } else {
                currentActivity?.let {
                    contextManager.attachActivity(it)
                    contextManager.ensureCastContext()
                    mediaClient.attachCurrentClientIfNeeded()
                }
            }

            result.success(null)
            return
        }

        if (!enabled) {
            result.error("DISABLED", "Google Cast backend disabled", null)
            return
        }

        // ------------------------------------------------------------
        // Google Cast standard
        // ------------------------------------------------------------
        when (call.method) {

            "showCastDialog" -> {
                currentActivity?.let {
                    contextManager.ensureCastContext()
                    mediaClient.attachCurrentClientIfNeeded()
                    dialogLauncher.showCastDialog(it)
                }
                result.success(null)
            }

            "startCustomReceiver" -> {
                val appId = call.argument<String>("appId")
                val url = call.argument<String>("receiverUrl")

                if (appId == null || url == null) {
                    result.error("ARG_ERROR", "appId and receiverUrl required", null)
                } else {
                    contextManager.ensureCastContext()
                    mediaClient.attachCurrentClientIfNeeded()
                    customReceiver.startCustomReceiver(appId, url)
                    result.success(null)
                }
            }

            "sendCustomMessage" -> {
                val message = call.argument<String>("message")
                if (message != null) {
                    customReceiver.sendCustomMessage(message)
                }
                result.success(null)
            }

            "loadQueue" -> {
                val items = call.argument<List<Map<String, Any>>>("items")
                val startIndex = call.argument<Int>("startIndex") ?: 0

                if (items == null) {
                    result.error("ARG_ERROR", "items required", null)
                } else {
                    contextManager.ensureCastContext()
                    mediaClient.attachCurrentClientIfNeeded()
                    queueManager.loadQueue(items, startIndex)
                    result.success(null)
                }
            }

            "next" -> {
                mediaClient.attachCurrentClientIfNeeded()
                queueManager.next()
                result.success(null)
            }

            "prev" -> {
                mediaClient.attachCurrentClientIfNeeded()
                queueManager.prev()
                result.success(null)
            }

            "play" -> {
                mediaClient.play()
                result.success(null)
            }

            "pause" -> {
                mediaClient.pause()
                result.success(null)
            }

            "seekTo" -> {
                val pos = call.argument<Number>("position")?.toLong() ?: 0L
                mediaClient.seek(pos)
                result.success(null)
            }

            "setVolume" -> {
                val v = call.argument<Double>("volume") ?: 0.0
                mediaClient.setVolume(v)
                result.success(null)
            }

            "setMute" -> {
                val m = call.argument<Boolean>("mute") ?: false
                mediaClient.setMute(m)
                result.success(null)
            }

            "stopCast" -> {
                try {
                    mediaClient.resetClientTracking()
                    contextManager.ensureCastContext()
                        ?.sessionManager
                        ?.endCurrentSession(true)
                } catch (_: Exception) {
                }
                result.success(null)
            }

            else -> result.notImplemented()
        }
    }

    // Activity lifecycle
    override fun onActivityResumed(activity: Activity) {
        currentActivity = activity
        if (!enabled) return

        contextManager.attachActivity(activity)
        contextManager.ensureCastContext()
        mediaClient.attachCurrentClientIfNeeded()
    }

    override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
        currentActivity = activity
    }

    override fun onActivityStarted(activity: Activity) {
        currentActivity = activity
    }

    override fun onActivityPaused(activity: Activity) {}
    override fun onActivityStopped(activity: Activity) {}
    override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
    override fun onActivityDestroyed(activity: Activity) {}
}
