#!/usr/bin/env python3
"""
Standalone migration tester. Run this to debug DB + migration issues.
When it passes, the same logic is already in deploy.py.

Run: python scripts/test_migrate.py
"""

from __future__ import annotations
import getpass
import os
import sys
from pathlib import Path

SERVER_HOST = "91.107.131.171"
SERVER_PORT = 2435
SSH_USER    = "root"
SSH_PASS    = os.environ.get("DANESHYAR_SSH_PASSWORD", "")
APP_DIR     = "/var/www/html"
PHP         = "php8.3"

ROOT = Path(__file__).resolve().parents[1]


def connect():
    import paramiko
    pw = SSH_PASS or getpass.getpass(f"SSH password for {SSH_USER}@{SERVER_HOST}: ")
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    print(f"Connecting {SSH_USER}@{SERVER_HOST}:{SERVER_PORT} ...")
    client.connect(SERVER_HOST, port=SERVER_PORT, username=SSH_USER, password=pw, timeout=15)
    client.get_transport().set_keepalive(30)
    print("Connected.\n")
    return client


def run(client, cmd: str, *, check: bool = True, stream: bool = True):
    print(f"  $ {cmd}")
    stdin, stdout, stderr = client.exec_command(cmd, get_pty=True)
    stdin.close()
    lines = []
    for line in iter(stdout.readline, ""):
        if stream:
            print(f"    {line}", end="", flush=True)
        lines.append(line)
    code = stdout.channel.recv_exit_status()
    out = "".join(lines)
    if check and code != 0:
        print(f"\n  [FAILED] exit {code}")
        sys.exit(code)
    return code, out


def test_db(client):
    print("=" * 50)
    print("STEP 1: Database connection test")
    print("=" * 50)

    php_code = r"""<?php
function env_get($file, $key) {
    foreach (file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
        $line = trim($line);
        if ($line === '' || $line[0] === '#') continue;
        if (strpos($line, $key . '=') === 0) {
            $val = substr($line, strlen($key) + 1);
            return trim($val, "\"'");
        }
    }
    return '';
}
$f = '/var/www/html/.env';
$host = env_get($f, 'DB_HOST');
$port = (int)(env_get($f, 'DB_PORT') ?: 3306);
$name = env_get($f, 'DB_DATABASE');
$user = env_get($f, 'DB_USERNAME');
$pass = env_get($f, 'DB_PASSWORD');

echo "  host : $host\n";
echo "  port : $port\n";
echo "  db   : $name\n";
echo "  user : $user\n";

echo "\n  TCP check ... ";
$sock = @fsockopen($host, $port, $errno, $errstr, 10);
if (!$sock) { echo "FAIL ($errno: $errstr)\n"; exit(2); }
fclose($sock);
echo "OK\n";

echo "  PDO connect ... ";
try {
    $dsn = "mysql:host=$host;port=$port;dbname=$name;connect_timeout=10";
    new PDO($dsn, $user, $pass, [PDO::ATTR_TIMEOUT => 10]);
    echo "OK\n";
} catch (Exception $ex) {
    echo "FAIL: " . $ex->getMessage() . "\n";
    exit(1);
}
echo "\n  DB CONNECTION OK\n";
"""
    sftp = client.open_sftp()
    with sftp.file("/tmp/db_test.php", "w") as f:
        f.write(php_code)
    sftp.close()

    code, out = run(client, f"timeout 20 {PHP} /tmp/db_test.php 2>&1; rm -f /tmp/db_test.php", check=False)
    if code != 0 or "DB CONNECTION OK" not in out:
        print("\n  FAILED — fix DB credentials in .env before migrating")
        sys.exit(1)
    print("\n  PASS\n")


def test_migrate(client):
    cwd = APP_DIR

    print("=" * 50)
    print("STEP 2: Migration status (pending migrations)")
    print("=" * 50)
    run(client, f"cd {cwd} && {PHP} artisan migrate:status 2>&1", check=False)

    print()
    print("=" * 50)
    print("STEP 3: Running migrations (verbose)")
    print("=" * 50)
    code, out = run(
        client,
        f"cd {cwd} && {PHP} artisan migrate --force -v 2>&1",
        check=False,
    )
    if code != 0:
        print(f"\n  [FAILED] exit {code}")
        print("  Check logs:")
        print(f"    ssh {SSH_USER}@{SERVER_HOST} -p {SERVER_PORT}")
        print(f"    tail -50 {cwd}/storage/logs/laravel.log")
        sys.exit(1)

    print("\n  MIGRATIONS PASSED\n")

    print("=" * 50)
    print("STEP 4: Laravel log tail (last 20 lines)")
    print("=" * 50)
    run(client, f"tail -20 {cwd}/storage/logs/laravel.log 2>/dev/null || echo '(no log file)'", check=False)


def main():
    try:
        import paramiko  # noqa
    except ImportError:
        print("ERROR: pip install paramiko")
        sys.exit(1)

    client = connect()
    try:
        test_db(client)
        test_migrate(client)
        print("\nAll steps passed. Copy this logic into deploy.py post-deploy.")
    finally:
        client.close()
        print("Connection closed.")


if __name__ == "__main__":
    main()
