package kr.lunaticbum.back.lun.service



import com.fasterxml.jackson.databind.ObjectMapper
import com.google.gson.Gson
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import io.micrometer.observation.ObservationRegistry
import kotlinx.coroutines.*
import kotlinx.coroutines.reactive.awaitSingle
import kr.lunaticbum.back.lun.configs.GlobalEnvironment
import kr.lunaticbum.back.lun.controllers.TelegramSendMsg
import kr.lunaticbum.back.lun.model.*
import kr.lunaticbum.back.lun.utils.RssFeedsParser
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.select.Elements
import org.openqa.selenium.By
import org.openqa.selenium.chrome.ChromeOptions
import org.openqa.selenium.remote.RemoteWebDriver
import org.springframework.ai.embedding.EmbeddingRequest
import org.springframework.ai.ollama.OllamaEmbeddingModel
import org.springframework.ai.ollama.api.OllamaApi
import org.springframework.ai.ollama.api.OllamaOptions
import org.springframework.ai.ollama.management.ModelManagementOptions
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.MediaType
import org.springframework.scheduling.annotation.Async
import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.BodyInserters
import org.springframework.web.reactive.function.client.WebClient
import reactor.kotlin.core.publisher.toMono
import java.net.URL
import java.net.URLEncoder
import java.text.SimpleDateFormat
import java.time.Duration
import java.util.*
import java.util.regex.Matcher
import java.util.regex.Pattern


@Service
class Lama {




    //, val date : String = SimpleDateFormat("yyyyMMddHHmmss").format(Date())
//    data class QSearchData(val query : FloatArray,val limit : Int)

    data class QSearchData(val vector : FloatArray,val limit : Int)
    data class QPut(val points : ArrayList<QData>)
    data class QData(val id : Long, val vector : FloatArray, val payload : SearXngResult)

    data class QContentsList(var ids : ArrayList<Long> = ArrayList(), var with_payload : Boolean = true, var with_vector : Boolean = false)
    //    fun makeCollection() : String{
//
//        class CollectionPut {
//            val name = "blama_vectors"
//            val vector_size = 3072
//            val distance = "Cosine"
//        }
//        val qUrl = "https://ollama.lunaticbum.kr/collections"
//        val client = WebClient.create()
//        return client.post()
//            .uri(qUrl)
//            .header("api-key","blama-admin-key-gb")
//            .body(BodyInserters.fromValue(Gson().toJson(CollectionPut())))
//            .retrieve()
//            .bodyToMono(String::class.java).timeout(Duration.ofMinutes(20L)).block() ?: ""
//    }

    private fun checkCollection() : Long {
        val qUrl = "https://ollama.lunaticbum.kr/collections/blama_vectors"
        val client = WebClient.create()
        return client.get()
            .uri(qUrl)
            .header("api-key", "blama-admin-key-gb")
            .retrieve()
            .bodyToMono(QCollection::class.java).timeout(Duration.ofMinutes(20L)).block()?.result?.points_count ?: 0L
    }

