/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.focus.utils

import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.fragment.app.FragmentActivity
import mozilla.components.browser.state.state.ExternalAppType
import mozilla.components.browser.state.state.SessionState
import mozilla.components.feature.customtabs.createCustomTabConfigFromIntent
import mozilla.components.support.utils.ext.packageManagerCompatHelper
import org.mozilla.focus.BuildConfig
import org.mozilla.focus.R
import org.mozilla.focus.activity.CustomTabActivity
import org.mozilla.focus.ext.components
import org.mozilla.focus.locale.Locales
import org.mozilla.focus.state.AppAction
import java.io.UnsupportedEncodingException
import java.net.URLEncoder
import java.util.Locale

/**
 * Utility class for support-related URLs and operations.
 */
object SupportUtils {
    const val HELP_URL = "https://support.mozilla.org/kb/what-firefox-focus-android"
    const val FOCUS_PLAY_STORE_URL = "https://play.google.com/store/apps/details?id=${BuildConfig.APPLICATION_ID}"
    const val RATE_APP_URL = "market://details?id=" + BuildConfig.APPLICATION_ID
    const val DEFAULT_BROWSER_URL = "https://support.mozilla.org/kb/set-firefox-focus-default-browser-android"
    const val PRIVACY_NOTICE_URL = "https://www.mozilla.org/privacy/firefox-focus/"
    const val TERMS_OF_USE_URL = "https://www.mozilla.org/about/legal/terms/firefox-focus/"

    const val OPEN_WITH_DEFAULT_BROWSER_URL = "https://www.mozilla.org/openGeneralSettings" // Fake URL
    val manifestoURL: String
        get() {
            val langTag = Locales.getLanguageTag(Locale.getDefault())
            return "https://www.mozilla.org/$langTag/about/manifesto/"
        }

    /**
     * Paths for specific pages on the Mozilla website.
     */
    enum class MozillaPage(internal val path: String) {
        PRIVATE_NOTICE("privacy/firefox-focus/"),
        TERMS_OF_SERVICE("about/legal/terms/firefox-focus/"),
    }

    /**
     * Returns the localised URL for a given [page].
     */
    fun getMozillaPageUrl(page: MozillaPage, locale: Locale = Locale.getDefault()): String {
        val path = page.path
        val langTag = Locales.getLanguageTag(locale)
        return "https://www.mozilla.org/$langTag/$path"
    }

    /**
     * Topics available on Mozilla Support (SUMO).
     */
    enum class SumoTopic(
        /** The final path segment for a SUMO URL - see {@see #getSumoURLForTopic}  */
        internal val topicStr: String,
    ) {
        ADD_SEARCH_ENGINE("add-search-engine"),
        AUTOCOMPLETE("autofill-domain-android"),
        TRACKERS("trackers"),
        USAGE_PING_SETTINGS("usage-ping-settings-mobile"),
        SEARCH_SUGGESTIONS("search-suggestions-focus-android"),
        HTTPS_ONLY("https-only-prefs-focus"),
        COOKIE_BANNER("cookie-banner-reduction-firefox-focus-android"),
    }

    /**
     * Returns a generic Mozilla Support (SUMO) URL for the given [topic].
     */
    fun getGenericSumoURLForTopic(topic: SumoTopic): String {
        val escapedTopic = getEncodedTopicUTF8(topic.topicStr)
        val langTag = Locales.getLanguageTag(Locale.getDefault())
        return "https://support.mozilla.org/$langTag/kb/$escapedTopic"
    }

    /**
     * Returns the SUMO URL for a specific topic
     */
    fun getSumoURLForTopic(appVersion: String, topic: SumoTopic): String {
        val escapedTopic = getEncodedTopicUTF8(topic.topicStr)
        val osTarget = "Android"
        val langTag = Locales.getLanguageTag(Locale.getDefault())
        return "https://support.mozilla.org/1/mobile/$appVersion/$osTarget/$langTag/$escapedTopic"
    }

    /**
     * Returns the Mozilla Support (SUMO) URL for safe browsing.
     */
    fun getSafeBrowsingURL(): String {
        val langTag = Locales.getLanguageTag(Locale.getDefault())
        return "https://support.mozilla.org/$langTag/kb/how-does-phishing-and-malware-protection-work"
    }

    private fun getEncodedTopicUTF8(topic: String): String {
        try {
            return URLEncoder.encode(topic, "UTF-8")
        } catch (e: UnsupportedEncodingException) {
            throw IllegalStateException("utf-8 should always be available", e)
        }
    }

    /**
     * Returns the version name of this package or an empty string if versionName is null.
     */
    fun getAppVersion(context: Context): String {
        try {
            return context.packageManagerCompatHelper.getPackageInfoCompat(
                context.packageName,
                0,
            ).versionName ?: ""
        } catch (e: PackageManager.NameNotFoundException) {
            // This should be impossible - we should always be able to get information about ourselves:
            throw IllegalStateException("Unable find package details for Focus", e)
        }
    }

    /**
     * Opens the default browser Mozilla Support (SUMO) page.
     */
    fun openDefaultBrowserSumoPage(context: Context) {
        val tabId = context.components.tabsUseCases.addTab(
            DEFAULT_BROWSER_URL,
            source = SessionState.Source.Internal.Menu,
            selectTab = true,
            private = true,
        )

        context.components.appStore.dispatch(
            AppAction.OpenTab(tabId),
        )
    }

    /**
     * Opens the given [destinationUrl] in a custom tab.
     */
    fun openUrlInCustomTab(
        activity: FragmentActivity,
        destinationUrl: String,
        externalAppType: ExternalAppType = ExternalAppType.CUSTOM_TAB,
    ) {
        activity.intent.putExtra(
            CustomTabsIntent.EXTRA_TOOLBAR_COLOR,
            ContextCompat.getColor(activity, R.color.settings_background),
        )

        val tabId = activity.components.customTabsUseCases.add(
            url = destinationUrl,
            customTabConfig = createCustomTabConfigFromIntent(
                intent = activity.intent,
                resources = activity.resources,
                externalAppType = externalAppType,
            ),
            private = true,
            source = SessionState.Source.Internal.None,
        )
        val openCustomTabActivityIntent =
            Intent(activity, CustomTabActivity::class.java).apply {
                action = Intent.ACTION_VIEW
                data = getSumoURLForTopic(getAppVersion(activity), SumoTopic.ADD_SEARCH_ENGINE).toUri()
                putExtra(CustomTabActivity.CUSTOM_TAB_ID, tabId)
            }

        activity.startActivity(openCustomTabActivityIntent)
    }
}
