#
#   Imandra Inc.
#
#   main.py - Main entrypoint for CodeLogician
#

import logging
from typing import Annotated, Final

import typer

from codelogician.commands.cmd_agent import run_agent_cmd
from codelogician.commands.cmd_doc import app as doc_app
from codelogician.commands.cmd_eval import app as eval_app
from codelogician.commands.cmd_multiagent import run_multiagent_cmd
from codelogician.commands.cmd_sample import run_sample_cmd
from codelogician.commands.cmd_server import app as server_app

logging.getLogger('httpx').setLevel(logging.WARNING)
logging.getLogger('httpcore').setLevel(logging.WARNING)
logging.getLogger('fsevents').setLevel(logging.WARNING)

log = logging.getLogger(__name__)


CL_HELP: Final = """
[bold deep_sky_blue1][italic]CodeLogician[/italic] is the neurosymbolic agentic governance framework for AI-powered coding.[/bold deep_sky_blue1] :rocket:

[not dim][bold italic purple]It helps your coding agent think logically about the code it's producing and test cases it's generating.[/bold italic purple]
The fundamental flaw that all LLM-powered assistants have is the reasoning they're capable of is based on statistics,
while you need rigorous logic-based automated reasoning.

- Generated code is based on explainable logic, not pure statistics
- Generated test cases are generated come with quantitative coverage metrics
- Generated code is consistent with the best security practices leveraging formal verification

To run [bold italic deep_sky_blue1]CodeLogician[/bold italic deep_sky_blue1], please obtain an [bold italic deep_sky_blue1]Imandra Universe API[/bold italic deep_sky_blue1] key available
(there's a free starting plan) at [bold italic deep_sky_blue1]https://universe.imandra.ai[/bold italic deep_sky_blue1] and make
sure it's available in your environment as [bold italic deep_sky_blue1]`IMANDRA_UNI_KEY`[/bold italic deep_sky_blue1].

[bold deep_sky_blue1 italic]Three typical workflows[/bold deep_sky_blue1 italic]:
1. [bold deep_sky_blue1 italic]DIY mode[/bold deep_sky_blue1 italic] - this is where your agent (e.g. Grok) uses the CLI to:
  - Learn how to use IML/ImandraX via `doc` command (e.g. `codelogician doc --help`)
  - Synthesizes IML code and uses the `eval` command to evaluate it
  - If there're errors, use `codelogician doc view errors` command to study how to correct the errors and re-evalute the code

2. [bold deep_sky_blue1 italic]Agent/multi-agent mode[/bold deep_sky_blue1 italic] - CodeLogician Agent is a Langgraph-based agent for automatically formalizing source code.
  - With `agent` command you can formalize a single source code file (e.g. `codelogician agent PATH_TO_FILE`)
  - With `multiagent` command you can formalize a whole directory (e.g. `codelogician agent PATH_TO_DIR`)

3. [bold deep_sky_blue1 italic]Server[/bold deep_sky_blue1 italic] - this is a "live" and interactive version of the `multiagent` command, but one you can interact with and one that
"listens" to live updates and automatically updates formalization as necessary. You can start the server and connect to it
with the TUI (we recommend separate terminal screens).

Learn more at[/not dim] [bold italic deep_sky_blue1]https://www.codelogician.dev![/bold italic deep_sky_blue1]
"""

app = typer.Typer(name='CodeLogician', help=CL_HELP, rich_markup_mode='rich')

# fmt: off
app.add_typer(server_app    , name='server'   , help='Commands for interacting with the server')
@app.command(name='tui', help='Run the TUI')
def run_tui_cmd(
    addr: Annotated[
        str, typer.Option(help='Server host/port')
    ] = 'http://127.0.0.1:8000',
):
    from codelogician.ui.main import run_tui
    run_tui(addr)
app.add_typer(doc_app       , name='doc'      , help='Documentation, guides and ImandraX reference')
app.add_typer(eval_app      , name='eval'     , help='Evaluate IML file via ImandraX API')
app.command(
    name='agent',
    help='Command for invoking CodeLogician Agent on a single file'
)(run_agent_cmd)
app.command(
    name='sample',
    help='Creates a sample Python project in specified directory (relative to the current directory)',
)(run_sample_cmd)
app.command(
    name='multiagent',
    help='Run the CL server in autoformalization mode for a directory and then quit.',
)(run_multiagent_cmd)

# fmt: on


def run_codelogician():
    app()


if __name__ == '__main__':
    app()
