"""Local Windows integration harness; isolated MariaDB and HTTP server, no existing databases."""
from pathlib import Path
import os, subprocess, tempfile, socket, time, shutil, secrets, json, re
from urllib.request import build_opener, HTTPCookieProcessor, Request
from urllib.error import HTTPError
from urllib.parse import urlencode
from http.cookiejar import CookieJar

ROOT=Path(__file__).resolve().parents[1]
PHP=Path(os.environ.get('MESRA_TEST_PHP',r'C:\wamp64\bin\php\php8.2.26\php.exe'))
BIN=Path(os.environ.get('MESRA_TEST_MARIADB',r'C:\wamp64\bin\mariadb\mariadb11.5.2\bin'))
HIDDEN=getattr(subprocess,'CREATE_NO_WINDOW',0)
def port():
 with socket.socket() as s: s.bind(('127.0.0.1',0));return s.getsockname()[1]
qa=Path(tempfile.mkdtemp(prefix='qa-',dir=ROOT/'storage'))
dbport,httpport=port(),port()
password=secrets.token_hex(20)
env={**os.environ,'MYSQL_PWD':password,'XDEBUG_MODE':'off'}
processes=[]; handles=[]; passed=[]
def check(ok,label):
 if not ok: raise AssertionError(label)
 passed.append(label);print('PASS:',label,flush=True)
def run(args,**kwargs):
 return subprocess.run([str(x) for x in args],env=env,creationflags=HIDDEN,capture_output=True,text=True,check=True,timeout=90,**kwargs)
def sql(query):
 return run([BIN/'mariadb.exe','--no-defaults','--protocol=tcp','-h127.0.0.1',f'-P{dbport}','-uroot','-N','-B','-e',query]).stdout.strip()
def spawn(args,name):
 f=open(qa/name,'w');handles.append(f)
 p=subprocess.Popen([str(x) for x in args],env=env,stdout=f,stderr=f,creationflags=HIDDEN);processes.append(p);return p
