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.client.request.forms.*
import io.ktor.http.*
import io.ktor.utils.io.core.*

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

    suspend fun getDocuments(
        token: String,
        residenceId: Int? = null,
        documentType: String? = null,
        // Deprecated filter args kept for source compatibility with iOS wrappers.
        // Backend/OpenAPI currently support: residence, document_type, is_active, expiring_soon, search.
        category: String? = null,
        contractorId: Int? = null,
        isActive: Boolean? = null,
        expiringSoon: Int? = null,
        tags: String? = null,
        search: String? = null
    ): ApiResult<List<Document>> {
        return try {
            val response = client.get("$baseUrl/documents/") {
                header("Authorization", "Token $token")
                residenceId?.let { parameter("residence", it) }
                documentType?.let { parameter("document_type", it) }
                isActive?.let { parameter("is_active", it) }
                expiringSoon?.let { parameter("expiring_soon", it) }
                search?.let { parameter("search", it) }
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                ApiResult.Error("Failed to fetch documents", response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

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

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                ApiResult.Error("Failed to fetch document", response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    suspend fun createDocument(
        token: String,
        title: String,
        documentType: String,
        residenceId: Int,
        description: String? = null,
        category: String? = null,
        tags: String? = null,
        notes: String? = null,
        contractorId: Int? = null,
        isActive: Boolean = true,
        // Warranty-specific fields
        itemName: String? = null,
        modelNumber: String? = null,
        serialNumber: String? = null,
        provider: String? = null,
        providerContact: String? = null,
        claimPhone: String? = null,
        claimEmail: String? = null,
        claimWebsite: String? = null,
        purchaseDate: String? = null,
        startDate: String? = null,
        endDate: String? = null,
        // File (optional for warranties) - kept for backwards compatibility
        fileBytes: ByteArray? = null,
        fileName: String? = null,
        mimeType: String? = null,
        // Multiple files support
        fileBytesList: List<ByteArray>? = null,
        fileNamesList: List<String>? = null,
        mimeTypesList: List<String>? = null
    ): ApiResult<Document> {
        return try {
            val response = if ((fileBytesList != null && fileBytesList.isNotEmpty() && fileNamesList != null && mimeTypesList != null) ||
                               (fileBytes != null && fileName != null && mimeType != null)) {
                // If files are provided, use multipart/form-data
                client.submitFormWithBinaryData(
                    url = "$baseUrl/documents/",
                    formData = formData {
                        append("title", title)
                        append("document_type", documentType)
                        append("residence_id", residenceId.toString())
                        description?.let { append("description", it) }
                        // Backend-supported fields
                        modelNumber?.let { append("model_number", it) }
                        serialNumber?.let { append("serial_number", it) }
                        // Map provider to vendor for backend compatibility
                        provider?.let { append("vendor", it) }
                        purchaseDate?.let { append("purchase_date", it) }
                        // Map endDate to expiry_date for backend compatibility
                        endDate?.let { append("expiry_date", it) }

                        // Backend accepts "file" field for single file upload
                        if (fileBytesList != null && fileBytesList.isNotEmpty() && fileNamesList != null && mimeTypesList != null) {
                            // Send first file as "file" (backend only accepts single file)
                            append("file", fileBytesList[0], Headers.build {
                                append(HttpHeaders.ContentType, mimeTypesList.getOrElse(0) { "application/octet-stream" })
                                append(HttpHeaders.ContentDisposition, "filename=\"${fileNamesList.getOrElse(0) { "file_0" }}\"")
                            })
                        } else if (fileBytes != null && fileName != null && mimeType != null) {
                            append("file", fileBytes, Headers.build {
                                append(HttpHeaders.ContentType, mimeType)
                                append(HttpHeaders.ContentDisposition, "filename=\"$fileName\"")
                            })
                        }
                    }
                ) {
                    header("Authorization", "Token $token")
                }
            } else {
                // If no file, use JSON
                val request = DocumentCreateRequest(
                    title = title,
                    documentType = documentType,
                    description = description,
                    modelNumber = modelNumber,
                    serialNumber = serialNumber,
                    vendor = provider, // Map provider to vendor
                    purchaseDate = purchaseDate,
                    expiryDate = endDate, // Map endDate to expiryDate
                    residenceId = residenceId
                )
                client.post("$baseUrl/documents/") {
                    header("Authorization", "Token $token")
                    contentType(ContentType.Application.Json)
                    setBody(request)
                }
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                val errorBody = try {
                    response.body<String>()
                } catch (e: Exception) {
                    "Failed to create document"
                }
                ApiResult.Error(errorBody, response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    suspend fun updateDocument(
        token: String,
        id: Int,
        title: String? = null,
        documentType: String? = null,
        description: String? = null,
        category: String? = null,
        tags: String? = null,
        notes: String? = null,
        contractorId: Int? = null,
        isActive: Boolean? = null,
        // Warranty-specific fields
        itemName: String? = null,
        modelNumber: String? = null,
        serialNumber: String? = null,
        provider: String? = null,
        providerContact: String? = null,
        claimPhone: String? = null,
        claimEmail: String? = null,
        claimWebsite: String? = null,
        purchaseDate: String? = null,
        startDate: String? = null,
        endDate: String? = null
    ): ApiResult<Document> {
        return try {
            // Backend update handler uses JSON via c.Bind (not multipart)
            val request = DocumentUpdateRequest(
                title = title,
                documentType = documentType,
                description = description,
                modelNumber = modelNumber,
                serialNumber = serialNumber,
                vendor = provider, // Map provider to vendor
                purchaseDate = purchaseDate,
                expiryDate = endDate // Map endDate to expiryDate
            )
            val response = client.patch("$baseUrl/documents/$id/") {
                header("Authorization", "Token $token")
                contentType(ContentType.Application.Json)
                setBody(request)
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                val errorBody = try {
                    response.body<String>()
                } catch (e: Exception) {
                    "Failed to update document"
                }
                ApiResult.Error(errorBody, response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

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

            if (response.status.isSuccess()) {
                ApiResult.Success(Unit)
            } else {
                ApiResult.Error("Failed to delete document", response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    suspend fun downloadDocument(token: String, url: String): ApiResult<ByteArray> {
        return try {
            val response = client.get(url) {
                header("Authorization", "Token $token")
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                ApiResult.Error("Failed to download document", response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    suspend fun activateDocument(token: String, id: Int): ApiResult<Document> {
        return try {
            val response = client.post("$baseUrl/documents/$id/activate/") {
                header("Authorization", "Token $token")
            }

            if (response.status.isSuccess()) {
                // Backend returns document directly
                val document: Document = response.body()
                ApiResult.Success(document)
            } else {
                ApiResult.Error("Failed to activate document", response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    suspend fun deactivateDocument(token: String, id: Int): ApiResult<Document> {
        return try {
            val response = client.post("$baseUrl/documents/$id/deactivate/") {
                header("Authorization", "Token $token")
            }

            if (response.status.isSuccess()) {
                // Backend returns document directly
                val document: Document = response.body()
                ApiResult.Success(document)
            } else {
                ApiResult.Error("Failed to deactivate document", response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    suspend fun uploadDocumentImage(
        token: String,
        documentId: Int,
        imageBytes: ByteArray,
        fileName: String = "image.jpg",
        mimeType: String = "image/jpeg",
        caption: String? = null
    ): ApiResult<Document> {
        return try {
            val response = client.submitFormWithBinaryData(
                url = "$baseUrl/documents/$documentId/images/",
                formData = formData {
                    append("image", imageBytes, Headers.build {
                        append(HttpHeaders.ContentType, mimeType)
                        append(HttpHeaders.ContentDisposition, "filename=\"$fileName\"")
                    })
                    caption?.let { append("caption", it) }
                }
            ) {
                header("Authorization", "Token $token")
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                val errorBody = try {
                    response.body<String>()
                } catch (e: Exception) {
                    "Failed to upload document image"
                }
                ApiResult.Error(errorBody, response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }

    suspend fun deleteDocumentImage(token: String, documentId: Int, imageId: Int): ApiResult<Document> {
        return try {
            val response = client.delete("$baseUrl/documents/$documentId/images/$imageId/") {
                header("Authorization", "Token $token")
            }

            if (response.status.isSuccess()) {
                ApiResult.Success(response.body())
            } else {
                ApiResult.Error("Failed to delete document image", response.status.value)
            }
        } catch (e: Exception) {
            ApiResult.Error(e.message ?: "Unknown error occurred")
        }
    }
}