    fun jsopFilter(url : String) : String {
        val joinString = "\n#"
        var lastElements : Elements = Elements()
        var body = Jsoup.connect(url).timeout(30000).get().body()
        var elements : Elements? = null
        if (url.contains("nate.com", true)) {
            if (url.contains("view", true)) {
                elements = body.select("[class*=articleView]")
            }else {
                elements = body.select("[class*=postRankSubjectList]")
            }
        } else if (url.contains("newsis.com/view", true)) {
            elements = body.select("[class*=articleView]")
        } else if (url.contains("blog.naver.com", true)) {
            elements = body.select("[class*=se-viewer]")
        } else if (url.contains("bbc.com/korean/articles", true)) {
            elements = body.select("main[role$=main]")
        } else if (url.contains("chosun.com/client", true)) {
            elements = body.select("[class*=articleBody]")
        } else if (url.contains("nocutnews.co.kr/news", true)) {
            elements = body.select("[class*=container]")
        } else if (url.contains("hani.co.kr/arti/", true)) {
            elements = body.select("[class*=ArticleDetail]")
        } else if (url.contains("yna.co.kr/view", true)) {
            elements = body.select("[class*=container]")
        } else if (url.contains("newspim.com/news", true)) {
            elements = body.select("[class*=container]")
        } else {

        }
        if (elements?.size ?: 0 > 0) {
            elements?.forEach {
                lastElements.add(it)
            }
        }

        if (lastElements.size < 1) {
            arrayOf("container","article","main","viewer","content").forEach {
                var result = Elements()
                result.addAll(body.select("[class*=$it]"))
                result.addAll(body.select("[id*=$it]"))
                result.addAll(body.select(it))
                result.forEach { if (it.text().length > 100 && it.children().size < 5) { lastElements.add(it) } }
            }
        }
        return if (lastElements.size > 0) {
            lastElements.text()
        } else {
            body.text()
        }
    }

    fun jsopFilter(doc : Document) : String {
        var url = doc.baseUri()
        val joinString = "\n#"
        var lastElements : Elements = Elements()
        var body = doc
        var elements : Elements? = null
        if (url.contains("nate.com", true)) {
            if (url.contains("view", true)) {
                elements = body.select("[class*=articleView]")
            }else {
                elements = body.select("[class*=postRankSubjectList]")
            }
        } else if (url.contains("newsis.com/view", true)) {
            elements = body.select("[class*=articleView]")
        } else if (url.contains("blog.naver.com", true)) {
            elements = body.select("[class*=se-viewer]")
        } else if (url.contains("bbc.com/korean/articles", true)) {
            elements = body.select("main[role$=main]")
        } else if (url.contains("chosun.com/client", true)) {
            elements = body.select("[class*=articleBody]")
        } else if (url.contains("nocutnews.co.kr/news", true)) {
            elements = body.select("[class*=container]")
        } else if (url.contains("hani.co.kr/arti/", true)) {
            elements = body.select("[class*=ArticleDetail]")
        } else if (url.contains("yna.co.kr/view", true)) {
            elements = body.select("[class*=container]")
        } else if (url.contains("newspim.com/news", true)) {
            elements = body.select("[class*=container]")
        } else {

        }
        if (elements?.size ?: 0 > 0) {
            elements?.forEach {
                lastElements.add(it)
            }
        }

        if (lastElements.size < 1) {
            arrayOf("container","article","main","viewer","content").forEach {
                var result = Elements()
                result.addAll(body.select("[class*=$it]"))
                result.addAll(body.select("[id*=$it]"))
                result.addAll(body.select(it))
                result.forEach { if (it.text().length > 100 && it.children().size < 5) { lastElements.add(it) } }
            }
        }
        return if (lastElements.size > 0) {
            lastElements.text()
        } else {
            body.text()
        }
    }


//    class WebScrap {
//        @SerializedName("query", alternate = ["question"])
//        var query: String? = null
//        var original_html: String? = null
//        var original_content: String? = null
//        var summary: String? = null
//        var keywords: ArrayList<String>? = null
//        var related_links: ArrayList<String>? = null
//        var relatedness_score: Double = 0.0
//    }


    val embedimgModelEeve ="lancard/korean-yanolja-eeve"
    val embedimgModelBgeM3 = "bge-m3"
    val currentEmbedimg = embedimgModelBgeM3

    val llmPhi4 = "phi4:14b"
    val llmGemma3 = "gemma3:4b"
    val llmPhi4Mini = "phi4-mini"
    val llmDolphin3 = "dolphin3"

    var llm_gemma3_4b = "gemma3:4b"
    var llm_phi4_mini = "phi4-mini:latest"
    var llm_dolphin3 = "dolphin3:latest"
    var llm_gemma3_12b = "gemma3:12b"
    var llm_phi4_14b = "phi4:14b"
    var llm_mistral_7b = "mistral:7b"




