package com.keylightpiano.pianotimeline.data.remote

import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit

/**
 * Central place that knows your server layout and builds the HTTP stack.
 * Everything media-related lives under this one base directory.
 */
object MusicNetwork {

    const val BASE_URL = "https://timeline.keylightpiano.com/music/"

    /**
     * JSON parser config.
     * - ignoreUnknownKeys: we don't model "generated-at", and this future-proofs
     *   the app against new server-side fields.
     * - isLenient: tolerates minor formatting slack.
     */
    private val json = Json {
        ignoreUnknownKeys = true
        isLenient = true
    }

    private val logging = HttpLoggingInterceptor().apply {
        // BODY in debug is verbose but invaluable while building. Dial down later.
        level = HttpLoggingInterceptor.Level.BASIC
    }

    private val okHttp: OkHttpClient = OkHttpClient.Builder()
        .addInterceptor(logging)
        .build()

    private val retrofit: Retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .client(okHttp)
        .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
        .build()

    val api: MusicApi = retrofit.create(MusicApi::class.java)

    /** The shared OkHttp client, reused later for streaming file downloads. */
    val httpClient: OkHttpClient get() = okHttp

    /**
     * Builds a correct, percent-encoded URL for a media file living next to list.json.
     * OkHttp's HttpUrl builder handles the encoding of spaces, '#', '&', apostrophes,
     * accented characters, etc. — so we never hand-concatenate raw filenames.
     */
    fun fileUrl(fileName: String): String =
        BASE_URL.toHttpUrl()
            .newBuilder()
            .addPathSegment(fileName)   // addPathSegment encodes the segment for us
            .build()
            .toString()
}
