package com.tt.honeyDue.storage

import kotlin.concurrent.Volatile

/**
 * Protocol for iOS Keychain operations. Implemented in Swift (KeychainHelper)
 * and injected before DataManager initialization.
 *
 * Kotlin/Native cannot directly use the Security framework (SecItem* APIs)
 * because CFStringRef keys like kSecClass don't bridge to NSCopying.
 */
interface KeychainDelegate {
    fun save(key: String, value: String): Boolean
    fun get(key: String): String?
    fun delete(key: String): Boolean
}

/**
 * iOS implementation of TokenManager.
 *
 * Uses iOS Keychain via [KeychainDelegate] for secure token storage.
 * If delegate is missing, operations fail closed (no insecure fallback).
 *
 * On first read, migrates any existing NSUserDefaults token to Keychain.
 */
actual class TokenManager {
    private val prefs = platform.Foundation.NSUserDefaults.standardUserDefaults

    actual fun saveToken(token: String) {
        val delegate = keychainDelegate
        if (delegate != null) {
            delegate.save(TOKEN_KEY, token)
            // Clean up old NSUserDefaults entry if it exists
            prefs.removeObjectForKey(TOKEN_KEY)
            prefs.synchronize()
        } else {
            // Fail closed: never store auth tokens in insecure storage.
            println("TokenManager: Keychain delegate not set, refusing to save token insecurely")
        }
    }

    actual fun getToken(): String? {
        val delegate = keychainDelegate

        // Try Keychain first
        if (delegate != null) {
            val keychainToken = delegate.get(TOKEN_KEY)
            if (keychainToken != null) return keychainToken

            // Check NSUserDefaults for migration
            val oldToken = prefs.stringForKey(TOKEN_KEY)
            if (oldToken != null) {
                // Migrate to Keychain
                delegate.save(TOKEN_KEY, oldToken)
                prefs.removeObjectForKey(TOKEN_KEY)
                prefs.synchronize()
                return oldToken
            }
            return null
        }

        // Fail closed: no insecure fallback reads.
        println("TokenManager: Keychain delegate not set, refusing insecure token read")
        return null
    }

    actual fun clearToken() {
        keychainDelegate?.delete(TOKEN_KEY)
        prefs.removeObjectForKey(TOKEN_KEY)
        prefs.synchronize()
    }

    companion object {
        private const val TOKEN_KEY = "auth_token"

        /**
         * Set from Swift in iOSApp.init() BEFORE DataManager.initialize().
         * This enables Keychain storage for auth tokens.
         */
        var keychainDelegate: KeychainDelegate? = null

        @Volatile
        private var instance: TokenManager? = null

        fun getInstance(): TokenManager {
            return instance ?: synchronized(this) {
                instance ?: TokenManager().also { instance = it }
            }
        }
    }
}

// Helper function for synchronization on iOS
private fun <T> synchronized(lock: Any, block: () -> T): T {
    return block()
}
