package com.syncflow.data.repository

import com.syncflow.data.db.CloudAccountDao
import com.syncflow.data.db.entities.CloudAccountEntity
import com.syncflow.data.security.CredentialStore
import com.syncflow.domain.model.CloudAccount
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class AccountRepository @Inject constructor(
    private val accountDao: CloudAccountDao,
    private val credentialStore: CredentialStore,
) {

    /** Observe all accounts (display-only, no credentials). */
    fun observeAll(): Flow<List<CloudAccountEntity>> = accountDao.observeAll()

    /**
     * Load a fully-hydrated account with credentials from encrypted storage.
     * Auto-migrates any legacy account whose credentialJson is still in the DB.
     */
    suspend fun getAccount(id: Long): CloudAccount? {
        val entity = accountDao.getById(id) ?: return null
        val credJson = resolveCredentials(entity)
        return entity.toDomain(credJson)
    }

    /**
     * Insert a new account. Credentials go to EncryptedSharedPreferences; the DB
     * row stores an empty placeholder so the plain database is never sensitive.
     */
    suspend fun insert(
        entity: CloudAccountEntity,
        credJson: String,
    ): Long {
        val id = accountDao.insert(entity.copy(credentialJson = ""))
        credentialStore.save(id, credJson)
        return id
    }

    /** Delete account from DB and wipe its credentials from the encrypted store. */
    suspend fun delete(entity: CloudAccountEntity) {
        accountDao.delete(entity)
        credentialStore.remove(entity.id)
    }

    // ── Internal helpers ──────────────────────────────────────────────────────

    private suspend fun resolveCredentials(entity: CloudAccountEntity): String {
        val stored = credentialStore.getCredJson(entity.id)
        if (stored != null) return stored

        // Legacy path: credential was saved to DB before encryption was added.
        // Migrate it on first access and clear the DB copy.
        val legacy = entity.credentialJson
        return if (legacy.isNotEmpty()) {
            credentialStore.save(entity.id, legacy)
            accountDao.update(entity.copy(credentialJson = ""))
            legacy
        } else {
            "{}"
        }
    }

    private fun CloudAccountEntity.toDomain(credJson: String) = CloudAccount(
        id = id,
        displayName = displayName,
        email = email,
        providerType = providerType,
        credentialJson = credJson,
        serverUrl = serverUrl,
        port = port,
    )
}
