import Foundation

public extension GenParamsSpec {
    /// The backend expects a JSON object for this field, and these underlying strings are flimsy and can even fail generation if incorrectly formed
    private struct Metadata: Codable {
        let lyricsModel: String?
        let createMode: String?
        let controlSliders: ControlSliders?
        let canControlSliders: [String]? // Mainly used for analytics

        struct ControlSliders: Codable {
            let weirdnessConstraint: Double?
            let styleWeight: Double?
            let audioWeight: Double?
        }
    }

    static func makeMetadata(
        createMode: String? = nil,
        lyricsModel: String? = "",
        weirdnessConstraint: Double? = nil,
        styleWeight: Double? = nil,
        audioWeight: Double? = nil,
        canControlSliders: [String]? = nil
    ) -> AnyJSON? {
        var controlSliders: Metadata.ControlSliders?
        /// Only make `controlSliders` if at least one of the values is provided
        if weirdnessConstraint != nil || styleWeight != nil || audioWeight != nil {
            controlSliders = Metadata.ControlSliders(
                weirdnessConstraint: weirdnessConstraint,
                styleWeight: styleWeight,
                audioWeight: audioWeight
            )
        }
        /// Make the `Metadata` object
        let metadata = Metadata(
            lyricsModel: lyricsModel,
            createMode: createMode,
            controlSliders: controlSliders,
            canControlSliders: canControlSliders
        )

        let encoder = JSONEncoder()
        encoder.keyEncodingStrategy = .convertToSnakeCase

        do {
            let json = try AnyJSON.from(metadata)
            return json
        } catch {
            assertionFailure("Error converting to AnyJSON: \(error)")
            return nil
        }
    }
}
