#!/usr/bin/env python3
"""Seed config_vars in the remote MySQL database from a local .env file.

cPanel/CloudLinux Passenger processes cannot always read a server-side ``.env``,
so this script pushes all non-sensitive and sensitive config values into the
``config_vars`` table before/after deployment.  The running app then loads them
via ``config.patch_from_db(db)``.

Usage (called by ``deploy.sh``)::

    python3 scripts/seed_config.py --env .env --ssh-host jnc

Requires:
    - SSH access to the cPanel server.
    - The local .env must contain MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DB.
"""

from __future__ import annotations

import argparse
import sys
from pathlib import Path
from typing import Optional

from dotenv import load_dotenv

# Make the repo root importable when this script is run from scripts/.
_PROJECT_ROOT = Path(__file__).resolve().parent.parent
if str(_PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(_PROJECT_ROOT))

from common import load_env, ssh_run, ssh_check, ssh_upload


def _build_remote_script(remote_dir: str) -> str:
    """Generate the Python seeder script to run on the remote server."""
    return f'''
import os
import sys
from pathlib import Path
from dotenv import load_dotenv

env_path = Path("/tmp/seed_config.env")
load_dotenv(env_path)

app_root = Path(os.path.expanduser({remote_dir!r}))
# Remove any stale server-side .env so it does not override the values we seed.
(app_root / ".env").unlink(missing_ok=True)

sys.path.insert(0, str(app_root))

from db import Database
from config import _db_overrides, _db_secret_overrides

db = Database()
env = dict(os.environ)
seen = set()
count = 0

# Secret keys are Fernet-encrypted at rest via db.set_secret_config().
secret_keys = set(_db_secret_overrides.values())

for attr, (db_key, _) in _db_overrides.items():
    val = env.get(attr, "").strip()
    if val and db_key not in secret_keys and db_key not in seen:
        db.set_config(db_key, val)
        seen.add(db_key)
        count += 1

for attr, db_key in _db_secret_overrides.items():
    val = env.get(attr, "").strip()
    if val and db_key not in seen:
        db.set_secret_config(db_key, val)
        seen.add(db_key)
        count += 1

print(f"seeded {{count}} config var(s)")
env_path.unlink(missing_ok=True)
'''


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(description="Seed remote config_vars from local .env")
    parser.add_argument("--env", default=".env", help="Path to local .env file")
    parser.add_argument("--ssh-host", default="jnc", help="SSH host alias")
    parser.add_argument("--remote-dir", default="~/quill.nx.kg", help="Remote app directory")
    parser.add_argument(
        "--remote-python",
        default="~/virtualenv/quill.nx.kg/3.13/bin/python",
        help="Remote Python interpreter to use",
    )
    args = parser.parse_args(argv)

    env_path = Path(args.env)
    if not env_path.exists():
        print(f"No local .env at {env_path}; skipping config seed")
        return 0

    ssh_check(args.ssh_host)

    # Build the list of values we are about to seed (for logging only).
    local_env = load_env(env_path)
    db_keys = set()

    # Import config to check which keys map to DB overrides.
    load_dotenv(env_path)
    from config import _db_overrides, _db_secret_overrides

    for attr, (db_key, _) in _db_overrides.items():
        if local_env.get(attr, "").strip():
            db_keys.add(db_key)
    for attr, db_key in _db_secret_overrides.items():
        if local_env.get(attr, "").strip():
            db_keys.add(db_key)

    if not db_keys:
        print("No config values found to seed")
        return 0

    print(f"Seeding {len(db_keys)} config key(s) into {args.ssh_host} ...")

    # Upload the .env content to a private temp file on the server.
    env_bytes = env_path.read_bytes()
    upload_env = ssh_upload(args.ssh_host, "/tmp/seed_config.env", env_bytes, mode="600")
    if upload_env.returncode != 0:
        print(upload_env.stderr.decode("utf-8", errors="ignore"), file=sys.stderr)
        return 1

    # Upload and run the Python seeder.
    remote_script = _build_remote_script(args.remote_dir)
    upload_script = ssh_upload(args.ssh_host, "/tmp/seed_config.py", remote_script.encode("utf-8"), mode="700")
    if upload_script.returncode != 0:
        print(upload_script.stderr.decode("utf-8", errors="ignore"), file=sys.stderr)
        return 1

    run = ssh_run(args.ssh_host, f"{args.remote_python} /tmp/seed_config.py")
    stdout = run.stdout.decode("utf-8", errors="ignore").strip()
    stderr = run.stderr.decode("utf-8", errors="ignore").strip()
    if stdout:
        print(stdout)
    if stderr:
        print(stderr, file=sys.stderr)

    # Clean up temp files regardless of success.
    ssh_run(args.ssh_host, "rm -f /tmp/seed_config.env /tmp/seed_config.py")

    return 0 if run.returncode == 0 else 1


if __name__ == "__main__":
    raise SystemExit(main())
