// Android cross-app SSO scaffold.
//
// All suite apps are signed with the SAME key, so a ContentProvider guarded by
// a signature-level permission lets them share the OIDC session that ulti-core
// persists. One app (e.g. UltiMail) hosts the provider; siblings read/write
// through it. Backed by EncryptedSharedPreferences (androidx.security:security-crypto).
//
// Alternative: a custom AccountManager account type ("space.ulti.suite") with a
// shared authenticator — heavier, but integrates with system account settings.
//
// Manifest (host app), plus a matching <uses-permission> in every sibling:
//   <permission android:name="space.ulti.suite.permission.SESSION"
//       android:protectionLevel="signature" />
//   <provider
//       android:name=".sso.SharedSessionProvider"
//       android:authorities="space.ulti.suite.session"
//       android:exported="true"
//       android:readPermission="space.ulti.suite.permission.SESSION"
//       android:writePermission="space.ulti.suite.permission.SESSION" />

package space.ulti.suite.sso

import android.content.ContentProvider
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import android.database.MatrixCursor
import android.net.Uri
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey

class SharedSessionProvider : ContentProvider() {

    override fun onCreate(): Boolean = true

    private fun prefs(ctx: Context) = EncryptedSharedPreferences.create(
        ctx,
        "ulti_shared_session",
        MasterKey.Builder(ctx).setKeyScheme(MasterKey.KeyScheme.AES256_GCM).build(),
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
    )

    // query(content://space.ulti.suite.session/<key>) -> single-row "value".
    override fun query(
        uri: Uri, projection: Array<out String>?, selection: String?,
        selectionArgs: Array<out String>?, sortOrder: String?,
    ): Cursor {
        val key = uri.lastPathSegment ?: ""
        val value = prefs(context!!).getString(key, null)
        return MatrixCursor(arrayOf("value")).apply { addRow(arrayOf(value)) }
    }

    // insert with values{ key, value } (value=null deletes).
    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        val key = values?.getAsString("key") ?: return null
        val value = values.getAsString("value")
        prefs(context!!).edit().apply {
            if (value == null) remove(key) else putString(key, value)
        }.apply()
        return uri
    }

    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
        val key = uri.lastPathSegment ?: return 0
        prefs(context!!).edit().remove(key).apply()
        return 1
    }

    override fun update(
        uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?,
    ): Int = insert(uri, values)?.let { 1 } ?: 0

    override fun getType(uri: Uri): String = "vnd.android.cursor.item/ulti.session"
}
