"""Scoped coturn operations; invoked only by the pinned Round 2 SSH wrapper."""
import base64
import fcntl
import hashlib
import hmac
import json
import os
from pathlib import Path
import secrets
import shutil
import socket
import subprocess
import sys
import time
import urllib.request


def main(payload):
    os.umask(0o077)
    action = payload['action']
    root = Path('/www/wwwroot/connectlyvideochat.com/Videocall')
    work = Path('/www/backup/bondvia-deploy/round2-turn')
    host = 'connectlyvideochat.com'
    if root.is_symlink() or socket.gethostbyname(host) != '13.204.142.120':
        raise ValueError('Unexpected host or application target')
    settings = work / 'backend.json'

    def run(args, **kwargs):
        return subprocess.run(args, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, **kwargs)

    if action == 'setup':
        if work.exists() or shutil.which('turnserver'):
            raise ValueError('TURN already configured/attempted; inspect before retry')
        cert = Path('/www/server/panel/vhost/cert/connectlyvideochat.com')
        run(['openssl', 'x509', '-in', str(cert / 'fullchain.pem'), '-noout', '-checkhost', host])
        run(['openssl', 'x509', '-in', str(cert / 'fullchain.pem'), '-noout', '-checkend', '604800'])
        work.mkdir(mode=0o700)
        (work / 'tooling-release').write_text(payload['tooling_release'] + '\n')
        (work / 'firewall-before.txt').write_text(subprocess.check_output(['ufw', 'status', 'numbered'], text=True))
        # Prevent package installation from briefly starting an unconfigured relay.
        run(['systemctl', 'mask', '--runtime', 'coturn.service'])
        try:
            with open(work / 'install.log', 'w') as log:
                subprocess.run(['apt-get', 'update'], check=True, stdout=log, stderr=subprocess.STDOUT)
                subprocess.run(['apt-get', 'install', '-y', '--no-install-recommends', 'coturn'], check=True,
                               stdout=log, stderr=subprocess.STDOUT, env={**os.environ, 'DEBIAN_FRONTEND': 'noninteractive'})
            secret = secrets.token_hex(32)
            config = {'TURN_ENABLED': '1', 'TURN_HOST': host, 'TURN_SHARED_SECRET': secret,
                      'TURN_CREDENTIAL_TTL_SECONDS': '3600',
                      'TURN_URLS': f'turn:{host}:3478?transport=udp,turn:{host}:3478?transport=tcp,turns:{host}:5349?transport=tcp'}
            settings.write_text(json.dumps(config))
            target = Path('/etc/turnserver.conf')
            shutil.copy2(target, work / 'turnserver.conf.before')
            text = f'''listening-port=3478
tls-listening-port=5349
listening-ip=172.31.33.153
relay-ip=172.31.33.153
external-ip=13.204.142.120/172.31.33.153
realm={host}
server-name={host}
fingerprint
use-auth-secret
static-auth-secret={secret}
cert=/run/credentials/coturn.service/turncert
pkey=/run/credentials/coturn.service/turnkey
min-port=49160
max-port=49260
relay-threads=2
user-quota=4
total-quota=100
max-bps=1000000
bps-capacity=20000000
stale-nonce=600
no-tlsv1
no-tlsv1_1
no-dtls
no-tcp-relay
no-cli
no-multicast-peers
syslog
no-stdout-log
deny-peer-ip=0.0.0.0-0.255.255.255
deny-peer-ip=10.0.0.0-10.255.255.255
deny-peer-ip=100.64.0.0-100.127.255.255
deny-peer-ip=127.0.0.0-127.255.255.255
deny-peer-ip=169.254.0.0-169.254.255.255
deny-peer-ip=172.16.0.0-172.31.255.255
deny-peer-ip=192.168.0.0-192.168.255.255
deny-peer-ip=224.0.0.0-255.255.255.255
deny-peer-ip=::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
'''
            target.write_text(text)
            shutil.chown(target, user='root', group='turnserver')
            target.chmod(0o640)
            override = Path('/etc/systemd/system/coturn.service.d')
            override.mkdir(exist_ok=True)
            (override / 'bondvia.conf').write_text(f'''[Service]
LoadCredential=turncert:{cert}/fullchain.pem
LoadCredential=turnkey:{cert}/privkey.pem
''')
            # Refresh systemd's private TLS credentials only when aaPanel renews its certificate.
            renewal = Path('/usr/local/sbin/bondvia-turn-renew')
            renewal.write_text('''#!/usr/bin/python3
import hashlib, subprocess
from pathlib import Path
source=Path('/www/server/panel/vhost/cert/connectlyvideochat.com')
state=Path('/www/backup/bondvia-deploy/round2-turn/certificate.sha256')
current=hashlib.sha256((source/'fullchain.pem').read_bytes()+(source/'privkey.pem').read_bytes()).hexdigest()
if state.read_text().strip()!=current:
 subprocess.run(['openssl','x509','-in',str(source/'fullchain.pem'),'-noout','-checkhost','connectlyvideochat.com'],check=True,stdout=subprocess.DEVNULL)
 subprocess.run(['systemctl','restart','coturn.service'],check=True)
 state.write_text(current+'\n')
''')
            renewal.chmod(0o700)
            (work / 'certificate.sha256').write_text(hashlib.sha256(
                (cert / 'fullchain.pem').read_bytes() + (cert / 'privkey.pem').read_bytes()).hexdigest() + '\n')
            Path('/etc/systemd/system/bondvia-turn-renew.service').write_text(
                '[Unit]\nDescription=Refresh Bondvia TURN TLS after certificate renewal\n[Service]\nType=oneshot\nExecStart=/usr/local/sbin/bondvia-turn-renew\n')
            Path('/etc/systemd/system/bondvia-turn-renew.timer').write_text(
                '[Unit]\nDescription=Check Bondvia TURN certificate renewal\n[Timer]\nOnCalendar=daily\nPersistent=true\n[Install]\nWantedBy=timers.target\n')
            for rule in ['3478/udp', '3478/tcp', '5349/tcp', '49160:49260/udp']:
                run(['ufw', 'allow', rule, 'comment', 'Bondvia TURN'])
            run(['systemctl', 'daemon-reload'])
            run(['systemctl', 'unmask', '--runtime', 'coturn.service'])
            run(['systemctl', 'enable', '--now', 'coturn.service'])
            run(['systemctl', 'enable', '--now', 'bondvia-turn-renew.timer'])
            run(['systemctl', 'is-active', '--quiet', 'coturn.service'])
        except BaseException:
            subprocess.run(['systemctl', 'stop', 'coturn.service'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            raise RuntimeError('TURN setup failed; inspect private install log and retained configuration')
        print(json.dumps({'installed': True, 'listeners': [3478, 5349], 'relay_range': '49160-49260/udp', 'api_activated': False}))
    elif action == 'credentials':
        config = json.loads(settings.read_text())
        username = f'{int(time.time()) + 600}:round2-probe'
        password = base64.b64encode(hmac.new(config['TURN_SHARED_SECRET'].encode(), username.encode(), hashlib.sha1).digest()).decode()
        print(json.dumps({'host': host, 'username': username, 'credential': password}))
    elif action == 'activate':
        # Only allowed after an independently recorded external allocation/media probe.
        validate(payload.get('probe', {}))
        config = json.loads(settings.read_text())
        backup = work / 'backend.env.before'
        if backup.exists():
            raise ValueError('Activation already attempted; inspect before retry')
        envfile = root / '.env'
        shutil.copy2(envfile, backup)
        if hashlib.sha256(envfile.read_bytes()).digest() != hashlib.sha256(backup.read_bytes()).digest():
            raise ValueError('Environment backup failed')
        binary = '/www/server/nodejs/v20.19.2/bin/pm2'
        environment = {**os.environ, 'PM2_HOME': '/root/.pm2', 'PATH': '/www/server/nodejs/v20.19.2/bin:' + os.environ['PATH']}
        processes = json.loads(subprocess.check_output([binary, 'jlist'], text=True, env=environment))
        target = [p for p in processes if p['name'] == 'videocall_server']
        if len(target) != 1 or target[0]['pm2_env']['pm_exec_path'] != str(root / 'server.js'):
            raise ValueError('Unexpected PM2 process')
        if any(key in target[0]['pm2_env'] for key in config):
            raise ValueError('PM2 overrides TURN settings; reconcile explicitly')
        expected_commit = (root / '.release-commit').read_text().strip()

        def healthy():
            for url in ['http://127.0.0.1:3000/health', 'https://connectlyvideochat.com/health']:
                with urllib.request.urlopen(url, timeout=10) as response:
                    health = json.load(response)
                if health.get('success') is not True or health.get('commit') != expected_commit:
                    raise ValueError('TURN activation health/revision check failed')

        healthy()
        content = '\n'.join(line for line in envfile.read_text().splitlines() if line.split('=', 1)[0].strip() not in config)
        content += '\n' + '\n'.join(f'{key}={value}' for key, value in config.items()) + '\n'
        temporary = root / '.env.round2'
        temporary.write_text(content)
        shutil.copystat(envfile, temporary)
        stat = envfile.stat()
        os.chown(temporary, stat.st_uid, stat.st_gid)
        os.replace(temporary, envfile)
        try:
            run([binary, 'restart', 'videocall_server'], env=environment)
            for attempt in range(15):
                try:
                    healthy()
                    break
                except (OSError, ValueError):
                    if attempt == 14:
                        raise
                    time.sleep(1)
        except BaseException:
            shutil.copy2(backup, envfile)
            run([binary, 'restart', 'videocall_server'], env=environment)
            raise
        print(json.dumps({'api_activated': True, 'environment_backup_verified': True, 'healthy_commit': expected_commit}))
    else:
        raise ValueError('Unknown TURN action')


if __name__ == '__main__':
    with open('/www/backup/bondvia-deploy/deploy.lock', 'a') as lock:
        fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
        main(json.loads(base64.b64decode(sys.argv[1])))
