"""Delivery-tree checks using only Python's standard library."""
import ast
from html.parser import HTMLParser
import json
from pathlib import Path
import re
import unittest
from urllib.parse import urlsplit

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


class Page(HTMLParser):
    def __init__(self,text):
        super().__init__();self.ids=[];self.refs=[];self.controls=[];self.inline_scripts=[];self.in_script=False
        self.feed(text)
    def handle_starttag(self,tag,attrs):
        attrs=dict(attrs)
        if 'id' in attrs:self.ids.append(attrs['id'])
        if 'aria-controls' in attrs:self.controls.append(attrs['aria-controls'])
        for key in ('src','href'):
            if key in attrs:self.refs.append(attrs[key])
        if tag=='script':self.in_script=True
    def handle_endtag(self,tag):
        if tag=='script':self.in_script=False
    def handle_data(self,data):
        if self.in_script and data.strip():self.inline_scripts.append(data)


class StructureTests(unittest.TestCase):
    def test_pages_have_unique_ids_and_valid_local_links(self):
        endpoints={'/ip','/ua','/port','/lang','/referer','/encoding','/mime','/forwarded','/host','/all.json'}
        for file in (ROOT/'public').glob('*.html'):
            page=Page(file.read_text())
            with self.subTest(page=file.name):
                self.assertEqual(len(page.ids),len(set(page.ids)))
                self.assertTrue(all(target in page.ids for target in page.controls))
                self.assertFalse(page.inline_scripts)
                for ref in page.refs:
                    path=urlsplit(ref).path
                    if ref.startswith('/') and path not in endpoints:
                        self.assertTrue((ROOT/'public'/path.lstrip('/')).exists(),ref)

    def test_page_scripts_reference_existing_elements(self):
        for name,script in [('ip.html','ip.js'),('access.html','access.js'),('wifi.html','wifi.js')]:
            ids=Page((ROOT/'public'/name).read_text()).ids
            for target in re.findall(r"\$\('([^']+)'\)",(ROOT/'public/assets'/script).read_text()):
                self.assertIn(target,ids)

    def test_service_origins_are_in_csp(self):
        catalog=json.loads((ROOT/'public/assets/services.json').read_text())
        config=(ROOT/'deploy/vishow.top.conf').read_text()
        self.assertEqual(len({s['id'] for s in catalog}),len(catalog))
        self.assertEqual(sum(s['category']=='ai' for s in catalog),9)
        for service in catalog:
            split=urlsplit(service['url'])
            self.assertEqual(split.scheme,'https')
            self.assertIn('https://'+split.netloc,config)

    def test_legacy_telemetry_is_not_in_network_code(self):
        code=(ROOT/'backend/diagnostics.py').read_text()+(ROOT/'check.sh').read_text()
        for host in ('hits.xykt.de','ipinfo.check.place','upload.check.place','widget/demo'):
            self.assertNotIn(host,code)
        self.assertNotIn('eval(',code)
        self.assertNotIn('shell=True',code)

    def test_required_components_and_modes(self):
        required=['check.sh','backend/app.py','backend/diagnostics.py','public/index.html','public/ip.html',
                  'public/access.html','public/password.html','public/totp.html','public/assets/style.css',
                  'public/assets/site.js','public/assets/services.json','public/wifi.html',
                  'public/assets/wifi.js','public/assets/wifi-core.js','public/assets/wifi.css',
                  'public/assets/qrcodegen.js','public/assets/field-notes.css','LICENSE','README.md','NOTICE.md']
        for name in required:self.assertTrue((ROOT/name).is_file(),name)
        self.assertEqual((ROOT/'check.sh').stat().st_mode&0o777,0o755)
        for file in (ROOT/'backend').glob('*.py'):ast.parse(file.read_text())

    def test_wifi_navigation_theme_and_privacy(self):
        for file in (ROOT/'public').glob('*.html'):
            text=file.read_text()
            self.assertIn('href="/wifi.html"',text)
            self.assertIn('href="/assets/field-notes.css"',text)
        for name in ('wifi.js','wifi-core.js','qrcodegen.js'):
            code=(ROOT/'public/assets'/name).read_text()
            for forbidden in ('fetch(', 'XMLHttpRequest', 'sendBeacon', 'localStorage', 'sessionStorage'):
                self.assertNotIn(forbidden,code)


if __name__=='__main__':unittest.main()
