package wang.yaojia.webterm.tlsandroid

import java.security.UnrecoverableKeyException
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertThrows
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import androidx.test.ext.junit.runners.AndroidJUnit4
import wang.yaojia.webterm.clienttls.CertificateSummaryReader
import wang.yaojia.webterm.clienttls.NoClientIdentityException

/**
 * Instrumented (real AndroidKeyStore — NOT Robolectric, plan §7) tests for the framework import path.
 * COMPILES in CI here; RUNS on a device/emulator during device QA.
 */
@RunWith(AndroidJUnit4::class)
class AndroidKeyStoreImporterTest {

    private val alias = "test-device-identity"
    private val importer = AndroidKeyStoreImporter(alias = alias)

    @Before
    fun clean() = importer.remove()

    @After
    fun tearDown() = importer.remove()

    @Test
    fun importHappyPath_importsRetrievableNonExportableKey() {
        val parsed = importer.import(Fixtures.leafP12(), Fixtures.PASSPHRASE)

        assertEquals("RSA", parsed.keyAlgorithm)
        assertEquals(Fixtures.LEAF_SUBJECT_CN, parsed.summary().subjectCommonName)
        assertEquals(Fixtures.LEAF_ISSUER_CN, parsed.summary().issuerCommonName)

        assertTrue("key entry present after import", importer.hasInstalledKey())
        assertNotNull("AndroidKeyStore key handle readable", importer.loadPrivateKey())
        val chain = importer.loadCertificateChain()
        assertNotNull("cert chain stored alongside key", chain)
        assertTrue("chain has at least the leaf", chain!!.isNotEmpty())
    }

    @Test
    fun certsOnlyP12_mapsToNoClientIdentity_andImportsNothing() {
        assertThrows(NoClientIdentityException::class.java) {
            importer.import(Fixtures.trustP12(), Fixtures.PASSPHRASE)
        }
        assertFalse("nothing persisted for a certs-only .p12", importer.hasInstalledKey())
    }

    @Test
    fun importValidatesBeforePersist_badPassphraseCannotClobberPriorIdentity() {
        // Install a good identity first.
        importer.import(Fixtures.leafP12(), Fixtures.PASSPHRASE)

        // A wrong passphrase must throw during PARSE (before any AndroidKeyStore mutation).
        assertThrows(UnrecoverableKeyException::class.java) {
            importer.import(Fixtures.leafP12(), Fixtures.WRONG_PASSPHRASE)
        }

        // The prior identity must still be present AND unchanged after the failed import.
        assertTrue("prior key survives a failed import", importer.hasInstalledKey())
        val leafCnAfter = importer.loadCertificateChain()!!.first().let {
            CertificateSummaryReader.summarize(it).subjectCommonName
        }
        assertEquals(Fixtures.LEAF_SUBJECT_CN, leafCnAfter)
    }
}
