#!/usr/bin/env python3
"""Finish nginx routing + ensure core/frontend env for accounting."""
from __future__ import annotations

import base64
from pathlib import Path

import paramiko

ROOT = Path(__file__).resolve().parents[1]
APP_HOST = "192.168.10.162"
APP_USER = "morteza"
APP_PASS = "Moli@5404"
NGX_HOST = "192.168.10.156"
NGX_USER = "torbatyaruser"
NGX_PASS = "Moli@5404"
REMOTE_DIR = "/home/morteza/torbatyar"


def connect(host: str, user: str, password: str) -> paramiko.SSHClient:
    c = paramiko.SSHClient()
    c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    c.connect(host, username=user, password=password, timeout=30, allow_agent=False, look_for_keys=False)
    return c


def run(client, cmd: str, *, sudo=False, password="", timeout=600):
    cmd = cmd.replace("\r\n", "\n").replace("\r", "\n").strip() + "\n"
    b64 = base64.b64encode(cmd.encode()).decode()
    if sudo:
        full = f"echo {password!r} | sudo -S -p '' bash -c 'echo {b64} | base64 -d | bash'"
    else:
        full = f"bash -lc 'echo {b64} | base64 -d | bash'"
    print("\n>>>", cmd[:200].replace("\n", " | "), "...")
    _i, out, err = client.exec_command(full, timeout=timeout, get_pty=True)
    text = (out.read() + err.read()).decode("utf-8", "replace")
    code = out.channel.recv_exit_status()
    print(text[-5000:].encode("ascii", "replace").decode("ascii"))
    return code, text


def put_text_sudo(client, password: str, remote: str, content: str) -> None:
    b64 = base64.b64encode(content.encode()).decode()
    cmd = f"mkdir -p $(dirname {remote!r}) && echo {b64} | base64 -d > {remote!r} && chmod 644 {remote!r}"
    code, _ = run(client, cmd, sudo=True, password=password, timeout=60)
    if code != 0:
        raise RuntimeError(f"write failed: {remote}")


def main() -> int:
    app = connect(APP_HOST, APP_USER, APP_PASS)
    try:
        code, _ = run(
            app,
            f"""
set -e
cd {REMOTE_DIR}
# ensure env
python3 - <<'PY'
from pathlib import Path
p = Path('.env')
text = p.read_text(encoding='utf-8') if p.exists() else ''
keys = {{
  'NEXT_PUBLIC_ACCOUNTING_API_URL': 'https://accounting.torbatyar.ir',
  'ACCOUNTING_DATABASE_URL': 'postgresql+asyncpg://superapp:superapp_password@postgres:5432/accounting_db',
  'ACCOUNTING_DATABASE_URL_SYNC': 'postgresql+psycopg://superapp:superapp_password@postgres:5432/accounting_db',
  'ACCOUNTING_SERVICE_NAME': 'accounting-service',
  'KEYCLOAK_SERVER_URL': 'http://keycloak:8080',
  'KEYCLOAK_REALM': 'superapp',
}}
lines = text.splitlines()
seen=set(); out=[]
for line in lines:
    if not line.strip() or line.lstrip().startswith('#') or '=' not in line:
        out.append(line); continue
    k=line.split('=',1)[0].strip()
    if k in keys:
        out.append(f"{{k}}={{keys[k]}}"); seen.add(k)
    else:
        out.append(line)
for k,v in keys.items():
    if k not in seen:
        out.append(f'{{k}}={{v}}')
p.write_text('\\n'.join(out).rstrip()+'\\n', encoding='utf-8')
print('env_ok')
PY
grep -E 'NEXT_PUBLIC_ACCOUNTING|ACCOUNTING_DATABASE|KEYCLOAK_SERVER_URL|KEYCLOAK_PUBLIC_URL' .env
# bring core back if missing + recreate frontend to pick env
docker compose up -d core-service identity-access-service accounting-service
docker compose up -d --force-recreate frontend
sleep 8
docker compose ps
curl -sf http://127.0.0.1:8000/health || curl -sf http://127.0.0.1:8000/api/v1/health || echo CORE_HEALTH_CHECK
curl -sf http://127.0.0.1:8002/health
echo
docker compose exec -T frontend printenv NEXT_PUBLIC_ACCOUNTING_API_URL || true
""",
            sudo=True,
            password=APP_PASS,
            timeout=600,
        )
        if code != 0:
            raise RuntimeError("app finalize failed")
    finally:
        app.close()

    ngx = connect(NGX_HOST, NGX_USER, NGX_PASS)
    try:
        conf = (ROOT / "infrastructure" / "nginx" / "torbatyar.ir.conf").read_text(encoding="utf-8")
        put_text_sudo(ngx, NGX_PASS, "/etc/nginx/conf.d/torbatyar.ir.conf", conf)
        # also update provision script on nginx host if present
        prov = (ROOT / "infrastructure" / "nginx" / "provision_ssl.py").read_text(encoding="utf-8")
        put_text_sudo(ngx, NGX_PASS, "/opt/torbatyar/bin/provision_ssl.py", prov)
        code, _ = run(
            ngx,
            r"""
set -e
mkdir -p /var/www/html
certbot certonly --webroot -w /var/www/html \
  -d torbatyar.ir -d www.torbatyar.ir \
  -d api.torbatyar.ir -d identity.torbatyar.ir -d auth.torbatyar.ir -d accounting.torbatyar.ir \
  --non-interactive --agree-tos --email support@torbatyar.ir --expand || true
openssl x509 -in /etc/letsencrypt/live/torbatyar.ir/fullchain.pem -noout -ext subjectAltName | tr ',' '\n' | grep -i accounting || echo SAN_ACCOUNTING_MISSING
nginx -t
systemctl reload nginx
echo NGINX_OK
curl -skI https://accounting.torbatyar.ir/health | head -n 8
echo ---
curl -sk https://accounting.torbatyar.ir/health || echo PUBLIC_HEALTH_FAIL
echo
curl -skI https://torbatyar.ir/accounting | head -n 8
""",
            sudo=True,
            password=NGX_PASS,
            timeout=300,
        )
        if code != 0:
            raise RuntimeError("nginx finalize failed")
    finally:
        ngx.close()

    print("\n=== FINALIZE DONE ===")
    return 0


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