package ru.forbion.f7cloud.feature.talk

/** Talk / WebRTC helpers (порт F7TalkHelper из android-webview). */
object TalkHelper {
    // Preconnect только к серверу сессии. Хост HPB НЕ хардкодим: боевой
    // hpb-prod.f7cloud.ru — §3-ресурс ячейки A (f7_platform mail/035), и клиент,
    // направленный на другой бэкенд, не должен его касаться. Если преконнект к
    // HPB понадобится — брать хост из capabilities spreed (signalingServers).
    fun buildPreconnectScript(serverOrigin: String): String {
        val origin = serverOrigin.replace("'", "\\'")
        return """
            (function(){
              var o='$origin';
              function link(rel,href){
                try{
                  if(document.querySelector('link[rel="'+rel+'"][href="'+href+'"]'))return;
                  var l=document.createElement('link');l.rel=rel;l.href=href;
                  if(rel==='preconnect')l.crossOrigin='anonymous';
                  (document.head||document.documentElement).appendChild(l);
                }catch(e){}
              }
              link('dns-prefetch',o);
              link('preconnect',o);
            })();
        """.trimIndent()
    }

    fun getCallUrlForWebViewLoad(url: String): String {
        if (!isCallRoomUrl(url)) return stripDirectCallHash(url)
        return runCatching {
            val uri = android.net.Uri.parse(url)
            val scheme = uri.scheme ?: return stripDirectCallHash(url)
            val host = uri.host ?: return stripDirectCallHash(url)
            val token = extractRoomTokenFromPath(uri.path) ?: return stripDirectCallHash(url)
            val port = uri.port
            val base = if (port > 0) "$scheme://$host:$port" else "$scheme://$host"
            "$base/call/$token"
        }.getOrDefault(stripDirectCallHash(url))
    }

    fun stripDirectCallHash(url: String): String {
        val hash = url.indexOf('#')
        return if (hash >= 0) url.substring(0, hash) else url
    }

    /** Incoming push accept: hide media-settings and join with mic/camera off. */
    fun buildDirectJoinDocumentStartScript(): String = """
        (function(){try{
          localStorage.setItem('showMediaSettings','false');
          var m=location.pathname.match(/\/call\/([A-Za-z0-9]+)/);
          if(m){
            localStorage.setItem('videoDisabled_'+m[1],'true');
            localStorage.removeItem('audioDisabled_'+m[1]);
          }
          if(location.hash==='#direct-call'){
            history.replaceState(history.state,'',location.pathname+location.search);
          }
        }catch(e){}})();
    """.trimIndent()

    /** Outgoing / manual join: restore Talk pre-call device picker. */
    fun buildNormalCallBootstrapScript(roomToken: String?): String {
        val tokenPrefs = if (roomToken.isNullOrBlank()) {
            ""
        } else {
            val tokenJs = roomToken.replace("'", "\\'")
            "localStorage.removeItem('videoDisabled_$tokenJs');" +
                "localStorage.removeItem('audioDisabled_$tokenJs');"
        }
        return """
            (function(){try{
              sessionStorage.removeItem('f7_apk_direct_join');
              document.documentElement.removeAttribute('data-f7-direct-join');
              localStorage.removeItem('showMediaSettings');
              $tokenPrefs
              if(location.hash==='#direct-call'){
                history.replaceState(history.state,'',location.pathname+location.search);
              }
            }catch(e){}})();
        """.trimIndent()
    }

    fun buildDirectJoinBootstrapScript(roomToken: String?): String {
        val tokenJs = roomToken?.replace("'", "\\'").orEmpty()
        val tokenPrefs = if (tokenJs.isEmpty()) {
            ""
        } else {
            "localStorage.setItem('videoDisabled_$tokenJs','true');" +
                "localStorage.removeItem('audioDisabled_$tokenJs');"
        }
        return """
            (function(){try{
              sessionStorage.setItem('f7_apk_direct_join','1');
              localStorage.setItem('showMediaSettings','false');
              document.documentElement.setAttribute('data-f7-direct-join','1');
              $tokenPrefs
              if(location.hash==='#direct-call'){
                history.replaceState(history.state,'',location.pathname+location.search);
              }
            }catch(e){}})();
        """.trimIndent()
    }

    fun extractRoomToken(url: String?): String? {
        if (url.isNullOrBlank()) return null
        return extractRoomTokenFromPath(android.net.Uri.parse(url).path)
    }

    private fun extractRoomTokenFromPath(path: String?): String? {
        if (path.isNullOrBlank()) return null
        val idx = path.indexOf("/call/")
        if (idx < 0) return null
        val rest = path.substring(idx + 6)
        val end = rest.indexOfFirst { it == '/' || it == '?' || it == '#' }.let { if (it < 0) rest.length else it }
        val token = rest.substring(0, end)
        return token.ifBlank { null }
    }

    fun isCallRoomUrl(url: String?): Boolean = url?.contains("/call/") == true

    fun isTalkAppUrl(url: String?): Boolean {
        if (url.isNullOrBlank()) return false
        return url.contains("/apps/spreed") || isCallRoomUrl(url)
    }

    fun isPortalHomeUrl(url: String?): Boolean {
        if (url.isNullOrBlank()) return false
        if (isCallRoomUrl(url)) return false
        val uri = android.net.Uri.parse(url)
        if (uri.scheme != "http" && uri.scheme != "https") return false
        val path = uri.path ?: return false
        if (path.isEmpty() || path == "/") return true
        return path.contains("/apps/dashboard") ||
            path.contains("/login") ||
            path.endsWith("/index.php")
    }

    fun isActiveCallUrl(url: String?): Boolean {
        if (url.isNullOrBlank()) return false
        if (isCallRoomUrl(url)) return true
        return url.contains("/apps/spreed") &&
            (url.contains("callUser=") || url.contains("callToken="))
    }

    fun talkAppWarmupUrl(serverBase: String): String {
        val base = serverBase.trimEnd('/')
        return "$base/apps/spreed/"
    }

    fun buildCallUrl(serverBase: String, roomToken: String): String {
        val base = serverBase.trimEnd('/')
        return "$base/call/${roomToken.trim()}"
    }
}