    val currentLLM = llm_dolphin3
    fun getGoogleSearch(query:String){
        Jsoup.connect("https://www.google.com/search?q=".plus(query)).timeout(30000).get().select("a[href]").forEach {  }
    }

    val waitTime = 1500L
    val topCount = 2

    fun webDriver() : RemoteWebDriver {
        val options : ChromeOptions = ChromeOptions();
        options.addArguments("--headless");
        options.addArguments("--disable-popup-blocking");
        options.addArguments("--disable-default-apps");
        options.addArguments("--disable-notifications");
        options.addArguments("--disable-blink-features=AutomationControlled")
        return RemoteWebDriver(URL("https://video.lunaticbum.kr"), options)
    }

    fun isValidUrl(url: String): Boolean {
        val urlRegex = "^(https?|ftp)://[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)$".toRegex()
        return url.matches(urlRegex)
    }

    @Async
    suspend fun getterUrl(urlString: String) {
        try {
            webDriver()?.let { driver ->
                var findCount = 0
                try {
                    driver.get("urlString");
                    Thread.sleep(waitTime)
                    println(driver.currentUrl)
                    driver.findElement(By.ByTagName("Body"))?.let { webElement ->
                        Jsoup.parse(driver.pageSource).select("[href*=https]").forEach {
                            var href = it.attr("href")
                            println(href)
                        }
                    }

                }catch (e:Exception){
                    e.printStackTrace()
                }
                driver.close()
                driver.quit()
            }
        }catch (e:Exception){}
    }


    @Async
    suspend fun addDocuments(query : String , refinedQuery: RefinedQuery?) {
        var querys : ArrayList<String> = ArrayList()
        querys.add(query)

        refinedQuery?.ko_query?.let { querys.add(it) }
        refinedQuery?.en_query?.let { querys.add(it) }
        refinedQuery?.ko_keywords?.let { querys.add(it.joinToString( " "))}
        refinedQuery?.en_keywords?.let { querys.add(it.joinToString( " "))}
        val readedUrls = ArrayList<String>()

        try {

            val targetUrls = hashSetOf<String>()

            querys.forEach { refinedQuery->
                try {
                    webDriver()?.let { driver ->
                        var findCount = 0
                        try {
                            driver.get("https://www.google.com/search?q=$refinedQuery");
                            Thread.sleep(waitTime)
                            println(driver.currentUrl)
                            driver.findElement(By.ByTagName("Body"))?.let { webElement ->
                                Jsoup.parse(driver.pageSource).select("[href*=https]").forEach {
                                    var href = it.attr("href")
                                    if (href?.length ?: 0 > 5 && href.startsWith("https://") && findCount < topCount && href.contains("google") == false && href.contains("youtube") == false) {
                                        targetUrls.add(href)
                                        println("add targetUrls $href")
                                        findCount += 1
                                    }
                                }
                            }

                        }catch (e:Exception){
                            e.printStackTrace()
                        }
                        driver.close()
                        driver.quit()
                    }
                }catch (e:Exception){}
            }

            querys.forEach { refinedQuery ->
                try {
                    webDriver()?.let { driver ->
                        var findCount = 0
                        RssFeedsParser().readFeed("https://news.google.com/rss/search?q=${URLEncoder.encode(refinedQuery)}=ko&gl=KR&ceid=KR%3Ako/")?.messages?.forEach {
                            var url: String? = it.link
                            if (url?.length ?: 0 > 5 && url?.startsWith("https://") == true && readedUrls.contains(url) == false && findCount < topCount) {
                                println("url >>>> $url")
                                targetUrls.add(url!!)
                                findCount += 1
                            }
                        }
                        driver.close()
                        driver.quit()
                    }
                }catch (e:Exception){
                }

            }


            targetUrls.forEach { url ->
                webDriver()?.let { driver ->
                    var result = SearXngResult()
                    if (url?.length ?: 0 > 5 && url?.startsWith("https://") == true && readedUrls.contains(url) == false) {
                        readedUrls.add(url!!)
                        result.url = url!!
                        result.originQuery = query
                        try {
                            driver.get(url);
                            Thread.sleep(waitTime)
                            driver.findElement(By.ByTagName("Body"))?.let { webElement ->
                                jsopFilter(Jsoup.parse(driver.pageSource)).let { text ->
                                    result.originHtml = text
                                    webPageSummarize(result)
                                }
                            }
                        } catch (e: Exception) {
//                            e.printStackTrace()
                        }
                    }
                    driver.close();
                    driver.quit()
                }
            }


        } catch (e:Exception){e.printStackTrace()}

        querys.forEach { refinedQuery ->
            val gSearch = "https://psn.lunaticbum.kr/search?q=${refinedQuery?.replace("오늘", SimpleDateFormat("yyyMMdd").format(Date()))}&language=ko&time_range=month&safesearch=0&categories=general&format=json"
//            println("gSearch >>> ${gSearch}")
            WebClient.create().get()
                .uri(gSearch)
                .retrieve()
                .bodyToMono(SearXng::class.java).timeout(Duration.ofMinutes(20L)).block()?.let { gsResult ->
                    gsResult.results?.filter { it.url?.startsWith("https://") == true && it.score > 5.0 }?.forEach {
                        if (readedUrls.contains(it.url) == false) {
                            readedUrls.add(it.url!!)
                            it.originQuery = query
                            it.refinedQuery = refinedQuery
                            try {
                                webDriver()?.let { driver ->
                                    driver.get(it.url!!)
                                    Thread.sleep(waitTime)
                                    driver.findElement(By.ByTagName("Body"))?.let { webElement ->
                                        jsopFilter(it.url!!).let { text ->
                                            it.originHtml = text
                                            webPageSummarize(it)
                                        }
                                    }
                                    driver.close()
                                    driver.quit()
                                }
                            } catch (e: Exception) {
                                e.printStackTrace()
                            }
                        }
                    }
                }
//            println("end of search")
        }
    }

