package com.tt.honeyDue.network

import com.tt.honeyDue.models.*
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.http.*

class TaskApi(private val client: HttpClient = ApiClient.httpClient) {
    private val baseUrl = ApiClient.getBaseUrl()

    suspend fun getTasks(
        token: String,
        days: Int? = null
    ): ApiResult<TaskColumnsResponse> {
        return try {
            val response = client.get("$baseUrl/tasks/") {
                header("Authorization", "Token $token")
                days?.let { parameter("days", it) }
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                val errorMessage = ErrorParser.parseError(response)
                ApiResult.Error(errorMessage, response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    suspend fun getTask(token: String, id: Int): ApiResult<TaskResponse> {
        return try {
            val response = client.get("$baseUrl/tasks/$id/") {
                header("Authorization", "Token $token")
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                val errorMessage = ErrorParser.parseError(response)
                ApiResult.Error(errorMessage, response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    suspend fun createTask(token: String, request: TaskCreateRequest): ApiResult<WithSummaryResponse<TaskResponse>> {
        return try {
            val response = client.post("$baseUrl/tasks/") {
                header("Authorization", "Token $token")
                contentType(ContentType.Application.Json)
                setBody(request)
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                val errorMessage = ErrorParser.parseError(response)
                ApiResult.Error(errorMessage, response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    /**
     * Atomically creates 1-50 tasks in a single transaction. Used by
     * onboarding and anywhere else that needs "all or nothing" task
     * creation. The server overrides every entry's residence_id with the
     * top-level request.residenceId.
     */
    suspend fun bulkCreateTasks(token: String, request: BulkCreateTasksRequest): ApiResult<BulkCreateTasksResponse> {
        return try {
            val response = client.post("$baseUrl/tasks/bulk/") {
                header("Authorization", "Token $token")
                contentType(ContentType.Application.Json)
                setBody(request)
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                val errorMessage = ErrorParser.parseError(response)
                ApiResult.Error(errorMessage, response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    suspend fun updateTask(token: String, id: Int, request: TaskCreateRequest): ApiResult<WithSummaryResponse<TaskResponse>> {
        return try {
            val response = client.put("$baseUrl/tasks/$id/") {
                header("Authorization", "Token $token")
                contentType(ContentType.Application.Json)
                setBody(request)
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                val errorMessage = ErrorParser.parseError(response)
                ApiResult.Error(errorMessage, response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    suspend fun deleteTask(token: String, id: Int): ApiResult<WithSummaryResponse<String>> {
        return try {
            val response = client.delete("$baseUrl/tasks/$id/") {
                header("Authorization", "Token $token")
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                val errorMessage = ErrorParser.parseError(response)
                ApiResult.Error(errorMessage, response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    suspend fun getTasksByResidence(
        token: String,
        residenceId: Int,
        days: Int? = null
    ): ApiResult<TaskColumnsResponse> {
        return try {
            val response = client.get("$baseUrl/tasks/by-residence/$residenceId/") {
                header("Authorization", "Token $token")
                days?.let { parameter("days", it) }
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                val errorMessage = ErrorParser.parseError(response)
                ApiResult.Error(errorMessage, response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    /**
     * Generic PATCH method for partial task updates.
     * Used for status changes and archive/unarchive operations.
     * Returns TaskWithSummaryResponse to update dashboard stats in one call.
     */
    suspend fun patchTask(token: String, id: Int, request: TaskPatchRequest): ApiResult<WithSummaryResponse<TaskResponse>> {
        return try {
            val response = client.patch("$baseUrl/tasks/$id/") {
                header("Authorization", "Token $token")
                contentType(ContentType.Application.Json)
                setBody(request)
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                val errorMessage = ErrorParser.parseError(response)
                ApiResult.Error(errorMessage, response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    // Convenience methods for common task actions
    // These use dedicated POST endpoints for state changes

    suspend fun cancelTask(token: String, id: Int): ApiResult<WithSummaryResponse<TaskResponse>> {
        return postTaskAction(token, id, "cancel")
    }

    suspend fun uncancelTask(token: String, id: Int): ApiResult<WithSummaryResponse<TaskResponse>> {
        return postTaskAction(token, id, "uncancel")
    }

    suspend fun markInProgress(token: String, id: Int): ApiResult<WithSummaryResponse<TaskResponse>> {
        return patchTask(token, id, TaskPatchRequest(inProgress = true))
    }

    suspend fun clearInProgress(token: String, id: Int): ApiResult<WithSummaryResponse<TaskResponse>> {
        return patchTask(token, id, TaskPatchRequest(inProgress = false))
    }

    suspend fun archiveTask(token: String, id: Int): ApiResult<WithSummaryResponse<TaskResponse>> {
        return postTaskAction(token, id, "archive")
    }

    suspend fun unarchiveTask(token: String, id: Int): ApiResult<WithSummaryResponse<TaskResponse>> {
        return postTaskAction(token, id, "unarchive")
    }

    /**
     * Helper for POST task action endpoints (cancel, uncancel, archive, unarchive)
     */
    private suspend fun postTaskAction(token: String, id: Int, action: String): ApiResult<WithSummaryResponse<TaskResponse>> {
        return try {
            val response = client.post("$baseUrl/tasks/$id/$action/") {
                header("Authorization", "Token $token")
                contentType(ContentType.Application.Json)
            }
            when (response.status) {
                HttpStatusCode.OK -> {
                    val data = response.body<WithSummaryResponse<TaskResponse>>()
                    ApiResult.Success(data)
                }
                HttpStatusCode.NotFound -> ApiResult.Error("Task not found", 404)
                HttpStatusCode.Forbidden -> ApiResult.Error("Access denied", 403)
                HttpStatusCode.BadRequest -> {
                    val errorBody = response.body<String>()
                    ApiResult.Error(errorBody, 400)
                }
                else -> ApiResult.Error("Task $action failed: ${response.status}", response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    /**
     * Get all completions for a specific task
     */
    suspend fun getTaskCompletions(token: String, taskId: Int): ApiResult<List<TaskCompletionResponse>> {
        return try {
            val response = client.get("$baseUrl/tasks/$taskId/completions/") {
                header("Authorization", "Token $token")
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                val errorMessage = ErrorParser.parseError(response)
                ApiResult.Error(errorMessage, response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }
}
