package de.tsschulz.tt_tagebuch.shared.api

import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.BillingCreateRunBody
import de.tsschulz.tt_tagebuch.shared.api.models.BillingCreateRunEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.BillingGenerateBody
import de.tsschulz.tt_tagebuch.shared.api.models.BillingGenerateEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.BillingHoursPreviewEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.BillingRunsEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.BillingSettingsEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.BillingTemplatesEnvelope
import io.ktor.client.call.body
import io.ktor.client.request.delete
import io.ktor.client.request.forms.MultiPartFormDataContent
import io.ktor.client.request.forms.formData
import io.ktor.client.request.get
import io.ktor.client.request.parameter
import io.ktor.client.request.post
import io.ktor.client.request.setBody
import io.ktor.client.statement.readBytes
import io.ktor.http.ContentType
import io.ktor.http.Headers
import io.ktor.http.HttpHeaders
import io.ktor.http.contentType

class BillingApi(
    private val client: AuthedHttpClient,
) {
    suspend fun listTemplates(clubId: Int): BillingTemplatesEnvelope =
        client.http.get("/api/billing/templates/$clubId").body()

    suspend fun uploadTemplate(clubId: Int, name: String, description: String, pdfBytes: ByteArray, filename: String = "template.pdf") {
        client.http.post("/api/billing/templates/$clubId") {
            contentType(ContentType.MultiPart.FormData)
            setBody(
                MultiPartFormDataContent(
                    formData {
                        append("name", name)
                        append("description", description)
                        append(
                            "templatePdf",
                            pdfBytes,
                            Headers.build {
                                append(HttpHeaders.ContentType, "application/pdf")
                                append(HttpHeaders.ContentDisposition, "filename=\"$filename\"")
                            },
                        )
                    },
                ),
            )
        }
    }

    suspend fun deleteTemplate(templateId: Int) {
        client.http.delete("/api/billing/templates/$templateId")
    }

    suspend fun listRuns(clubId: Int): BillingRunsEnvelope =
        client.http.get("/api/billing/runs/$clubId").body()

    suspend fun getSettings(clubId: Int): BillingSettingsEnvelope =
        client.http.get("/api/billing/settings/$clubId").body()

    suspend fun hoursPreview(clubId: Int, monthFrom: String, monthTo: String): BillingHoursPreviewEnvelope =
        client.http.get("/api/billing/hours-preview/$clubId") {
            parameter("monthFrom", monthFrom)
            parameter("monthTo", monthTo)
        }.body()

    suspend fun createRun(clubId: Int, body: BillingCreateRunBody): BillingCreateRunEnvelope =
        client.http.post("/api/billing/runs/$clubId") {
            contentType(ContentType.Application.Json)
            setBody(body)
        }.body()

    suspend fun generateRun(runId: Int, locale: String = "de-DE"): BillingGenerateEnvelope =
        client.http.post("/api/billing/runs/$runId/generate") {
            contentType(ContentType.Application.Json)
            setBody(BillingGenerateBody(locale = locale))
        }.body()

    suspend fun downloadRunPdf(runId: Int): ByteArray =
        client.http.get("/api/billing/runs/$runId/download").readBytes()

    suspend fun deleteRun(runId: Int) {
        client.http.delete("/api/billing/runs/$runId")
    }
}