    var format = "\"context:'%s'\n" +
            "The context is extracted text from a web page. '%s' is the content received as a relevant result for this question. Please analyze and summarize the given context in detail, and provide the following information in JSON format.\n" +
            "\n" +
            "Please provide the result in this format, ensuring that all information is in Korean language."


    var webSummaryResultFormat : String = """{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "description": "Original question"
    },
    "contents_ko": {
      "type": "string",
      "description": "Detailed content in Korean"
    },
    "summary_ko": {
      "type": "string",
      "description": "Concise summary in Korean"
    },
    "keywords": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1
    },
    "related_links": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "link": { "type": "string" },
          "description": { "type": "string" }
        },
        "required": ["link", "description"],
        "additionalProperties": false
      }
    },
    "relatedness_score": {
      "type": "number",
      "minimum": 0.0,
      "maximum": 10.0
    }
  },
  "required": ["query", "contents_ko", "summary_ko", "keywords", "related_links", "relatedness_score"],
  "additionalProperties": false
}""";


    internal fun makeSummarizeRequestMsg(it : SearXngResult) : String= format.format(it.originHtml,it.originQuery)

    internal fun makeCahtReq(reqMsg:String, ollamaOptions: OllamaOptions?, format: Any) = OllamaApi.ChatRequest.Builder(currentLLM).options(ollamaOptions).stream(false).format(format).messages(reqMsg.chunked(100).map { OllamaApi.Message.Builder(OllamaApi.Message.Role.USER).content(it).build()}.toList()).build()
    var options = OllamaOptions.builder().build()//.temperature(0.8).topK(3).seed(30)

