# offline_preview.py
"""
ShaiWatcher offline preview (Discord-less)

Run from anywhere:
  # optional (forces root if your layout is odd)
  # export SHAI_PROJECT_ROOT=/absolute/path/to/shaiwatcher
  # export SHAI_DOCS_HOST=127.0.0.1
  # export SHAI_DOCS_PORT=8910
  # export SHAI_OFFLINE=1
  python3 offline_preview.py
"""
import os
import sys
import asyncio
import pathlib
import traceback

VERSION = "offline-preview-3"

# ---------- repo root discovery ----------
def _find_project_root() -> pathlib.Path:
    cand = []
    env = os.environ.get("SHAI_PROJECT_ROOT")
    if env:
        cand.append(pathlib.Path(env).resolve())
    here = pathlib.Path(__file__).resolve().parent
    cand.extend([
        pathlib.Path.cwd().resolve(),   # current working dir
        here,                           # folder containing this file
        here.parent,                    # one level up
        here.parent.parent,             # two levels up
    ])
    # Also walk upwards from CWD a few levels to be forgiving
    cur = pathlib.Path.cwd().resolve()
    for _ in range(5):
        cand.append(cur)
        cur = cur.parent

    tried = []
    for c in cand:
        tried.append(str(c))
        if (c / "modules").is_dir() and (c / "modules" / "common").is_dir():
            return c

    raise FileNotFoundError(
        "Could not locate project root with a 'modules/common' folder.\n"
        f"Tried:\n - " + "\n - ".join(tried) +
        "\nTip: set SHAI_PROJECT_ROOT=/absolute/path/to/repo"
    )

PROJECT_ROOT = _find_project_root()
if str(PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(PROJECT_ROOT))

# ---------- now safe to import project modules ----------
import discord  # type: ignore
from discord.ext import commands  # type: ignore

# Optional: your config helper if cogs expect it to exist
try:
    from modules.common.settings import cfg as cfg_helper  # noqa: F401
except Exception as e:
    print("[OFFLINE] Warning: couldn't import cfg helper:", repr(e))

def _discover_extensions(project_root: pathlib.Path):
    modules_path = project_root / "modules"
    exts = []
    for folder in modules_path.iterdir():
        if not folder.is_dir():
            continue
        if folder.name == "common":  # match your prod loader
            continue
        for file in folder.glob("*.py"):
            if file.name == "__init__.py":
                continue
            exts.append(f"modules.{folder.name}.{file.stem}")
    return exts

async def main():
    print(f"[OFFLINE] ShaiWatcher offline preview v{VERSION}")
    print(f"[OFFLINE] Project root -> {PROJECT_ROOT}")

    # Keep intents minimal; we never connect anyway
    intents = discord.Intents.none()
    intents.guilds = True

    bot = commands.Bot(command_prefix="!", intents=intents)

    # Mark environment as offline for any cogs that check it
    os.environ.setdefault("SHAI_OFFLINE", "1")
    # Bind docs to localhost by default while testing
    os.environ.setdefault("SHAI_DOCS_HOST", "127.0.0.1")
    os.environ.setdefault("SHAI_DOCS_PORT", "8910")
    os.environ.setdefault("SHAI_DOCS_TITLE", "ShaiWatcher (Offline Preview)")

    # Optional: isolate data file so we don't touch prod paths
    data_file = os.environ.get("SHAI_DATA", str(PROJECT_ROOT / ".offline_data.json"))
    try:
        from data_manager import DataManager  # if your project has this at root
        os.makedirs(os.path.dirname(data_file) or ".", exist_ok=True)
        if not os.path.exists(data_file):
            with open(data_file, "w", encoding="utf-8") as f:
                f.write("{}")
        bot.data_manager = DataManager(data_file)
        print(f"[OFFLINE] DATA_FILE -> {data_file}")
    except Exception as e:
        print("[OFFLINE] DataManager unavailable/failed:", repr(e))

    os.environ.setdefault("SHAI_OFFLINE", "1")  # before loading cogs

    # Load extensions exactly like prod
    failures = 0
    for ext in _discover_extensions(PROJECT_ROOT):
        try:
            await bot.load_extension(ext)
            print(f"[Modules] Loaded: {ext}")
        except Exception as e:
            failures += 1
            print(f"[Modules] Failed to load {ext}: {e}")
            traceback.print_exc()

    if failures:
        print(f"[OFFLINE] Loaded with {failures} module error(s). See logs above.")

    docs = bot.get_cog("DocsSite")
    if docs and hasattr(docs, "force_ready"):
        docs.force_ready(True)

    # Make is_ready() == True so DocsSite serves immediately
    try:
        # discord.py sets this in login/READY; we emulate it
        if not hasattr(bot, "_ready") or bot._ready is None:  # type: ignore[attr-defined]
            bot._ready = asyncio.Event()  # type: ignore[attr-defined]
        bot._ready.set()  # type: ignore[attr-defined]
    except Exception:
        pass

    print("[OFFLINE] Docs: http://%s:%s/"
          % (os.environ.get("SHAI_DOCS_HOST", "0.0.0.0"),
             os.environ.get("SHAI_DOCS_PORT", "8911")))
    print("[OFFLINE] This runner does NOT connect to Discord.")

    # Idle forever; DocsSite runs in its own daemon thread
    await asyncio.Event().wait()

if __name__ == "__main__":
    asyncio.run(main())
