using Revise
using YiemAgent, GeneralUtils, JSON3, DataStructures

thoughtDict = OrderedDict(
  :Question=> "Hello, I would like a get a bottle of wine",
  :Thought_1=> "The customer wants to buy a bottle of wine, but we need more information about their preferences.",
  :Action_1=> Dict(
      :name=> "chatbox",
      :input=> "What occasion are you buying the wine for?",
    ),
  :Observation_1=> "We are having a wedding pary this weekend.",

  :Thought_2=> "A wedding party is a great occasion to have a good bottle of wine.",
  :Action_2=> Dict(
      :name=> "chatbox",
      :input=> "What type of food will you be serving with the wine?",
    ),
  :Observation_2=> "I think it is Thai dishes",

  :Thought_3=> "Now that I know the occasion and food, I need to ask about the budget.",
  :Action_3=> Dict(
      :name=> "chatbox",
      :input=> "What is your budget for this wine?",
    ),
  :Observation_3=> "50 bucks",

  :Thought_4=> "With a budget of \$50, we have a wide range of options. Now that I know it's a wedding party and Thai dishes, I need to ask about the type of wine they prefer.",
  :Action_4=> Dict(
      :name=> "chatbox",
      :input=> "What type of wine are you looking for? (Red, White, Sparkling, Rose, Dessert, Fortified)",
    ),
  :Observation_4=> "Sparkling please.",

  :Thought_5=> "Now that I know the occasion, food, budget and preferred type of wine, it's time to check our inventory for the best matching wine.",
  :Action_5=> Dict(
      :name=> "winestock",
      :input=> "wine with budget \$50, Thai dishes, sparkling, wedding party",
    ),
  :Observation_5=> "I found the following wine in stock {1 : Zena Crown Vista, 2 : Schrader Cabernet Sauvignon}",
  
  :Thought_6=> "Now that I have all the information, it's time to recommend a wine that fits their preferences.",
  :Action_6=> Dict(
      :name=> "recommendation",
      :input=> "I recommend Zena Crown Vista for its sparkling and affordable price.",
    ),
  :Observation_6=> "I don't like it. Do you have another option?",
  )

_thoughtJsonStr = JSON.json(thoughtDict)
thoughtJsonStr = _thoughtJsonStr[1:end-1]  # remove } at the end
# @show thoughtJsonStr

_, latestThoughtIndice = GeneralUtils.findHighestIndexKey(thoughtDict, "Thought")
nextThoughtIndice = latestThoughtIndice + 1

_prompt = 
"""
You are a helpful sommelier working for a wine store. 
Your goal is to reccommend the best wine from your inventory that match the user preferences.

You must follow the following criteria:
1) Get to know what occasion the user is buying wine for
2) Get to know what food the user will have with wine
3) Get to know how much the user willing to spend
4) Get to know type of wine the user is looking for e.g. Red, White, Sparkling, Rose, Dessert, Fortified
5) Get to know what characteristics of wine the user is looking for 
    e.g. tannin, sweetness, intensity, acidity
6) Check your inventory for the best wine that match the user preference
7) Recommend wine to the user

You should only respond with interleaving Thought, Action, Observation steps. 
Thought can reason about the current situation, and Action can be three types:
1) winestock[query], which you can use to find wine in your inventory. The more input data the better.
2) chatbox[text], which you can use to interact with the user.
3) recommendation[answer], which returns your wine reccommendation to the user. 

You should only respond in JSON format as describe below:
{
  "Thought": "your reasoning",
  "Action": {"name": "action to take", "input": "Action input"},
  "Observation": "result of the action"
}

Here are some examples:
{
"Question": "I would like to buy a sedan with 8 seats.",
"Thought_1": "Our showroom carries various vehicle model. But I'm not sure whether we have a models that fits the user demand, I need to check our inventory.",
"Action_1": {"name": "inventory", "input": "sedan with 8 seats."},
"Observation_1": "Several model has 8 seats. Available color are black, red green"
}
{
  "Thought_2": "I have to ask the user what color he likes.",
  "Action_2": {"name": "chatbox", "input": "Which color do you like?"}
  "Observation_2": "I'll take black."
}
{
  "Thought_3": "There is only one model that fits the user preference. It's Yiem model A",
  "Action_3": {"name": "recommendation", "input": "I recommend a Yiem model A"}
}

Let's begin!

$(JSON.json(thoughtDict))
{Thought_$nextThoughtIndice
"""

prompt =  YiemAgent.formatLLMtext_llama3instruct("system", _prompt)
@show prompt
msgMeta = Dict(:requestResponse => nothing,
  :msgPurpose => nothing,
  :receiverId => nothing,
  :getPost => nothing,
  :msgId => "4c7111e0-c30e-44c3-8f85-1c8b3f03a8be",
  :acknowledgestatus => nothing,
  :replyToMsgId => nothing,
  :msgFormatVersion => nothing,
  :mqttServerInfo => Dict(:port => 1883, :broker => "mqtt.yiem.cc"),
  :sendTopic => "/loadbalancer/requestingservice",
  :receiverName => "text2textinstruct",
  :replyTopic => nothing,
  :senderName => "decisionMaker",
  :senderSelfnote => nothing,
  :senderId => "testingSessionID",
  :timeStamp => "2024-05-04T08:06:23.561"
  )

outgoingMsg = Dict(
  :msgMeta=> msgMeta,
  :payload=> Dict(
    :text=> prompt,
  )
)



_response = GeneralUtils.sendReceiveMqttMsg(outgoingMsg)
thoughtJsonStr = _response[:response][:text]






















