package de.tsschulz.tt_tagebuch.shared.api

import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.models.AddDiaryNoteRequest
import de.tsschulz.tt_tagebuch.shared.api.models.AddFreeformActivityBody
import de.tsschulz.tt_tagebuch.shared.api.models.AddDiaryPlanGroupActivityRequest
import de.tsschulz.tt_tagebuch.shared.api.models.CreateDiaryDateRequest
import de.tsschulz.tt_tagebuch.shared.api.models.CreateDiaryPlanActivityRequest
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryDate
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryDateActivityItem
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryFreeformActivity
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryNote
import de.tsschulz.tt_tagebuch.shared.api.models.DiaryTag
import de.tsschulz.tt_tagebuch.shared.api.models.LinkDiaryTagRequest
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateDiaryPlanActivityOrderRequest
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateDiaryPlanActivityRequest
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateDiaryTimesRequest
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateNestedPlanGroupActivityRequest
import io.ktor.client.call.body
import io.ktor.client.request.delete
import io.ktor.client.request.get
import io.ktor.client.request.parameter
import io.ktor.client.request.post
import io.ktor.client.request.put
import io.ktor.client.request.setBody

class DiaryApi(
    private val client: AuthedHttpClient,
) {
    suspend fun listDates(clubId: Int): List<DiaryDate> {
        return client.http.get("/api/diary/$clubId").body()
    }

    suspend fun listFreeformActivities(diaryDateId: Int): List<DiaryFreeformActivity> {
        return client.http.get("/api/activities/$diaryDateId").body()
    }

    suspend fun addFreeformActivity(diaryDateId: Int, description: String): DiaryFreeformActivity {
        return client.http.post("/api/activities/add") {
            setBody(AddFreeformActivityBody(diaryDateId = diaryDateId, description = description.trim()))
        }.body()
    }

    suspend fun listDateActivities(clubId: Int, diaryDateId: Int): List<DiaryDateActivityItem> {
        return client.http.get("/api/diary-date-activities/$clubId/$diaryDateId").body()
    }

    suspend fun createDateActivity(clubId: Int, body: CreateDiaryPlanActivityRequest) {
        client.http.post("/api/diary-date-activities/$clubId") {
            setBody(body)
        }
    }

    suspend fun addDateGroupActivity(body: AddDiaryPlanGroupActivityRequest) {
        client.http.post("/api/diary-date-activities/group") {
            setBody(body)
        }
    }

    suspend fun updateDateActivity(clubId: Int, activityId: Int, body: UpdateDiaryPlanActivityRequest) {
        client.http.put("/api/diary-date-activities/$clubId/$activityId") {
            setBody(body)
        }
    }

    suspend fun updateDateActivityOrder(clubId: Int, activityId: Int, orderId: Int) {
        client.http.put("/api/diary-date-activities/$clubId/$activityId/order") {
            setBody(UpdateDiaryPlanActivityOrderRequest(orderId))
        }
    }

    suspend fun deleteDateActivity(clubId: Int, activityId: Int) {
        client.http.delete("/api/diary-date-activities/$clubId/$activityId")
    }

    suspend fun updateNestedGroupActivity(clubId: Int, groupActivityId: Int, body: UpdateNestedPlanGroupActivityRequest) {
        client.http.put("/api/diary-date-activities/group/$clubId/$groupActivityId") {
            setBody(body)
        }
    }

    suspend fun deleteNestedGroupActivity(clubId: Int, groupActivityId: Int) {
        client.http.delete("/api/diary-date-activities/group/$clubId/$groupActivityId")
    }

    suspend fun createDate(
        clubId: Int,
        date: String,
        trainingStart: String?,
        trainingEnd: String?,
        excludeFromBilling: Boolean = false,
    ): DiaryDate {
        return client.http.post("/api/diary/$clubId") {
            setBody(CreateDiaryDateRequest(date, trainingStart, trainingEnd, excludeFromBilling))
        }.body()
    }

    suspend fun updateTimes(
        clubId: Int,
        dateId: Int,
        trainingStart: String?,
        trainingEnd: String?,
        excludeFromBilling: Boolean? = null,
    ): DiaryDate {
        return client.http.put("/api/diary/$clubId") {
            setBody(UpdateDiaryTimesRequest(dateId, trainingStart, trainingEnd, excludeFromBilling))
        }.body()
    }

    suspend fun deleteDate(clubId: Int, dateId: Int) {
        client.http.delete("/api/diary/$clubId/$dateId")
    }

    suspend fun addNote(diaryDateId: Int, content: String): List<DiaryNote> {
        return client.http.post("/api/diary/note") {
            setBody(AddDiaryNoteRequest(diaryDateId, content))
        }.body()
    }

    suspend fun deleteNote(noteId: Int): List<DiaryNote> {
        return client.http.delete("/api/diary/note/$noteId").body()
    }

    suspend fun createTag(name: String): DiaryTag {
        return client.http.post("/api/tags") {
            setBody(mapOf("name" to name))
        }.body()
    }

    suspend fun listTags(): List<DiaryTag> {
        return client.http.get("/api/tags").body()
    }

    suspend fun linkTag(clubId: Int, diaryDateId: Int, tagId: Int): List<DiaryTag> {
        return client.http.post("/api/diary/tag/$clubId/add-tag") {
            setBody(LinkDiaryTagRequest(diaryDateId, tagId))
        }.body()
    }

    suspend fun removeTag(clubId: Int, tagId: Int) {
        client.http.delete("/api/diary/$clubId/tag") {
            parameter("tagId", tagId)
        }
    }
}
