import os
import subprocess
import sys

import click
import docker
from loguru import logger

from odoo_openupgrade_wizard.cli.cli_options import (
    database_option_required,
    get_migration_step_from_options,
    step_option,
)
from odoo_openupgrade_wizard.tools.tools_odoo import (
    generate_odoo_command_options,
)
from odoo_openupgrade_wizard.tools.tools_postgres import ensure_database


@click.command()
@step_option
@database_option_required
@click.option(
    "--code",
    default=None,
    help="Python code to execute in the Odoo shell. "
    "Example: 'print(env.user.name)'",
)
@click.pass_context
def shell(ctx, step, database, code):
    """Run an Odoo shell in the running Odoo container."""

    migration_step = get_migration_step_from_options(ctx, step)
    ensure_database(ctx, database, state="present")

    config = ctx.obj.get("config", {})
    project_name = config.get("project_name")
    if not project_name:
        click.echo("Unable to find the project name.")
        sys.exit(1)

    expected_container_name_prefix = f"oow-{project_name}-{database}"

    # Connect to the Docker daemon
    docker_client = docker.from_env()

    # List all running containers
    running_containers = docker_client.containers.list(
        filters={"status": "running"}
    )

    # Find the running Odoo container
    matching_container = next(
        (
            c
            for c in running_containers
            if expected_container_name_prefix in c.name and "step" in c.name
        ),
        None,
    )

    if not matching_container:
        logger.error(
            "No running Odoo container found. "
            "Please run oow run before running the shell."
        )
        sys.exit(1)

    logger.info(f"Execute shell in {matching_container.name} container...")

    common_options = generate_odoo_command_options(
        ctx, migration_step, "regular", database
    )

    # Build the docker exec command
    command = [
        "docker",
        "exec",
        "-i",  # Interactive mode to enable stdin
        matching_container.name,
        "/odoo_env/src/odoo/odoo-bin",
        "shell",
        "--no-http",
        "--shell-interface=iptyhon",
    ] + common_options

    logger.info(f"Command: {' '.join(command)}")

    # If code is provided, send it via stdin
    if code:
        logger.info(f"Executing code: {code}")
        process = subprocess.Popen(
            command,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,  # Enables text mode
        )
        stdout, stderr = process.communicate(code)
        if process.returncode != 0:
            logger.error(f"Error executing code: {stderr}")
            sys.exit(1)
        else:
            click.echo(stdout)
    else:
        # Interactive session requires TTY
        command.insert(2, "-t")
        os.execvp(command[0], command)
