"""Helper script for tdd_sqlite_url_cwd.robot integration tests.

Each subcommand exercises the real application path (no mocks) to
reproduce bug #1024.  The helper reports the **real** outcome: it exits
0 and prints the sentinel when the database resolves inside
CLEVERAGENTS_HOME (bug is fixed), and exits 1 when it resolves to CWD
(bug still present).  The ``tdd_expected_fail_listener`` on the Robot
side handles pass/fail inversion while the bug remains open.

Bug: https://git.cleverthis.com/cleveragents/cleveragents-core/issues/1024
TDD: https://git.cleverthis.com/cleveragents/cleveragents-core/issues/1034
"""

from __future__ import annotations

import os
import shutil
import sys
import tempfile
from collections.abc import Callable
from pathlib import Path
from typing import NoReturn

# Ensure local source tree is importable.
_ROOT = Path(__file__).resolve().parents[1]
_SRC = str(_ROOT / "src")
if _SRC not in sys.path:
    sys.path.insert(0, _SRC)


def _fail(message: str) -> NoReturn:
    """Print an error message to stderr and exit with code 1."""
    print(message, file=sys.stderr)
    sys.exit(1)


def _extract_sqlite_path(url: str) -> Path | None:
    """Extract the file path from a SQLite URL."""
    prefix = "sqlite:///"
    if not url.startswith(prefix):
        return None
    raw_path = url[len(prefix) :]
    if not raw_path:
        return None
    return Path(raw_path).resolve()


# ---------------------------------------------------------------------------
# Subcommands
# ---------------------------------------------------------------------------


def check_db_url_resolution() -> None:
    """Verify that get_database_url() resolves inside CLEVERAGENTS_HOME.

    Creates a temporary CLEVERAGENTS_HOME, removes any overriding env
    vars for database URLs, resets singletons, and checks whether the
    resolved database URL points inside the temporary home directory.
    """
    from cleveragents.application.container import (
        get_database_url,
        reset_container,
    )
    from cleveragents.config.settings import Settings

    original_cwd = Path.cwd().resolve()
    tmpdir = tempfile.mkdtemp(prefix="tdd_sqlite_url_1024_robot_")

    # Save and remove any overriding env vars
    saved_db_url = os.environ.pop("CLEVERAGENTS_DATABASE_URL", None)
    saved_test_db_url = os.environ.pop("CLEVERAGENTS_TEST_DATABASE_URL", None)

    try:
        os.environ["CLEVERAGENTS_HOME"] = tmpdir
        reset_container()
        Settings._instance = None

        resolved_url = get_database_url()
        db_path = _extract_sqlite_path(resolved_url)

        home = Path(tmpdir).resolve()

        if db_path is None:
            _fail(f"Could not extract file path from database URL: {resolved_url}")

        if not str(db_path).startswith(str(home)):
            _fail(
                f"Database path {db_path} is NOT inside "
                f"CLEVERAGENTS_HOME {home}.\n"
                f"Full URL: {resolved_url}\n"
                f"CWD was: {original_cwd}"
            )

        print("tdd-sqlite-url-cwd-resolution-ok")

    finally:
        # Restore env vars
        if saved_db_url is not None:
            os.environ["CLEVERAGENTS_DATABASE_URL"] = saved_db_url
        else:
            os.environ.pop("CLEVERAGENTS_DATABASE_URL", None)
        if saved_test_db_url is not None:
            os.environ["CLEVERAGENTS_TEST_DATABASE_URL"] = saved_test_db_url
        else:
            os.environ.pop("CLEVERAGENTS_TEST_DATABASE_URL", None)
        os.environ.pop("CLEVERAGENTS_HOME", None)
        reset_container()
        Settings._instance = None
        shutil.rmtree(tmpdir, ignore_errors=True)


def check_cli_db_location() -> None:
    """Verify that a CLI command creates the DB inside CLEVERAGENTS_HOME.

    Invokes ``session list`` via the Typer CLI runner and then checks
    whether any database files ended up inside CLEVERAGENTS_HOME rather
    than the original CWD.
    """
    from typer.testing import CliRunner

    from cleveragents.application.container import reset_container
    from cleveragents.cli.commands.session import app as session_app
    from cleveragents.config.settings import Settings

    original_cwd = Path.cwd().resolve()
    tmpdir = tempfile.mkdtemp(prefix="tdd_sqlite_url_1024_robot_cli_")

    saved_db_url = os.environ.pop("CLEVERAGENTS_DATABASE_URL", None)
    saved_test_db_url = os.environ.pop("CLEVERAGENTS_TEST_DATABASE_URL", None)

    try:
        os.environ["CLEVERAGENTS_HOME"] = tmpdir
        reset_container()
        Settings._instance = None

        runner = CliRunner()
        runner.invoke(session_app, ["list"])

        home = Path(tmpdir).resolve()

        # Check for DB files in CWD that shouldn't be there
        suspect_files = [
            original_cwd / "cleveragents.db",
            original_cwd / "cleveragents_test.db",
            original_cwd / ".cleveragents" / "db.sqlite",
        ]
        found_in_cwd = [f for f in suspect_files if f.exists()]

        if found_in_cwd:
            _fail(
                f"Database file(s) found in CWD instead of CLEVERAGENTS_HOME:\n"
                f"  CWD files: {found_in_cwd}\n"
                f"  CLEVERAGENTS_HOME: {home}"
            )

        # Verify the DB was actually created inside CLEVERAGENTS_HOME.
        # If no DB file exists anywhere, the test isn't exercising the
        # database path and the result would be vacuously true.
        home_db_files = list(home.rglob("*.db")) + list(home.rglob("*.sqlite"))
        if not home_db_files:
            _fail(
                f"No database file was created inside CLEVERAGENTS_HOME "
                f"({home}).  The CLI command did not trigger database "
                f"creation, so the test result is inconclusive.\n"
                f"CWD was: {original_cwd}"
            )

        print("tdd-sqlite-url-cwd-cli-ok")

    finally:
        if saved_db_url is not None:
            os.environ["CLEVERAGENTS_DATABASE_URL"] = saved_db_url
        else:
            os.environ.pop("CLEVERAGENTS_DATABASE_URL", None)
        if saved_test_db_url is not None:
            os.environ["CLEVERAGENTS_TEST_DATABASE_URL"] = saved_test_db_url
        else:
            os.environ.pop("CLEVERAGENTS_TEST_DATABASE_URL", None)
        os.environ.pop("CLEVERAGENTS_HOME", None)
        reset_container()
        Settings._instance = None
        shutil.rmtree(tmpdir, ignore_errors=True)


# ---------------------------------------------------------------------------
# Dispatcher
# ---------------------------------------------------------------------------

_COMMANDS: dict[str, Callable[[], None]] = {
    "check-db-url-resolution": check_db_url_resolution,
    "check-cli-db-location": check_cli_db_location,
}

if __name__ == "__main__":
    if len(sys.argv) < 2 or sys.argv[1] not in _COMMANDS:
        print(
            f"Usage: {sys.argv[0]} <{'|'.join(_COMMANDS)}>",
            file=sys.stderr,
        )
        sys.exit(1)
    cmd = _COMMANDS[sys.argv[1]]
    cmd()
