package com.omixlab.lckcontrol.p2p.discovery

import android.content.Context
import android.net.nsd.NsdManager
import android.net.nsd.NsdServiceInfo
import android.os.Build
import android.util.Log
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class NsdAdvertiser @Inject constructor(
    @ApplicationContext private val context: Context,
    private val p2pPreferences: P2pPreferences,
) {
    companion object {
        private const val TAG = "NsdAdvertiser"
        private const val SERVICE_TYPE = "_lckcontrol._tcp."
        private const val SERVICE_NAME = "LCKControl"
        const val PORT = 8765
    }

    private val nsdManager: NsdManager =
        context.getSystemService(Context.NSD_SERVICE) as NsdManager

    private var registrationListener: NsdManager.RegistrationListener? = null

    fun startAdvertising(userId: String) {
        if (!p2pPreferences.lanDiscoveryEnabled) return
        if (registrationListener != null) return

        val serviceInfo = NsdServiceInfo().apply {
            serviceName = SERVICE_NAME
            serviceType = SERVICE_TYPE
            port = PORT
            setAttribute("userId", userId)
            setAttribute("deviceId", p2pPreferences.stableDeviceId)
            setAttribute("model", Build.MODEL)
        }

        registrationListener = object : NsdManager.RegistrationListener {
            override fun onServiceRegistered(info: NsdServiceInfo?) {
                Log.d(TAG, "NSD registered: ${info?.serviceName}")
            }

            override fun onRegistrationFailed(info: NsdServiceInfo?, errorCode: Int) {
                Log.e(TAG, "NSD registration failed: $errorCode")
                registrationListener = null
            }

            override fun onServiceUnregistered(info: NsdServiceInfo?) {
                Log.d(TAG, "NSD unregistered")
            }

            override fun onUnregistrationFailed(info: NsdServiceInfo?, errorCode: Int) {
                Log.e(TAG, "NSD unregistration failed: $errorCode")
            }
        }

        nsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, registrationListener)
    }

    fun stopAdvertising() {
        registrationListener?.let {
            try {
                nsdManager.unregisterService(it)
            } catch (_: Exception) {}
        }
        registrationListener = null
    }
}
