/*
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
package com.runicgateway.app.ui.contact

import com.runicgateway.app.data.api.dto.ContactResponse
import com.runicgateway.app.data.api.fake.FakePublicApi
import com.runicgateway.app.data.repository.ContactRepository
import com.runicgateway.app.ui.ErrorKind
import com.runicgateway.app.util.MainDispatcherRule
import com.runicgateway.app.util.httpError
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test

class ContactViewModelTest {

    @get:Rule val mainDispatcher = MainDispatcherRule()

    private val api = FakePublicApi()
    private fun viewModel() = ContactViewModel(ContactRepository(api))

    @Test fun blankFieldsProduceValidationError() {
        val vm = viewModel()
        vm.onNameChange("Gwen")
        vm.send() // email + message still blank
        assertEquals(ContactViewModel.Result.ValidationError, vm.state.value.result)
        assertEquals(null, api.lastContact) // never hit the API
    }

    @Test fun successfulSendClearsFieldsAndReportsSent() {
        api.contactResponse = ContactResponse(sent = true)
        val vm = viewModel()
        vm.onNameChange(" Gwen ")
        vm.onEmailChange(" g@x.c ")
        vm.onMessageChange(" hello ")
        vm.send()
        assertEquals(ContactViewModel.Result.Sent, vm.state.value.result)
        assertEquals("", vm.state.value.name) // fields cleared on success
        // Repository trims before sending.
        assertEquals("Gwen", api.lastContact!!.name)
        assertEquals("g@x.c", api.lastContact!!.email)
    }

    @Test fun mailerFallbackSurfacesEmail() {
        api.contactResponse = ContactResponse(sent = false, fallback = "mailto", email = "team@shard.gg")
        val vm = viewModel()
        vm.onNameChange("A"); vm.onEmailChange("a@b.c"); vm.onMessageChange("m")
        vm.send()
        val result = vm.state.value.result
        assertTrue(result is ContactViewModel.Result.Fallback)
        assertEquals("team@shard.gg", (result as ContactViewModel.Result.Fallback).email)
        // Fields kept (not a clean send) so the user can retry.
        assertEquals("A", vm.state.value.name)
    }

    @Test fun serverErrorSurfacesFailedWithKind() {
        api.error = httpError(500)
        val vm = viewModel()
        vm.onNameChange("A"); vm.onEmailChange("a@b.c"); vm.onMessageChange("m")
        vm.send()
        val result = vm.state.value.result
        assertTrue(result is ContactViewModel.Result.Failed)
        assertEquals(ErrorKind.SERVER, (result as ContactViewModel.Result.Failed).kind)
    }
}
