package com.swoosh.microblog.data

import com.swoosh.microblog.data.model.LinkPreview

/**
 * Builds Ghost mobiledoc JSON from text content, optional images, and optional link preview.
 * Extracted as a shared utility used by both ComposerViewModel and PostUploadWorker.
 */
object MobiledocBuilder {

    fun build(text: String, linkPreview: LinkPreview?): String {
        return build(text, linkUrl = linkPreview?.url, linkTitle = linkPreview?.title, linkDescription = linkPreview?.description)
    }

    /**
     * Builds mobiledoc JSON with support for multiple images (with optional alt text on the first),
     * optional video, optional audio, an optional link preview, and an optional file attachment.
     *
     * Card order: images -> video -> audio -> bookmark -> file
     */
    fun build(
        text: String,
        imageUrls: List<String> = emptyList(),
        linkUrl: String? = null,
        linkTitle: String? = null,
        linkDescription: String? = null,
        imageAlt: String? = null,
        videoUrl: String? = null,
        audioUrl: String? = null,
        fileUrl: String? = null,
        fileName: String? = null,
        fileSize: Long = 0
    ): String {
        val escapedText = escapeForJson(text).replace("\n", "\\n")

        val cards = mutableListOf<String>()
        val cardSections = mutableListOf<String>()

        // Add image cards
        for ((index, url) in imageUrls.withIndex()) {
            val escapedUrl = escapeForJson(url)
            // Apply alt text to the first image only
            val alt = if (index == 0 && imageAlt != null) escapeForJson(imageAlt) else ""
            cards.add("""["image",{"src":"$escapedUrl","alt":"$alt","caption":""}]""")
            cardSections.add("[10,${cards.size - 1}]")
        }

        // Add video card if present
        if (videoUrl != null) {
            val escapedUrl = escapeForJson(videoUrl)
            cards.add("""["video",{"src":"$escapedUrl","loop":false}]""")
            cardSections.add("[10,${cards.size - 1}]")
        }

        // Add audio card if present
        if (audioUrl != null) {
            val escapedUrl = escapeForJson(audioUrl)
            cards.add("""["audio",{"src":"$escapedUrl"}]""")
            cardSections.add("[10,${cards.size - 1}]")
        }

        // Add bookmark card if link is present
        if (linkUrl != null) {
            val escapedUrl = escapeForJson(linkUrl)
            val escapedTitle = linkTitle?.let { escapeForJson(it) } ?: ""
            val escapedDesc = linkDescription?.let { escapeForJson(it) } ?: ""
            cards.add("""["bookmark",{"url":"$escapedUrl","metadata":{"title":"$escapedTitle","description":"$escapedDesc"}}]""")
            cardSections.add("[10,${cards.size - 1}]")
        }

        // Add file card if file is present
        if (fileUrl != null) {
            val escapedFileUrl = escapeForJson(fileUrl)
            val escapedFileName = fileName?.let { escapeForJson(it) } ?: ""
            cards.add("""["file",{"src":"$escapedFileUrl","fileName":"$escapedFileName","fileSize":$fileSize}]""")
            cardSections.add("[10,${cards.size - 1}]")
        }

        val cardsJson = cards.joinToString(",")
        val cardSectionsJson = if (cardSections.isNotEmpty()) "," + cardSections.joinToString(",") else ""

        return """{"version":"0.3.1","atoms":[],"cards":[$cardsJson],"markups":[],"sections":[[1,"p",[[0,[],0,"$escapedText"]]]$cardSectionsJson]}"""
    }

    internal fun escapeForJson(value: String): String {
        return value.replace("\\", "\\\\").replace("\"", "\\\"")
    }
}
