"""Read-only production evidence for the cross-backend audit; raw source stays private."""
import importlib.util
import json
from pathlib import Path
import subprocess

ROOT = Path(__file__).resolve().parents[1]
spec = importlib.util.spec_from_file_location('deployment_client', ROOT / 'scripts/deploy.py')
client = importlib.util.module_from_spec(spec)
spec.loader.exec_module(client)
config = client.configuration(ROOT / '.deploy/config.json')
js = r'''
const db=require('./db').promise;
(async()=>{
 const [tables]=await db.query("SELECT TABLE_NAME,ENGINE,TABLE_ROWS,DATA_LENGTH,INDEX_LENGTH FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE()");
 const [indexes]=await db.query("SELECT TABLE_NAME,INDEX_NAME,NON_UNIQUE,SEQ_IN_INDEX,COLUMN_NAME,CARDINALITY FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=DATABASE() ORDER BY TABLE_NAME,INDEX_NAME,SEQ_IN_INDEX");
 const [columns]=await db.query("SELECT TABLE_NAME,COLUMN_NAME,COLUMN_TYPE,IS_NULLABLE,COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME IN ('users','messages','chat_requests','user_interest','user_album','user_filters','video_call_sessions','user_block','user_followers','user_stories','user_config','call_sessions')");
 const [status]=await db.query("SHOW GLOBAL STATUS WHERE Variable_name IN ('Uptime','Threads_connected','Threads_running','Max_used_connections','Slow_queries','Questions','Created_tmp_disk_tables','Created_tmp_tables','Innodb_buffer_pool_reads','Innodb_buffer_pool_read_requests','Aborted_connects')");
 const explains={};
 const queries={
  history:[`SELECT id FROM messages WHERE ((sender_id=? AND receiver_id=?) OR (sender_id=? AND receiver_id=?)) AND deleted_at IS NULL ORDER BY id DESC LIMIT 20`,[166828,166829,166829,166828]],
  unread:[`SELECT COUNT(*) FROM messages WHERE receiver_id=? AND sender_id=? AND is_read=0`,[166828,166829]],
  reverse_block:[`SELECT user_id FROM user_block WHERE user_block_id=?`,[166828]],
  followers:[`SELECT user_id FROM user_followers WHERE follower_id=?`,[166828]],
  discovery:[`SELECT u.id FROM users u WHERE u.status=1 AND u.deleted_at IS NULL AND LOWER(TRIM(u.country))=LOWER(TRIM(?)) AND LOWER(TRIM(u.gender))=LOWER(TRIM(?)) AND EXISTS (SELECT 1 FROM user_interest ui WHERE ui.user_id=u.id) ORDER BY u.created_at DESC,u.id DESC LIMIT 200`,['Pakistan','male']],
  search:[`SELECT id,name FROM users WHERE status=1 AND deleted_at IS NULL AND name LIKE ? ORDER BY name,id LIMIT 20`,['QA%']],
 };
 for(const [name,[sql,params]] of Object.entries(queries)){const [rows]=await db.query('EXPLAIN '+sql,params);explains[name]=rows;}
 const [variables]=await db.query("SHOW GLOBAL VARIABLES WHERE Variable_name IN ('version','max_connections','innodb_buffer_pool_size','slow_query_log','long_query_time','performance_schema','query_cache_type','query_cache_size')");
 console.log('AUDIT_DB='+JSON.stringify({tables,indexes,columns,status,variables,explains}));
})().catch(()=>{console.log('AUDIT_DB_ERROR=true');process.exitCode=1}).finally(()=>db.end());
'''
code = r'''
import json, subprocess, os, hashlib
from pathlib import Path
node=Path('/www/wwwroot/connectlyvideochat.com/Videocall')
php=Path('/www/wwwroot/app.connectlyvideochat.com')
def cmd(args):
 r=subprocess.run(args,capture_output=True,text=True,timeout=30)
 return {'status':r.returncode,'stdout':r.stdout[:20000],'stderr':r.stderr[:1000]}
files={}
for folder in ['app','routes','config']:
 for p in (php/folder).rglob('*.php'):
  if not p.is_symlink(): files[str(p.relative_to(php))]=p.read_text(errors='replace')
for name in ['composer.json','composer.lock']:
 files[name]=(php/name).read_text()
versions={'node':cmd(['/www/server/nodejs/v20.19.2/bin/node','--version']),
 'php':cmd(['/www/server/php/83/bin/php','-v']), 'apache':cmd(['/www/server/apache/bin/httpd','-v']),
 'openssl':cmd(['openssl','version']), 'disk':cmd(['df','-h',str(node)]), 'memory':cmd(['free','-m']),
 'load':cmd(['uptime']), 'listeners':cmd(['ss','-lntu']), 'firewall':cmd(['ufw','status'])}
binary='/www/server/nodejs/v20.19.2/bin'
env={**os.environ,'PATH':binary+':'+os.environ['PATH'],'PM2_HOME':'/root/.pm2'}
processes=json.loads(subprocess.check_output([binary+'/pm2','jlist'],env=env,text=True))
target=next(p for p in processes if p['name']=='videocall_server')
procenv=target['pm2_env']
settings={k:procenv.get(k) for k in ['MOBILE_REQUIRE_AUTH','NODE_ENV','watch','exec_mode','instances','kill_timeout','restart_time','status']}
# Only explicitly safe flags are emitted; never serialize the full environment.
for line in (node/'.env').read_text().splitlines():
 if '=' in line:
  k,v=line.split('=',1)
  if k in ['MOBILE_REQUIRE_AUTH','NODE_ENV','API_RATE_LIMIT','TURN_ENABLED'] and settings.get(k) is None: settings[k]=v
php_settings={}
for line in (php/'.env').read_text().splitlines():
 if '=' in line:
  k,v=line.split('=',1)
  if k in ['APP_ENV','APP_DEBUG','SESSION_SECURE_COOKIE','SESSION_SAME_SITE','QUEUE_CONNECTION','CACHE_DRIVER']:php_settings[k]=v
runtime=cmd(['/www/server/php/83/bin/php','-r','echo json_encode(["opcache_enabled"=>ini_get("opcache.enable"),"opcache_validate_timestamps"=>ini_get("opcache.validate_timestamps"),"memory_limit"=>ini_get("memory_limit"),"upload_max_filesize"=>ini_get("upload_max_filesize"),"post_max_size"=>ini_get("post_max_size"),"display_errors"=>ini_get("display_errors")]);'])
fpm=subprocess.run(['/www/server/php/83/sbin/php-fpm','-i'],text=True,capture_output=True,timeout=30)
fpm_selected=[line for line in fpm.stdout.splitlines() if line.startswith(('Server API','opcache.enable =>','opcache.validate_timestamps =>','display_errors =>','Loaded Configuration File'))]

overrides={k:str(v) for k,v in procenv.items() if k.startswith('DB_')}
r=subprocess.run([binary+'/node','-'],cwd=node,input=__AUDIT_DATABASE_JS__,text=True,capture_output=True,env={**env,**overrides},timeout=45)
database={}
for line in r.stdout.splitlines():
 if line.startswith('AUDIT_DB='):database=json.loads(line.split('=',1)[1])
print(json.dumps({'php_files':files,'versions':versions,'node_settings':settings,'php_settings':php_settings,'php_cli_settings':runtime,'php_fpm_settings':fpm_selected,
 'database':database,'node_memory':target.get('monit'),
 'node_installed_versions':cmd(['/www/server/nodejs/v20.19.2/bin/node','-e',"console.log(JSON.stringify(Object.fromEntries(['express','mysql2','socket.io'].map(name=>[name,require('/www/wwwroot/connectlyvideochat.com/Videocall/node_modules/'+name+'/package.json').version]))))"]),
 'php_route_audit':cmd(['/www/server/php/83/bin/php','-r',"chdir('/www/wwwroot/app.connectlyvideochat.com'); require 'vendor/autoload.php'; $app=require 'bootstrap/app.php'; $app->make(\\Illuminate\\Contracts\\Console\\Kernel::class)->bootstrap(); $actions=array_map(fn($route)=>$route->getActionName(),app('router')->getRoutes()->getRoutes()); $banned=['App\\\\Http\\\\Controllers\\\\HomeController@licence_details','App\\\\Http\\\\Controllers\\\\HomeController@destroy_data','App\\\\Http\\\\Controllers\\\\HomeController@update_date','App\\\\Http\\\\Controllers\\\\Admin\\\\HomeController@get_details']; echo json_encode(['destructive_actions_registered'=>array_values(array_intersect($banned,$actions)),'debug'=>config('app.debug'),'environment'=>config('app.env')]);"]),
 'php_installed':json.loads((php/'vendor/composer/installed.json').read_text()),
 'php_cached_config_exists':(php/'bootstrap/cache/config.php').exists(),
 'php_route_cache_files':[p.name for p in (php/'bootstrap/cache').glob('routes*.php')],
 'php_upload_rules':{str(p.relative_to(php)):p.read_text() for folder in ['uploads','public/uploads','public/photo_album','public'] for p in (php/folder).glob('.htaccess') if p.is_file()},
 'health':cmd(['curl','-fsS','http://127.0.0.1:3000/health']),
 'node_lock':(node/'package-lock.json').read_text(),'node_package':(node/'package.json').read_text()}))
'''.replace('__AUDIT_DATABASE_JS__', repr(js))
result = subprocess.run(['ssh', '-p', str(config['port']), *client.ssh_options(config),
                         f"{config['user']}@{config['host']}", 'python3 -'], input=code,text=True,capture_output=True,check=True)
folder=ROOT / '.deploy/audit'
folder.mkdir(exist_ok=True,mode=0o700)
path=folder/'production.json';path.write_text(result.stdout);path.chmod(0o600)
data=json.loads(result.stdout)
source=folder/'php';source.mkdir(exist_ok=True,mode=0o700)
for name,value in data.pop('php_files').items():
 target=source/name;target.parent.mkdir(parents=True,exist_ok=True,mode=0o700);target.write_text(value);target.chmod(0o600)
(folder/'package-lock.json').write_text(data.pop('node_lock'))
(folder/'package.json').write_text(data.pop('node_package'))
print(json.dumps({key:data[key] for key in ['versions','node_settings','php_settings','php_cli_settings','php_fpm_settings','node_installed_versions','php_route_audit','node_memory','health']},indent=2))
print('Private source snapshot captured; database tables:',len(data['database'].get('tables',[])))