    @Async
    fun webPageSummarize(it : SearXngResult) {
        try {
//            println("send to blama >> ${it.url}")
            infomationDic.get(it.originQuery)?.put(it.url!!,Gson().toJson(it))
            try {
                CoroutineScope(Dispatchers.IO).launch {
                    val chatClient = OllamaApi("https://lama.lunaticbum.kr")
                    chatClient.chat(makeCahtReq(makeSummarizeRequestMsg(it), options, ObjectMapper().readValue(webSummaryResultFormat,Map::class.java))).toMono().subscribe({aiResponce ->
                        it.pageData = aiResponce.message.content
                        var needSave = true
                        try {
                            var jsonObj = JsonParser.parseString(aiResponce.message.content)
                            needSave = jsonObj.isJsonObject && (jsonObj as JsonObject)?.get("relatedness_score")?.asDouble ?: 0.0 > 0.5 } catch (e: Exception) {
                            e.printStackTrace()
                        }
                        if (needSave) {
                            sendTlg("유효한 정보가 수집됨.".plus(aiResponce.message.content))
                            val embeddingModel = OllamaEmbeddingModel(chatClient, OllamaOptions.builder().build(), ObservationRegistry.create(), ModelManagementOptions.defaults())
                            val embeddingResponse = embeddingModel.call(EmbeddingRequest(Gson().toJson(it).chunked(400).toList(), OllamaOptions.builder().model(currentEmbedimg).truncate(false).build()))

                            val sdss = QPut(arrayListOf())
                            sdss.points.add(QData(id = System.currentTimeMillis(), embeddingResponse.result.output, it))
                            if (sdss.points.size > 0) {
                                val qUrl = "https://ollama.lunaticbum.kr/collections/blama_vectors".plus("/points")
                                val client = WebClient.create()
                                client.put()
                                    .uri(qUrl)
                                    .header("api-key", "blama-admin-key-gb")
                                    .body(BodyInserters.fromValue(Gson().toJson(sdss)))
                                    .retrieve()
                                    .bodyToMono(String::class.java).timeout(Duration.ofMinutes(20L)).subscribe(
                                        { resultString -> }, { error -> error.printStackTrace() }
                                    )
                            }}
                    },{err->
                        err.printStackTrace()
                    })
                }
            }
            catch (e:Exception){e.printStackTrace()}
        }catch (e : Exception) {
            e.printStackTrace()
        }
    }

    class RefinedQuery {
        var ko_query : String? = null
        var en_query : String? = null
        var ko_keywords : Array<String>? = null
        var en_keywords : Array<String>? = null
    }


    var jsonSchema: String = """{
  "type": "object",
  "properties": {
    "ko_query": {
      "type": "string",
      "description": "korean query"
    },
    "en_query": {
      "type": "string",
      "description": "english query"
    },
    "ko_keywords": {
      "type": "array",
      "items": { "type": "string" },
      "minItems": 1,
      "description": "korean keywords"
    },
    "en_keywords": {
      "type": "array",
      "items": { "type": "string" },
      "minItems": 1,
      "description": "query keyword"
    }
  },
  "required": ["ko_query", "en_query", "ko_keywords", "en_keywords"],
  "additionalProperties": false
}""".trimIndent()
    var queryFormat = "Question:\n'%s'\nBased on the above question, please provide a JSON result formatted\nPlease ensure:\n1. Faithful translation maintaining original intent\n2. Keyword extraction focusing on core concepts\n3. Bilingual keyword matching\n4. Proper JSON formatting"

    internal fun makeQuerySummarizeRequestMsg(query : String) : String= queryFormat.format(query)
    fun querySummarize(query: String) : RefinedQuery? {
        var refinedQuery : RefinedQuery? = null
        try {
            val chatClient = OllamaApi("https://lama.lunaticbum.kr")
            var dispoable = chatClient.chat(makeCahtReq(makeQuerySummarizeRequestMsg(query),options, ObjectMapper().readValue(jsonSchema,Map::class.java))).toMono().subscribe({aiResponce ->
                println("summary result >>>>>  ${aiResponce.message.content}")
                refinedQuery =  Gson().fromJson(aiResponce.message.content, RefinedQuery::class.java)
            },{err->
                err.printStackTrace()
            })
        }catch (e : Exception) {

            e.printStackTrace()
        }
        return refinedQuery
    }


