#!/usr/bin/env python3
"""
My Daneshyar — Ubuntu server setup + post-deploy helper.

Two modes:
  sudo python3 scripts/server_setup.py              -- Install Apache/PHP/MySQL/Composer
  python3 scripts/server_setup.py --post-deploy     -- Laravel setup after upload

Environment variables (optional overrides):
  APP_DIR       Server path where project lives (default: /var/www/html)
  PHP_VERSION   PHP version to install (default: 8.3)
  SERVER_NAME   Apache ServerName (default: _ = catch-all)
"""

from __future__ import annotations

import argparse
import os
import subprocess
import sys
from pathlib import Path

# ── Config ────────────────────────────────────────────────────────────
PHP_VERSION = os.environ.get("PHP_VERSION", "8.3")
APP_DIR = os.environ.get("APP_DIR", "/var/www/html")
SERVER_NAME = os.environ.get("SERVER_NAME", "_")
# ──────────────────────────────────────────────────────────────────────


def run(cmd: str, *, cwd: str | None = None, check: bool = True) -> int:
    print(f"\n→ {cmd}")
    result = subprocess.run(cmd, shell=True, cwd=cwd, check=False)
    if check and result.returncode != 0:
        print(f"[FAILED] exit code {result.returncode}")
        sys.exit(result.returncode)
    return result.returncode


def require_root() -> None:
    if os.getuid() != 0:
        print("ERROR: This mode must run as root.")
        print("       sudo python3 scripts/server_setup.py")
        sys.exit(1)


# ── System install ────────────────────────────────────────────────────

def install_system() -> None:
    require_root()

    print("\n[1/7] Updating apt and installing base tools...")
    run("apt-get update -qq")
    run("apt-get install -y -qq software-properties-common ca-certificates curl unzip git rsync")

    print("\n[2/7] Adding PHP ondrej/php PPA...")
    run("add-apt-repository -y ppa:ondrej/php || true")
    run("apt-get update -qq")

    print("\n[3/7] Installing Apache + PHP extensions...")
    exts = [
        "cli", "common", "mysql", "mbstring", "xml", "curl",
        "zip", "gd", "bcmath", "intl", "fileinfo", "tokenizer",
        "ctype", "dom", "pdo",
    ]
    ext_list = " ".join(f"php{PHP_VERSION}-{e}" for e in exts)
    run(
        f"apt-get install -y -qq "
        f"apache2 php{PHP_VERSION} libapache2-mod-php{PHP_VERSION} {ext_list}"
    )

    print("\n[4/7] Installing MySQL server...")
    run("apt-get install -y -qq mysql-server")
    run("systemctl enable mysql")
    run("systemctl start mysql")

    print("\n[5/7] Installing Composer...")
    if run("which composer", check=False) != 0:
        run("curl -fsSL https://getcomposer.org/installer -o /tmp/composer-setup.php")
        run(f"php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer")
        run("rm -f /tmp/composer-setup.php")
    else:
        print("  composer already installed, skipping.")

    print("\n[6/7] Creating app directory...")
    run(f"mkdir -p {APP_DIR}")
    run(f"chown -R www-data:www-data {APP_DIR}")

    print("\n[7/7] Configuring Apache vhost...")
    vhost = (
        "<VirtualHost *:80>\n"
        f"    ServerName {SERVER_NAME}\n"
        f"    DocumentRoot {APP_DIR}/public\n"
        "\n"
        f"    <Directory {APP_DIR}/public>\n"
        "        AllowOverride All\n"
        "        Require all granted\n"
        "        Options -Indexes\n"
        "    </Directory>\n"
        "\n"
        "    ErrorLog ${APACHE_LOG_DIR}/daneshyar_error.log\n"
        "    CustomLog ${APACHE_LOG_DIR}/daneshyar_access.log combined\n"
        "</VirtualHost>\n"
    )

    vhost_path = "/etc/apache2/sites-available/daneshyar.conf"
    with open(vhost_path, "w") as fh:
        fh.write(vhost)

    run("a2enmod rewrite headers")
    run("a2dissite 000-default.conf || true")
    run("a2ensite daneshyar.conf")
    run("systemctl enable apache2")
    run("systemctl reload apache2")

    _print_system_done()