try:
 run([BIN/'mariadb-install-db.exe',f'--datadir={qa/"db"}',f'--password={password}',f'--port={dbport}','--silent'])
 db=spawn([BIN/'mariadbd.exe','--no-defaults',f'--datadir={qa/"db"}',f'--port={dbport}','--bind-address=127.0.0.1','--skip-log-bin','--console'],'database.log')
 for _ in range(100):
  try: sql('SELECT 1');break
  except Exception:
   if db.poll() is not None: raise RuntimeError('Isolated database startup failed; inspect QA logs.')
   time.sleep(.2)
 else: raise RuntimeError('Database startup timed out')
 sql('CREATE DATABASE mesra_qa CHARACTER SET utf8mb4')
 app=qa/'application'
 for name in ['app','public','database','cron']:shutil.copytree(ROOT/name,app/name)
 (app/'config').mkdir();(app/'storage').mkdir()
 secret=secrets.token_hex(32)
 def quote(s):return "'"+str(s).replace('\\','\\\\').replace("'","\\'")+"'"
 config={'dsn':f'mysql:host=127.0.0.1;port={dbport};dbname=mesra_qa;charset=utf8mb4','db_user':'root','db_password':password,'canonical_url':f'http://127.0.0.1:{httpport}','site_name':'Independent QA','timezone':'Asia/Kuala_Lumpur','setup_secret':secret}
 (app/'config/local.php').write_text('<?php return ['+','.join(quote(k)+'=>'+quote(v) for k,v in config.items())+',\'require_https\'=>false];',encoding='utf-8')
 server=spawn([PHP,'-d','xdebug.mode=off','-d',f'xdebug.log={qa/"xdebug.log"}','-S',f'127.0.0.1:{httpport}','-t',app/'public'],'http.log')
 jar=CookieJar();client=build_opener(HTTPCookieProcessor(jar))
 base=f'http://127.0.0.1:{httpport}/'
 def request(page='overview',data=None):
  req=Request(base+'?page='+page,data=urlencode(data).encode() if data is not None else None)
  try:
   with client.open(req,timeout=10) as res:return res.status,res.read().decode(),res.geturl(),res.headers
  except HTTPError as e:return e.code,e.read().decode(),e.geturl(),e.headers
 def token(body):return re.search(r'name="csrf" value="([a-f0-9]+)"',body).group(1)
 for _ in range(50):
  try: status,body,_,_=request();break
  except OSError:time.sleep(.1)
 check(status==200 and 'Install independent core' in body,'Fresh installation wizard')
 status,_,_,_=request('install',{'csrf':'bad'});check(status==403,'Installer rejects invalid CSRF')
 _,body,_,_=request('install')
 status,body,_,_=request('install',{'csrf':token(body),'email':'qa@example.test','password':'independent-test-password','setup_secret':'wrong'})
 check(status==503 and sql("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='mesra_qa'")=='0','Invalid setup secret creates no tables')
 _,body,_,_=request('install')
 status,body,url,_=request('install',{'csrf':token(body),'email':'qa@example.test','password':'independent-test-password','setup_secret':secret})
 check(status==200 and 'page=login' in url and 'Welcome back' in body,'Authorized setup creates administrator and redirects to login')
 check(sql('SELECT COUNT(*) FROM mesra_qa.users')=='1' and sql('SELECT COUNT(*) FROM mesra_qa.schema_migrations')=='1','Core migration and administrator recorded once')
 _,locked,url,_=request('install');check('page=login' in url,'Installer locks after completion')
 _,unauthorized,url,_=request('health');check('page=health' in url and 'Welcome back' in unauthorized and 'Installation health' not in unauthorized,'Health data requires sign-in')
 before=next(c.value for c in jar if c.name=='mesra_analytics')
 status,body,url,headers=request('login',{'csrf':token(unauthorized),'email':'qa@example.test','password':'independent-test-password'})
 after=next(c.value for c in jar if c.name=='mesra_analytics')
 check(status==200 and 'A clear view' in body and before!=after,'Login succeeds and rotates session ID')
 check('Demonstration data only' in body and 'Not connected' in body,'Dashboard separates demo values and unavailable analytics')
 preview=ROOT/'docs/preview';preview.mkdir(parents=True,exist_ok=True)
 shutil.copytree(ROOT/'public/assets',preview/'assets',dirs_exist_ok=True)
 safe=re.sub(r'<script.*?</script>','',body)
 safe=re.sub(r'name="csrf" value="[^"]+"','name="csrf" value="offline-preview"',safe)
 safe=safe.replace('Independent QA','Static design preview · demonstration only')
 (preview/'index.html').write_text(safe,encoding='utf-8')
 check(headers.get('Content-Security-Policy') is not None and headers.get('Cache-Control')=='no-store','Security and no-store headers')
 _,body,_,_=request('health');check('Core migration applied' in body and 'Healthy' in body,'Authenticated health report')
 status,_,_,_=request('logout',{'csrf':'invalid'});check(status==403,'Logout requires valid CSRF')
 _,body,_,_=request()
 status,body,url,_=request('logout',{'csrf':token(body)});check('Welcome back' in body,'Logout destroys authenticated session')
 for _ in range(9):
  _,body,_,_=request('login')
  _,body,_,_=request('login',{'csrf':token(body),'email':'qa@example.test','password':'wrong-password'})
 _,body,_,_=request('login')
 status,body,_,_=request('login',{'csrf':token(body),'email':'qa@example.test','password':'independent-test-password'})
 check('Sign-in failed or temporarily limited' in body,'Rate limit blocks repeated attempts, including valid password')
 result=run([PHP,'-d','xdebug.mode=off','-d',f'xdebug.log={qa/"xdebug.log"}',app/'cron/maintenance.php'])
 check('Maintenance complete' in result.stdout and sql("SELECT status FROM mesra_qa.cron_runs ORDER BY id DESC LIMIT 1")=='success','CLI maintenance records success')
 db.terminate();db.wait(timeout=15)
 status,body,_,_=request('login');check(status==503 and 'service is unavailable' in body and password not in body,'Database outage is isolated with sanitized error')
 summary={'passed':passed,'count':len(passed),'database':'isolated MariaDB 11.5.2','php':'8.2.26','browser_visual_qa':'not run'}
 (ROOT/'tests/integration-results.json').write_text(json.dumps(summary,indent=2),encoding='utf-8')
 print(f'PASS: {len(passed)} integration checks',flush=True)
finally:
 for p in reversed(processes):
  if p.poll() is None:
   p.terminate()
   try:p.wait(timeout=15)
   except subprocess.TimeoutExpired:p.kill();p.wait(timeout=10)
 for f in handles:f.close()
 # Keep isolated test files private for diagnosis; never include storage/qa-* in a release.
 print('QA artifacts:',qa,flush=True)