    @Async
    public fun embedQuery(embedFlots : FloatArray) : QContents?{
        val qUrl = "https://ollama.lunaticbum.kr/collections/blama_vectors".plus("/points/search")
        val client = WebClient.create()
        var lists = client.post()
            .uri(qUrl)
            .header("api-key","blama-admin-key-gb")
            .body(BodyInserters.fromValue(Gson().toJson(QSearchData(embedFlots,3))))
            .retrieve()
            .bodyToMono(QSearch::class.java).timeout(Duration.ofMinutes(20L)).block()

        return if (lists?.result?.size ?: 0 > 0) {
            val qContents = QContentsList()
            lists?.result?.filter { it.score > 8.0 }?.forEach { qContents.ids.add(it.id) }
            val qCUrl = "https://ollama.lunaticbum.kr/collections/blama_vectors".plus("/points")
            val client2 = WebClient.create()
            client2.post()
                .uri(qCUrl)
                .header("api-key", "blama-admin-key-gb")
                .body(BodyInserters.fromValue(Gson().toJson(qContents)))
                .retrieve()
                .bodyToMono(QContents::class.java).timeout(Duration.ofMinutes(20L)).block()
        } else {
            null
        }
    }

    @Autowired
    lateinit var globalEvv : GlobalEnvironment


    val resultJsonScheme = """{
"type": "object",
"properties": {
"querys": {
"type": "array",
"items": {
"type": "string"
},
"description": "사용자의 질문 목록"
},
"answers": {
"type": "array",
"items": {
"type": "string"
},
"description": "질문에 대한 상세한 답변 목록"
},
"keywords": {
"type": "array",
"items": {
"type": "string"
},
"description": "답변과 관련된 주요 키워드 목록"
},
"links": {
"type": "array",
"items": {
"type": "string"
},
"description": "참고할 만한 관련 링크 목록"
}
},
"required": ["querys", "answers", "keywords", "links"],
"additionalProperties": false
}""".trimIndent()