def _print_system_done() -> None:
    sep = "=" * 60
    print(f"\n{sep}")
    print("  SYSTEM SETUP COMPLETE")
    print(sep)
    print(f"\n  Apache DocumentRoot : {APP_DIR}/public")
    print(f"  Upload project to   : {APP_DIR}/")
    print("\n  After uploading all files, run:")
    print(f"    cd {APP_DIR}")
    print("    cp .env.example .env")
    print("    nano .env   # fill in DB_DATABASE, DB_USERNAME, DB_PASSWORD, APP_KEY")
    print(f"    python3 scripts/server_setup.py --post-deploy")
    print()


# ── Post-deploy ───────────────────────────────────────────────────────

def post_deploy() -> None:
    # Find project root — either APP_DIR or this script's own parent
    candidates = [
        Path(APP_DIR),
        Path(__file__).resolve().parents[1],
    ]
    app_path: Path | None = None
    for candidate in candidates:
        if (candidate / "artisan").exists():
            app_path = candidate
            break

    if app_path is None:
        print("ERROR: artisan not found. Upload the project first, then run this script.")
        sys.exit(1)

    cwd = str(app_path)
    print(f"\nProject root: {cwd}")

    env_file = app_path / ".env"
    if not env_file.exists():
        print("\nWARNING: .env not found.")
        print("  Copy .env.example to .env and fill in your DB credentials before continuing.")
        print(f"    cp {cwd}/.env.example {cwd}/.env")
        print(f"    nano {cwd}/.env")
        sys.exit(1)

    print("\n[1/7] Installing Composer dependencies (no-dev)...")
    run("composer install --no-dev --optimize-autoloader", cwd=cwd)

    print("\n[2/7] Generating application key (if not set)...")
    run("php artisan key:generate --force", cwd=cwd)

    print("\n[3/7] Running database migrations...")
    run("php artisan migrate --force", cwd=cwd)

    print("\n[4/7] Seeding initial data (if needed)...")
    run("php artisan db:seed --force", cwd=cwd, check=False)

    print("\n[5/7] Caching config, routes, views...")
    run("php artisan config:cache", cwd=cwd)
    run("php artisan route:cache", cwd=cwd)
    run("php artisan view:cache", cwd=cwd)

    print("\n[6/7] Creating storage symlink...")
    run("php artisan storage:link", cwd=cwd, check=False)

    print("\n[7/7] Setting file permissions...")
    dirs = [
        f"{cwd}/storage/logs",
        f"{cwd}/storage/framework/cache",
        f"{cwd}/storage/framework/sessions",
        f"{cwd}/storage/framework/views",
        f"{cwd}/bootstrap/cache",
    ]
    run(f"mkdir -p {' '.join(dirs)}")
    run(f"chown -R www-data:www-data {cwd}/storage {cwd}/bootstrap/cache")
    run(f"chmod -R 775 {cwd}/storage {cwd}/bootstrap/cache")

    _print_deploy_done()


def _print_deploy_done() -> None:
    sep = "=" * 60
    print(f"\n{sep}")
    print("  POST-DEPLOY COMPLETE")
    print(sep)
    print("\n  Test these URLs:")
    print("    /              — landing page")
    print("    /login         — login screen")
    print("    /dashboard     — redirect by role (requires login)")
    print("\n  Super Admin credentials: see database/seed.sql")
    print("\n  If you see a 500 error:")
    print("    Check .env values")
    print("    Check: php artisan config:cache (run again after .env edit)")
    print("    Check Apache error log: /var/log/apache2/daneshyar_error.log")
    print()


# ── Main ──────────────────────────────────────────────────────────────

def main() -> None:
    parser = argparse.ArgumentParser(
        description="My Daneshyar server setup.",
        formatter_class=argparse.RawTextHelpFormatter,
        epilog=(
            "Examples:\n"
            "  sudo python3 scripts/server_setup.py              # install system\n"
            "  python3 scripts/server_setup.py --post-deploy     # after upload\n"
            "\n"
            "Override with env vars:\n"
            "  APP_DIR=/var/www/html SERVER_NAME=mydaneshyar.ir sudo python3 scripts/server_setup.py\n"
        ),
    )
    parser.add_argument(
        "--post-deploy",
        action="store_true",
        help="Run Laravel post-upload setup (composer install, migrate, cache, permissions).",
    )
    args = parser.parse_args()

    if args.post_deploy:
        post_deploy()
    else:
        install_system()


if __name__ == "__main__":
    main()
