import os
import logging
import sys
import time

import markitdown
import smolagents

# Logs appear to be swallowed.
LOG = logging.getLogger(__name__)

SYSTEM_PROMPT = """
You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string.

The current date is April 30, 2025.

Take the time to plan the steps to reach the solution. Show the steps and then execute the steps.

The question is below:
"""

SUFFIX_PROMPT = """
Remember - The FINAL ANSWER must be a string, a number or a comma separated list that is only strings and numbers. No other output is allowed for a FINAL ANSWER! If any other output is provided other than a string, number or comma separated list that contains only strings and numbers, you fail. Don't fail.
"""


@smolagents.tool
def convert_from_url(url: str) -> str:
  """Convert data at a url into a markdown string.

   This method takes a url as input and converts the contents
   into a markdown. It can convert file formats such as
   pdf, excel, xlsx, csv, powerpoint, ppt, etc.

   It can also transcribe audio files such as mp3.

   Args:
     url: the url to access the file. If the file is on the
          local machine, the url should start with "file://"
          instead of the traditional "http://" or "https://".

   Returns:
     string that is in the markdown format.
   """
  # Don't need third-party plugins.
  md = markitdown.MarkItDown(enable_plugins=False)
  result = md.convert(url)
  return result.text_content


class BasicAgent:

  def check_results(self, final_answer, agent_memory):
    if isinstance(final_answer, str) or isinstance(
        final_answer, int) or isinstance(final_answer, float):
      return True
    failure = "FAILED! The final answer must be a string, a number or a comma separated list of strings and numbers."
    print(f"Feedback: {failure}")
    raise Exception(failure)

  def __init__(self):
    print("BasicAgent initializing.")

    # too big
    #    self.manager_model_id = "google/gemma-3-27B-it"
    #    self.manager_model_id = "OpenGVLab/InternVL3-14B"
    #    self.manager_model_id = "AIDC-AI/Ovis2-34B"

    self.manager_model_id = "meta-llama/Llama-3.3-70B-Instruct"
    self.manager_model = None

    self.code_model_id = "Qwen/Qwen2.5-Coder-32B-Instruct"
    self.code_model = None

    if not self.manager_model:
      self.manager_model = smolagents.HfApiModel(
          max_tokens=64000,
          temperature=0.3,
          model_id=self.manager_model_id,
          custom_role_conversions=None,
      )

    if not self.code_model:
      self.code_model = smolagents.HfApiModel(
          max_tokens=32000,
          temperature=0.3,
          model_id=self.code_model_id,
          custom_role_conversions=None,
      )

    print(f"NEW5: BasicAgent {self.manager_model_id=} {self.code_model_id=}")

    math_tools = [
        smolagents.FinalAnswerTool(),
    ]
    self.math_agent = smolagents.CodeAgent(
        name="date_time_math_agent",
        description="Handle date, time and math caclulations",
        model=self.code_model,
        tools=math_tools,
        max_steps=6,
        verbosity_level=2,
        planning_interval=None,
        additional_authorized_imports=["datetime", "time", "calendar"],
    )

    web_search_tools = [
        smolagents.DuckDuckGoSearchTool(),
        smolagents.VisitWebpageTool(),
        smolagents.FinalAnswerTool()
    ]

    self.web_search_agent = smolagents.CodeAgent(
        name="web_search_agent",
        description="Search the web",
        model=self.code_model,
        tools=web_search_tools,
        max_steps=6,
        verbosity_level=2,
        planning_interval=None,
        additional_authorized_imports=["duckduckgo_search"],
    )

    wikipedia_search_tools = [
        smolagents.WikipediaSearchTool(),
        smolagents.VisitWebpageTool(),
        smolagents.FinalAnswerTool()
    ]

    self.wikipedia_search_agent = smolagents.CodeAgent(
        name="wikipedia_search_agent",
        description="Best search of wikipedia pages",
        model=self.code_model,
        tools=wikipedia_search_tools,
        max_steps=6,
        verbosity_level=2,
        planning_interval=None,
        additional_authorized_imports=["wikipedia-api"],
    )

    manager_tools = [
        convert_from_url,
        smolagents.FinalAnswerTool(),
    ]
    self.manager_agent = smolagents.CodeAgent(
        name="manager_agent",
        description="Manger of other agents",
        tools=manager_tools,
        model=self.manager_model,
        add_base_tools=True,
        max_steps=15,
        verbosity_level=2,
        planning_interval=3,
        additional_authorized_imports=[
            "duckduckgo_search",
            "wikipedia-api",
            "markitdown",
            "requests",
            "pandas",
            "io",
        ],
        managed_agents=[
            self.web_search_agent,
            self.wikipedia_search_agent,
            self.math_agent,
            #            self.convert_files_to_markdown,
        ],
        final_answer_checks=[self.check_results],
    )

  def __call__(self, question: str) -> str:
    print(f"Agent received question (first 50 chars): {question[:50]}...")
    prompt = f'{SYSTEM_PROMPT}\n\n{question}\n\n {SUFFIX_PROMPT}'
    answer = self.manager_agent.run(prompt)
    print(f"{answer=}")
    return answer