package cy.agorise.bitsybitshareswallet.domain.usecase

import android.content.Context
import android.util.Log
import androidx.core.os.ConfigurationCompat
import androidx.documentfile.provider.DocumentFile
import com.opencsv.CSVWriter
import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.database.joins.TransferDetail
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.OutputStreamWriter
import java.text.SimpleDateFormat
import java.util.*
import kotlin.math.pow

class ExportTransactionsToCsvUseCase(private val applicationContext: Context) {

    suspend operator fun invoke(
        transactions: List<TransferDetail>,
        folderDocumentFile: DocumentFile
    ) = withContext(Dispatchers.IO) { // TODO Inject Dispatcher
        // Create the PDF file name
        val fileName = applicationContext.resources.let {
            "${it.getString(R.string.app_name)}-${it.getString(R.string.title_transactions)}.csv"
        }

        // Obtains the path to store the PDF
        val csvDocUri = folderDocumentFile.createFile("text/csv", fileName)?.uri
        val contentResolver = applicationContext.contentResolver
        val csvOutputStream = contentResolver.openOutputStream(csvDocUri!!, "w")
        val csvWriter = CSVWriter(OutputStreamWriter(csvOutputStream))

        // Add the table header
        csvWriter.writeNext(
            arrayOf(
                R.string.title_from, R.string.title_to, R.string.title_memo, R.string.title_date,
                R.string.title_time, R.string.title_amount, R.string.title_equivalent_value
            ).map { columnNameId -> applicationContext.getString(columnNameId) }.toTypedArray()
        )

        // Configure date and time formats to reuse in all the transfers
        val locale = ConfigurationCompat.getLocales(applicationContext.resources.configuration)[0]
        val dateFormat = SimpleDateFormat("MM-dd-yyyy", locale)
        val timeFormat = SimpleDateFormat("HH:mm:ss", locale)

        // Save all the transfers information
        val row = Array(7) { "" }     // Array initialized with empty strings
        for ((index, transferDetail) in transactions.withIndex()) {
            val date = Date(transferDetail.date * 1000)

            row[0] = transferDetail.from ?: ""          // From
            row[1] = transferDetail.to ?: ""            // To
            row[2] = transferDetail.memo                // Memo
            row[3] = dateFormat.format(date)            // Date
            row[4] = timeFormat.format(date)            // Time

            // Asset Amount
            val assetPrecision = transferDetail.assetPrecision
            val assetAmount = transferDetail.assetAmount / 10.0.pow(assetPrecision)
            row[5] =
                String.format("%.${assetPrecision}f %s", assetAmount, transferDetail.assetSymbol)

            // Fiat Equivalent
            row[6] = if (transferDetail.fiatAmount != null && transferDetail.fiatSymbol != null) {
                val currency = Currency.getInstance(transferDetail.fiatSymbol)
                val fiatAmount = transferDetail.fiatAmount / 10.0.pow(currency.defaultFractionDigits)
                String.format(
                    "%.${currency.defaultFractionDigits}f %s",
                    fiatAmount,
                    currency.currencyCode
                )
            } else {
                ""
            }

            csvWriter.writeNext(row)

            // TODO update progress
        }

        csvWriter.close()

        Log.d("ExportTransactionsToCsv", "CSV generated and saved")
    }
}
