package com.tt.honeyDue.network

import io.ktor.client.HttpClient
import io.ktor.client.engine.mock.MockEngine
import io.ktor.client.engine.mock.respond
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.http.HttpMethod
import io.ktor.http.HttpStatusCode
import io.ktor.http.HttpHeaders
import io.ktor.http.headersOf
import io.ktor.serialization.kotlinx.json.json
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.Json
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

/**
 * Verifies the residence-invite accept/decline endpoints hit the correct
 * paths. Wired from [com.tt.honeyDue.notifications.NotificationActionReceiver]
 * when the user taps the Accept/Decline button on a `residence_invite`
 * push notification (iOS parity with `NotificationCategories.swift`).
 */
class ResidenceApiInviteTest {

    private fun mockClient(onRequest: (String) -> Unit): HttpClient =
        HttpClient(MockEngine) {
            engine {
                addHandler { req ->
                    onRequest(req.url.encodedPath)
                    respond(
                        content = "",
                        status = HttpStatusCode.OK,
                        headers = headersOf(HttpHeaders.ContentType, "text/plain")
                    )
                }
            }
            install(ContentNegotiation) {
                json(Json { ignoreUnknownKeys = true })
            }
        }

    @Test
    fun acceptResidenceInvite_hits_correct_endpoint() = runTest {
        var method: HttpMethod? = null
        var path: String? = null
        val client = HttpClient(MockEngine) {
            engine {
                addHandler { req ->
                    method = req.method
                    path = req.url.encodedPath
                    respond(
                        content = "",
                        status = HttpStatusCode.OK,
                        headers = headersOf(HttpHeaders.ContentType, "text/plain")
                    )
                }
            }
            install(ContentNegotiation) { json(Json { ignoreUnknownKeys = true }) }
        }
        val api = ResidenceApi(client)

        val result = api.acceptResidenceInvite("test-token", residenceId = 42)

        assertTrue(result is ApiResult.Success, "expected Success, got $result")
        assertEquals(HttpMethod.Post, method)
        assertTrue(
            path?.endsWith("/residences/42/invite/accept/") == true,
            "unexpected path: $path"
        )
        client.close()
    }

    @Test
    fun declineResidenceInvite_hits_correct_endpoint() = runTest {
        var method: HttpMethod? = null
        var path: String? = null
        val client = HttpClient(MockEngine) {
            engine {
                addHandler { req ->
                    method = req.method
                    path = req.url.encodedPath
                    respond(
                        content = "",
                        status = HttpStatusCode.OK,
                        headers = headersOf(HttpHeaders.ContentType, "text/plain")
                    )
                }
            }
            install(ContentNegotiation) { json(Json { ignoreUnknownKeys = true }) }
        }
        val api = ResidenceApi(client)

        val result = api.declineResidenceInvite("test-token", residenceId = 99)

        assertTrue(result is ApiResult.Success, "expected Success, got $result")
        assertEquals(HttpMethod.Post, method)
        assertTrue(
            path?.endsWith("/residences/99/invite/decline/") == true,
            "unexpected path: $path"
        )
        client.close()
    }

    @Test
    fun acceptResidenceInvite_surfaces_server_error() = runTest {
        val client = HttpClient(MockEngine) {
            engine {
                addHandler {
                    respond(
                        content = """{"detail":"Invite not found"}""",
                        status = HttpStatusCode.NotFound,
                        headers = headersOf(HttpHeaders.ContentType, "application/json")
                    )
                }
            }
            install(ContentNegotiation) { json(Json { ignoreUnknownKeys = true }) }
        }
        val api = ResidenceApi(client)

        val result = api.acceptResidenceInvite("test-token", residenceId = 1)

        assertTrue(result is ApiResult.Error, "expected Error, got $result")
        assertEquals(404, result.code)
        client.close()
    }
}
