@file:Suppress("unused", "ClassName")

package viaduct.tenant.tutorial01

import org.junit.jupiter.api.Test
import viaduct.api.Resolver
import viaduct.graphql.test.assertEquals
import viaduct.tenant.runtime.fixtures.FeatureAppTestBase
import viaduct.tenant.tutorial01.resolverbases.QueryResolvers

/**
 * LEARNING OBJECTIVES:
 * - Understand the most basic Viaduct resolver pattern
 * - See how @resolver directive generates base classes
 * - Learn the relationship between SDL schema and Kotlin code
 *
 * VIADUCT FEATURES DEMONSTRATED:
 * - Field Resolvers
 * - Automatic code generation from SDL
 * - Context object usage
 *
 * CONCEPTS COVERED:
 * - SDL (Schema Definition Language) -> Kotlin class generation
 * - @resolver annotation registration
 * - Context.resolve() pattern
 *
 * NEXT: [viaduct.tenant.tutorial02.SimpleNodeResolverFeatureAppTest]
 */
class SimpleFieldResolverFeatureAppTest : FeatureAppTestBase() {
    // SCHEMA DEFINITION:
    // This SDL defines what your GraphQL API looks like to clients
    override var sdl = """
        | #START_SCHEMA
        | extend type Query {
        |   foo: String! @resolver  # <- @resolver tells Viaduct to generate QueryResolvers.Foo()
        | }
        | #END_SCHEMA
    """.trimMargin()

    /**
     * USER-IMPLEMENTED RESOLVER
     *
     * What YOU write:
     * - Extend the generated QueryResolvers.Foo() base class
     * - Implement resolve() method with your business logic
     * - Add @Resolver annotation to register with framework
     *
     * What VIADUCT generates:
     * - QueryResolvers.Foo() abstract base class
     * - Context object with proper typing
     * - Automatic wiring between GraphQL queries and your code
     */
    @Resolver // This registers your resolver with Viaduct
    class FooResolver : QueryResolvers.Foo() { // NodeResolvers.Foo was generated by Viaduct plugin's code generation
        override suspend fun resolve(ctx: Context): String {
            // YOUR BUSINESS LOGIC GOES HERE
            // This could be:
            // - Database queries: userRepository.findById(id)
            // - API calls: externalService.getData()
            // - Computations: calculateScore(data)
            // - Static data: return "bar" (for this example)

            return "bar"
        }
    }

    // TEST SETUP - Not part of the feature, just for demonstration
    @Test
    fun `Query returns a field resolver`() {
        execute(
            query = """
                query TestQuery {
                   foo  # This triggers FooResolver.resolve()
                }
            """.trimIndent()
        ).assertEquals {
            "data" to {
                "foo" to "bar" // Value computed by your FooResolver
            }
        }
    }

    /**
     * WHAT HAPPENS UNDER THE HOOD:
     *
     * 1. Client sends GraphQL query requesting "foo" field
     * 2. Viaduct sees @resolver in SDL and looks for registered resolver
     * 3. Finds your FooResolver (because of @Resolver annotation)
     * 4. Calls resolve() method you implemented
     * 5. Returns your computed value to the client
     *
     * KEY TAKEAWAYS:
     * - SDL defines the API contract (what clients see)
     * - @resolver generates base classes for you to implement
     * - Your job: implement resolve() with business logic
     * - Framework handles all GraphQL protocol details
     */
}
