import argparse
import json
import os
import platform
import sys
import traceback
from typing import Any, Literal

from .config import execute_configs
from .env import OSWorldDesktopEnv
from .evaluate import evaluate
from .logging import logger
from .osworld_types import Example

platform_name = platform.system()


def main() -> None:
    """
    Main function to execute the CLI commands inside the container for OSWorld evaluations.

    This function parses the command-line arguments, reads the example configuration
    from a JSON file, and performs actions based on the provided arguments.

    Actions:
      - "config": Executes the configuration commands.
      - "evaluate": Runs any post-config commands, executes the evaluation, and prints the result.
    """
    try:
        args = _parse_arguments()
        with open(
            "/tmp/osworld/desktop_env/example.json", "r", encoding="utf-8"
        ) as file:
            example = Example(**json.loads(file.read()))

        logger.info(f"called with '{args.action}' for '{example.id}'")
        env = OSWorldDesktopEnv()
        if args.action == "config":
            if example.config:
                execute_configs(env, example.config)
        else:
            score, explanation = evaluate(env, example.evaluator)
            # The one and only stdout print that goes back to the host
            print(
                "infeasible"
                if score == "infeasible"
                else _json_result({"score": score, "explanation": explanation})
            )
    except Exception as e:  # pylint: disable=broad-exception-caught
        error_msg = str(e)
        tb = traceback.format_exc()
        print(_json_result({"error": error_msg, "traceback": tb}), file=sys.stderr)
        logger.error(f"An error occurred: {error_msg} at:\n{tb}")
        sys.exit(1)


class _Arguments(argparse.Namespace):
    action: Literal["config", "evaluate"]


def _parse_arguments() -> _Arguments:
    parser = argparse.ArgumentParser(
        description="Execute computer tool 'in container' action in support of OSWorld evaluation."
    )
    parser.add_argument(
        "action",
        type=str,
        choices=["config", "evaluate"],
        help="Action to perform. 'config' to configure the container, 'evaluate' to run the post-config and scorer.",
    )
    return parser.parse_args(namespace=_Arguments())


def _json_result(stdout_result: dict[str, Any]) -> str:
    current_dir = os.path.dirname(os.path.abspath(__file__))
    temp = _add_log("stdout", f"{current_dir}/cli.log", stdout_result)
    temp = _add_log("stderr", f"{current_dir}/cli.err", temp)
    return json.dumps(temp)


def _add_log(key: str, log_path: str, the_dict: dict[str, Any]) -> dict[str, Any]:
    try:
        with open(log_path, "r", encoding="utf-8") as log_file:
            log = log_file.read()
        if log:
            new_stdout_result = the_dict.copy()
            new_stdout_result[key] = log
            return new_stdout_result
    except FileNotFoundError:
        pass
    return the_dict


if __name__ == "__main__":
    main()
