package ac.mdiq.podcini.preferences

import ac.mdiq.podcini.preferences.AppPreferences.AppPrefs
import ac.mdiq.podcini.preferences.AppPreferences.getPref
import ac.mdiq.podcini.preferences.AppPreferences.putPref
import ac.mdiq.podcini.util.Logd
import ac.mdiq.podcini.util.Loge
import ac.mdiq.podcini.util.dateStampFilename
import android.app.Activity
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.IOException
import androidx.core.net.toUri

const val autoBackupDirName = "Podcini-AutoBackups"

fun autoBackup(activity: Activity) {
    val TAG = "autoBackup"

    val prefsDirName = "Podcini-Prefs"

    val isAutoBackup = getPref(AppPrefs.prefAutoBackup, false)
    if (!isAutoBackup) return
    val uriString = getPref(AppPrefs.prefAutoBackupFolder, "")
    if (uriString.isBlank()) return

    Logd("autoBackup", "in autoBackup directory: $uriString")

    fun deleteDirectoryAndContents(directory: DocumentFile): Boolean {
        if (directory.isDirectory) {
            directory.listFiles().forEach { file ->
                if (file.isDirectory) deleteDirectoryAndContents(file)
                Logd(TAG, "deleting ${file.name}")
                try { file.delete() } catch (e: Throwable) { Loge(TAG, "deleteDirectoryAndContents: failed to delete ${file.name} ${e.message}")}
            }
        }
        try { return  directory.delete() } catch (e: Throwable) { Loge(TAG, "deleteDirectoryAndContents: failed to delete ${directory.name} ${e.message}")}
        return false
    }

//    fun deleteDirectoryAndContents1(dir: DocumentFile): Boolean {
//        if (dir.isDirectory) {
//            dir.listFiles().forEach { child ->
//                val fresh = dir.findFile(child.name ?: return@forEach)
//                if (fresh != null) {
//                    if (fresh.isDirectory) deleteDirectoryAndContents1(fresh)
//                    Logd("DELETE", "Deleting ${fresh.name}")
//                    fresh.delete()
//                }
//            }
//        }
//        return dir.delete()
//    }

//    fun deleteDirectoryAndContents2(directory: DocumentFile): Boolean {
//        if (!directory.isDirectory) {
//            Logd(TAG, "deleting file: ${directory.name}")
//            return directory.delete()
//        }
//        val contents = directory.listFiles()
//        if (contents.isNotEmpty()) {
//            for (file in contents) {
//                if (file.isDirectory) {
//                    if (!deleteDirectoryAndContents2(file)) Loge(TAG, "deleteDirectoryAndContents Failed to recursively delete directory: ${file.name}")
//                } else {
//                    Logd(TAG, "deleting file: ${file.name}")
//                    if (!file.delete()) Loge(TAG, "deleteDirectoryAndContents Failed to delete file: ${file.name}")
//                }
//            }
//        }
//        Logd(TAG, "deleting empty parent directory: ${directory.name}")
//        return directory.delete()
//    }

    CoroutineScope(Dispatchers.IO).launch {
        val interval = getPref(AppPrefs.prefAutoBackupIntervall, 24)
        val lastBackupTime = getPref(AppPrefs.prefAutoBackupTimeStamp, 0L)
        val curTime = System.currentTimeMillis()
        if ((curTime - lastBackupTime) / 1000 / 3600 > interval) {
            val uri = uriString.toUri()
            val permissions = activity.contentResolver.persistedUriPermissions.find { it.uri == uri }
            if (permissions != null && permissions.isReadPermission && permissions.isWritePermission) {
                val chosenDir = DocumentFile.fromTreeUri(activity, uri)
                if (chosenDir != null) {
                    val backupDirs = mutableListOf<DocumentFile>()
                    try {
                        if (chosenDir.isDirectory) {
                            chosenDir.listFiles().forEach { file ->
                                Logd(TAG, "file: $file")
                                if (file.isDirectory && file.name?.startsWith(autoBackupDirName, ignoreCase = true) == true) backupDirs.add(file)
                            }
                        }
                        Logd(TAG, "backupDirs: ${backupDirs.size}")
                        val limit = getPref(AppPrefs.prefAutoBackupLimit, 2)
                        if (backupDirs.size >= limit) {
                            backupDirs.sortBy { it.name }
                            for (i in 0..(backupDirs.size - limit)) deleteDirectoryAndContents(backupDirs[i])
                        }

                        val dirName = dateStampFilename("$autoBackupDirName-%s")
                        val exportSubDir = chosenDir.createDirectory(dirName) ?: throw IOException("Error creating subdirectory $dirName")
                        val subUri: Uri = exportSubDir.uri
                        PreferencesTransporter(prefsDirName).exportToDocument(subUri, activity)
                        val realmFile = exportSubDir.createFile("application/octet-stream", "backup.realm")
                        if (realmFile != null) DatabaseTransporter().exportToDocument(realmFile.uri, activity)

                        putPref(AppPrefs.prefAutoBackupTimeStamp, curTime)
                    } catch (e: Exception) { Loge("autoBackup", "Error backing up ${e.message}") }
                }
            } else Loge("autoBackup", "Uri permissions are no longer valid")
        }
    }
}