package com.isidroid.job_sender.ext

import android.content.Context
import android.graphics.BitmapFactory
import com.isidroid.job.constant.SendJobStatus
import com.isidroid.job.model.PrintJob
import com.isidroid.job_sender.RenderBitmapProfileException
import com.isidroid.job_sender.SendJobEventCollectorFlow
import com.isidroid.job_sender.domain.model.PrintJobSender
import com.isidroid.rendering.constant.RenderConstant
import com.isidroid.rendering.model.RenderSettingsV2
import com.isidroid.rendering.repository.RenderRepository
import com.isidroid.spot.model.PrintProfile
import com.isidroid.spot.model.RichSpot
import com.isidroid.spot.repository.SpotRepository
import com.isidroid.utils.createTempFile
import com.isidroid.utils.md5
import com.isidroid.utils.saveToFile
import java.io.File

internal fun renderBitmapForPrint(
    context: Context,
    filePath: String,
    printProfile: PrintProfile?,
    printJob: PrintJob,
    renderRepository: RenderRepository
): File {
    printProfile ?: throw RenderBitmapProfileException("Print profile is null")

    val picture = BitmapFactory.decodeFile(filePath)
    val file = context.createTempFile(RenderConstant.RENDER_FOLDER)

    val updatedSettings = RenderSettingsV2(
        filePath = file.absolutePath,
        greyscale = printProfile.grayscale,
        isRealSize = true,
        orientation = printJob.printOrientation,
        printSize = printJob.printSize,
    )

    val result = renderRepository.renderBitmap(
        width = printProfile.width,
        height = printProfile.height,
        printWidth = printProfile.printWidth,
        printHeight = printProfile.printHeight,
        marginTop = printProfile.marginTop,
        marginLeft = printProfile.marginLeft,
        dpix = printProfile.dpix,
        dpiy = printProfile.dpiy,
        renderSettingsV2 = updatedSettings,
        picture = picture,
    )

    result.saveToFile(file)
    return file
}

internal fun createSingleRender(
    context: Context,
    renderRepository: RenderRepository,
    richSpots: List<RichSpot>?,
    printJob: PrintJob,
    source: String
): PrintJobSender? {
    val printJobId = printJob.id
    val richSpot = richSpots?.find { it.spot.id == printJob.spotId } ?: return null
    val printProfile = richSpot.printProfiles.find { it.id == printJob.profileId } ?: return null

    val id = "${source}_${printJobId}".md5

    val file = renderBitmapForPrint(
        context = context,
        filePath = source,
        printProfile = printProfile,
        printJob = printJob,
        renderRepository = renderRepository
    )

    return PrintJobSender(
        id = id,
        printJobId = printJobId,
        status = SendJobStatus.RENDERED,
        sourceFile = file.absolutePath,
        accessToken = printJob.accessToken.orEmpty(),
    )
}

internal suspend fun createRenderItems(
    context: Context,
    spotRepository: SpotRepository,
    renderRepository: RenderRepository,
    eventCollector: SendJobEventCollectorFlow,
    jobIdleList: Collection<PrintJob>
): Collection<PrintJobSender> {
    val richSpots = spotRepository.findLocalRichSpots(ids = jobIdleList.map { it.spotId })

    val result = jobIdleList.mapNotNull { printJob ->
        val jobTotal = printJob.sourceFiles.orEmpty().size
        var jobIndex = 0

        printJob.sourceFiles?.mapNotNull { source ->
            createSingleRender(context, renderRepository, richSpots, printJob, source)
                .also { eventCollector.renderProgress(printJob.id, ++jobIndex, jobTotal) }
        }
    }.flatten()

    return result
}