#!/usr/bin/env python3
"""
Bootstrap a local CNPERP installation: verify PostgreSQL, create schema, run migrations, seed system data.
Called by deploy/local-server/Install-CNPERP-Local.ps1
"""
from __future__ import annotations

import os
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))

from sqlalchemy import create_engine, text
from sqlalchemy.engine import make_url


def load_database_url() -> str:
    env_path = ROOT / ".env"
    if env_path.is_file():
        for line in env_path.read_text(encoding="utf-8").splitlines():
            line = line.strip()
            if line.startswith("DATABASE_URL=") and not line.startswith("#"):
                return line.split("=", 1)[1].strip().strip('"').strip("'")
    from app.core.config import settings
    return str(settings.database_url)


def verify_postgresql(url: str) -> dict:
    engine = create_engine(url, pool_pre_ping=True)
    with engine.connect() as conn:
        version = conn.execute(text("SELECT version()")).scalar()
        db = conn.execute(text("SELECT current_database()")).scalar()
    return {"ok": True, "version": version, "database": db}


def ensure_schema(url: str) -> None:
    import app.models  # noqa: F401 — register all models
    from app.core.database import Base

    engine = create_engine(url)
    Base.metadata.create_all(bind=engine)
    print("[bootstrap] Database tables created/verified")


def run_migrations() -> None:
    migrations = [
        ROOT / "migrations" / "add_company_multitenancy.py",
        ROOT / "migrations" / "add_licensing_tables.py",
        ROOT / "migrations" / "add_pos_session_timeout.py",
        ROOT / "migrations" / "add_cloud_sync_tables.py",
        ROOT / "migrations" / "fix_user_email_nullable_unique.py",
    ]
    for path in migrations:
        if not path.is_file():
            continue
        print(f"[bootstrap] Running {path.name} …")
        import subprocess
        r = subprocess.run([sys.executable, str(path)], cwd=str(ROOT), capture_output=True, text=True)
        if r.returncode != 0 and "already exists" not in (r.stderr or "") and "already exists" not in (r.stdout or ""):
            print(r.stdout or "")
            print(r.stderr or "")


def seed_system_data() -> None:
    from app.core.database import SessionLocal
    from scripts.seeds.registry import run_selected

    db = SessionLocal()
    try:
        run_selected(db, ["roles_permissions", "units", "accounts", "walkin_customer"])
        db.commit()
        print("[bootstrap] System seeds applied (roles, units, COA, walk-in customer)")
    except Exception as exc:
        db.rollback()
        print(f"[bootstrap] Seed warning: {exc}")
    finally:
        db.close()


def write_install_state(cloud_url: str, port: int) -> None:
    state_dir = ROOT / "deploy" / "local-server"
    state_dir.mkdir(parents=True, exist_ok=True)
    state_file = state_dir / "install-state.json"
    import json
    from datetime import datetime

    state = {
        "installed_at": datetime.utcnow().isoformat() + "Z",
        "cloud_url": cloud_url.rstrip("/"),
        "port": port,
        "setup_complete": False,
    }
    state_file.write_text(json.dumps(state, indent=2), encoding="utf-8")


def main() -> int:
    import argparse

    parser = argparse.ArgumentParser(description="CNPERP local install bootstrap")
    parser.add_argument("--cloud-url", default=os.environ.get("LICENSE_CLOUD_URL", "http://localhost:8000"))
    parser.add_argument("--port", type=int, default=8010)
    args = parser.parse_args()

    url = load_database_url()
    print(f"[bootstrap] Database: {make_url(url).render_as_string(hide_password=True)}")

    try:
        info = verify_postgresql(url)
        print(f"[bootstrap] PostgreSQL OK — {info['database']}")
    except Exception as exc:
        print(f"[bootstrap] PostgreSQL connection FAILED: {exc}")
        return 1

    ensure_schema(url)
    run_migrations()
    seed_system_data()
    write_install_state(args.cloud_url, args.port)

    print("[bootstrap] Local installation bootstrap complete.")
    return 0


if __name__ == "__main__":
    sys.exit(main())
