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

import logging
from typing import Annotated, Final

import typer

from codelogician import __version__
from codelogician.commands.cmd_agent import run_agent_cmd
from codelogician.commands.cmd_doc import DOC_COMMAND_HELP_HUMAN, 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 = """
CodeLogician helps AI coding agents reason about complex software using math and logic. 🚀

LLM-based coding assistants are excellent at generating code, but their reasoning is fundamentally statistical.
CodeLogician makes the agent build a mathematical model of the system and uses automated reasoning to analyze behavior before software is deployed.

With CodeLogician, agents can:
- discover edge cases
- verify invariants
- explore behavioral boundaries
- generate high-coverage tests
- produce concrete counterexamples when assumptions fail

To run CodeLogician, obtain an Imandra Universe API key
(there is a free starting plan) at https://universe.imandra.ai
and make it available in your environment as `IMANDRA_UNI_KEY`.

Main interfaces:

1. `codelogician` CLI <- You are here!
   The full platform, including:
   - autoformalization agent
   - evaluation commands
   - decomposition
   - TUI
   - server mode

2. VS Code extension
   For IDE-based usage.

3. MCP server
   For external agent frameworks.

4. Python library
   For advanced automation.

Typical workflow:
- use `doc` to learn the toolchain
- formalize source code into IML
- run `eval` commands to analyze the model
- use the reasoning results to refine code, models, and tests

Learn more at https://www.codelogician.dev!
"""

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


@app.callback(invoke_without_command=True)
def _main(
    ctx: typer.Context,
    version: bool = typer.Option(
        False, '--version', '-V', is_eager=True, help='Show version and exit'
    ),
):
    if version:
        typer.echo(__version__)
        raise typer.Exit()
    if ctx.invoked_subcommand is None:
        typer.echo(ctx.get_help())

    from codelogician.update_check import check_for_update

    check_for_update()


# 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=DOC_COMMAND_HELP_HUMAN)
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()