    var infomationDic = hashMapOf<String,HashMap<String,String>>()
    suspend fun generateResponse(query: String, targetId: String? = globalEvv.telegramMyId) {

        if (isValidUrl(query)) {
            getterUrl(query)
        }else {

            val fullUrl = "https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage"
            val chatClient = OllamaApi("https://lama.lunaticbum.kr")
            val embeddingModel = OllamaEmbeddingModel(
                chatClient,
                OllamaOptions.builder().build(),
                ObservationRegistry.create(),
                ModelManagementOptions.defaults()
            )
            println("On generateResponse :: find something ${query}")

            query.let { originalQuery ->
                infomationDic.put(query!!, hashMapOf())

                try {
                    var embeddingResponse = embeddingModel.call(
                        EmbeddingRequest(
                            listOf(originalQuery),
                            OllamaOptions.builder().model(currentEmbedimg).truncate(false).build()
                        )
                    )
                    addDocuments(originalQuery, querySummarize(originalQuery))
                    println("points size  ${embeddingResponse.result.output.size}")
                    var context: StringBuffer = StringBuffer()
                    embedQuery(embeddingResponse.result.output)?.result?.forEach { result ->
                        if (infomationDic.get(query!!)!!.contains(result.payload?.url ?: "NONE") == false) {
                            context.append(
                                "\nReference:#".plus(
                                    if (result.payload?.pageData?.length ?: 0 > 10) {
                                        result.payload?.pageData
                                    } else {
                                        result.payload?.content
                                    }
                                )
                            )
                        }
                    }

                    infomationDic.get(query!!)!!.iterator()
                        .forEach { context.append("\nReference:#${it.key}:${it.value}") }


                    val prompt: StringBuffer = StringBuffer()
                    prompt.append(context)
                    prompt.append("\nConsidering the above reference, please answer the following question:\n'$query'\n\nProvide a detailed response in the following JSON format\nPlease ensure all content is in Korean language and as detailed as possible.")


                    val answers = StringBuffer()
                    chatClient.streamingChat(OllamaApi.ChatRequest.Builder(currentLLM).stream(true)
                        .format(ObjectMapper().readValue(resultJsonScheme, Map::class.java)).messages(
                        prompt.chunked(1024)
                            .map { OllamaApi.Message.Builder(OllamaApi.Message.Role.USER).content(it).build() }.toList()
                    ).build()
                    ).timeout(Duration.ofMinutes(20)).subscribe({ responce ->
                        answers.append(responce.message.content)
                        println("responce.message.content >>> ${answers.length}")
                        try {
                            if (answers.length % 100 == 0) {
                                var tlgSend = TelegramSendMsg(
                                    targetId ?: globalEvv.telegramMyId!!,
                                    "결과를 수집 중 ${responce.message.content.length}의 문자열이 추가됨. 수집된 통 데이터는 ${answers.length}"
                                )
                                WebClient
                                    .create(fullUrl)
                                    .post()
                                    .contentType(MediaType.APPLICATION_JSON)
                                    .body(BodyInserters.fromValue(Gson().toJson(tlgSend)))
                                    .retrieve().bodyToMono(String::class.java).timeout(Duration.ofMinutes(20L))
                                    .block()?.let { result ->
                                        println("result >>> ${result}")
                                    }
                            }
                        } catch (e: Exception) {
                            e.printStackTrace()
                        }

                    }, { error ->

                    }, {
                        var toalmsg: StringBuffer = StringBuffer("${query}의 대답이 도착했어요.\n").append(answers.toString())
                        sendTlg(toalmsg.toString())
                        infomationDic.remove(query)
                        println("On generateResponse :: END OF Answer")
                    })

                } catch (e: Exception) {
                    e.printStackTrace()
                }

            }
        }
    }


    fun sendTlg(toalmsg : String) {
        telegramScope.launch {
            val fullUrl = "https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage"
            toalmsg.chunked(512).forEach { chunkedMsg ->
                launch {
                    println("chunkedMsg >>> ${chunkedMsg}")
                    globalEvv.telegramMyId?.let {
                        try {
                            var tlgSend = TelegramSendMsg(it, chunkedMsg)
                            WebClient
                                .create(fullUrl)
                                .post()
                                .contentType(MediaType.APPLICATION_JSON)
                                .body(BodyInserters.fromValue(Gson().toJson(tlgSend)))
                                .retrieve().bodyToMono(String::class.java).timeout(Duration.ofMinutes(20L))
                                .awaitSingle()?.let { result ->
                                    println("result >>> ${result}")
                                }
                        }catch (e:Exception){
                            e.printStackTrace()
                        }
                    }
                }
            }
        }
    }
    private val telegramScope = CoroutineScope(Dispatchers.IO + SupervisorJob())

//    fun sendTlg2(toalmsg: String) {
//        telegramScope.launch {
//            val fullUrl = "https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage"
//            val chunkedMessages = toalmsg.chunked(512)
//            chunkedMessages.forEach { chunkedMsg ->
//                launch {
//                    try {
//                        globalEvv.telegramMyId?.let { chatId ->
//                            val tlgSend = TelegramSendMsg(chatId, chunkedMsg)
//                            val result = WebClient.create(fullUrl)
//                                .post()
//                                .contentType(MediaType.APPLICATION_JSON)
//                                .bodyValue(Gson().toJson(tlgSend))
//                                .retrieve()
//                                .awaitBody<String>()
//
//                            println("Telegram send success: $result")
//                        }
//                    } catch (e: Exception) {
//                        println("Telegram send failed: ${e.localizedMessage}")
//                        // 추가 에러 처리 로직
//                    }
//                }
//            }
//        }
//    }
}