from pathlib import Path
import ast,json,re,html,shutil

REF='https://github.com/brendan-w/python-OBD/blob/e3be50335f7b96e53a02a1c0dbb9f888d9744c2f/obd/codes.py'
OEM='https://static.nhtsa.gov/odi/inv/2014/INRD-PE14030-61127P.pdf'
CRASH='https://static.nhtsa.gov/odi/inv/2010/INRD-EA10001-44822P.pdf'
GM='https://static.nhtsa.gov/odi/tsbs/2015/MC-10115014-9999.pdf'
VAG='https://wiki.ross-tech.com/wiki/index.php/'
ROUTES={'Network & communication':'electrical-can-diagnostics','Circuit & voltage':'electrical-can-diagnostics','Coding & configuration':'module-programming','Module electronics':'module-repair','Restraints & crash events':'srs-airbag-services','Chassis & body':'advanced-diagnostics','Mechanical & performance':'advanced-diagnostics'}
def category(c,d):
 t=d.lower()
 if any(x in t for x in ['programming','incompatib','configuration','vin ','not learned']):return 'Coding & configuration'
 if any(x in t for x in ['internal control','processor','memory','eeprom']):return 'Module electronics'
 if c.startswith('U'):return 'Network & communication'
 if any(x in t for x in ['circuit','voltage','electrical','relay','short','open']):return 'Circuit & voltage'
 return 'Mechanical & performance'
def data():
 tree=ast.parse(Path('reference-source/codes.py').read_text())
 defs=next(ast.literal_eval(n.value) for n in tree.body if isinstance(n,ast.Assign) and any(isinstance(x,ast.Name) and x.id=='DTC' for x in n.targets))
 rows={}
 for c,d in defs.items():
  if not d or 'reserved' in d.lower() or 'iso/sae' in d.lower():continue
  cat=category(c,d)
  rows[c]={'code':c,'description':d,'category':cat,'service':ROUTES[cat],'application':'General OBD reference — confirm the vehicle-specific definition and complete scan text.','source':REF,'sourceLabel':'python-OBD open reference','note':'This description identifies a monitored condition. Vehicle-specific testing establishes whether the cause is wiring, a component, software or a mechanical issue.'}
 def add(c,d,cat,app,source,note='Check the full scan report and the applicable manufacturer procedure before deciding the repair.'):
  rows[c]={'code':c,'description':d,'category':cat,'service':ROUTES[cat],'application':app,'source':source,'sourceLabel':'OEM technical reference' if 'nhtsa' in source else 'Ross-Tech technical reference','note':note}
 add('U3000','Control-module fault — the failure-type suffix identifies the reported condition.','Module electronics','Used by several manufacturers; identify the reporting module and full suffix.','https://www.gmupfitter.com/wp-content/uploads/2025/09/Suburban-Tahoe-Electrical-Body-Builder-Manual-Service-Manual-2026_en_US.pdf','Power, network, software and hardware need assessment. U3000 alone does not establish that a module must be replaced. Some Ford U3000:49 cruise-control applications have an OEM software-update remedy.')
 for suffix,meaning in [('41','General checksum failure'),('46','Calibration/parameter memory failure'),('49','Internal electronic failure'),('61','Signal calculation failure'),('72','Actuator stuck open'),('96','Component internal failure')]:add('U3000:'+suffix,'Control module: '+meaning,'Module electronics','Ford steering-controller technical examples; applicability depends on vehicle and module.',OEM)
 for suffix,meaning in [('16','Battery circuit voltage below threshold'),('17','Battery circuit voltage above threshold'),('68','Battery voltage event information')]:add('U3003:'+suffix,meaning,'Circuit & voltage','Ford technical example; confirm the reporting module.',OEM)
 add('U3003','Battery-voltage fault; retain the complete suffix.','Circuit & voltage','Manufacturer and module specific.',OEM)
 for c,d in [('U2100','Initial configuration not complete'),('U2101','Control-module configuration incompatible'),('U3002','Vehicle-identification fault; incorrect VIN in documented replacement-module applications')]:add(c,d,'Coding & configuration','Ford examples; not a universal repair instruction.','https://static.nhtsa.gov/odi/tsbs/2023/MC-10243479-0001.pdf' if c=='U3002' else OEM)
 for c,d in [('B1193','Crash-event memory full/locked in applicable Ford restraint systems'),('B1231','Event threshold exceeded in applicable Ford restraint systems')]:add(c,d,'Restraints & crash events','Ford restraint/occupant-classification applications; follow vehicle-specific post-collision requirements.',CRASH,'A stored crash event is different from an open or shorted circuit. This is an assessment enquiry, not a promise of reset eligibility. OEM procedures may require module, sensor or deployed-component replacement; clearing data does not establish system serviceability.')
 add('B0051','Airbag deployment commanded / stored deployment event in applicable GM systems.','Restraints & crash events','GM SDM application example; this meaning must not be applied to all manufacturers.','https://gm.saturn.team/Chevrolet/SSR/2005/50/8/4323/57999','Follow the applicable post-collision procedure. A latched deployment record may require replacement; reset availability is not implied by this reference.')
 for c,d in [('B1001','Option configuration error'),('B1325:03','Device power circuit voltage below threshold'),('B1370:06','Device ignition circuit short to ground'),('B0081:71','Passenger-presence system received invalid serial data'),('U2103','Fewer controllers present on the bus than configured')]:add(c,d,'Restraints & crash events' if c.startswith('B0081') else ('Circuit & voltage' if c.startswith(('B1325','B1370')) else 'Coding & configuration'),'GM examples; retain the symptom byte and module name.','https://static.nhtsa.gov/odi/inv/2011/INRD-EA11015-57392P.PDF')
 for suffix,d in [('00','ECU hardware malfunction'),('31','Internal checksum fault'),('32','General memory fault'),('37','Software fault'),('38','Supervision-software fault'),('39','Internal Bluetooth communication fault'),('3C','Internal GPS communication fault'),('F0','Internal phone communication fault')]:add('B101D:'+suffix,d,'Module electronics','GM OnStar examples; model coverage and suffix matter.',GM)
 for c,d in [('C0035','Left-front wheel-speed sensor circuit fault'),('C0040','Right-front wheel-speed sensor circuit fault'),('C0045','Left-rear wheel-speed sensor circuit fault'),('C0050','Right-rear wheel-speed sensor circuit fault')]:add(c,d,'Chassis & body','GM application examples; confirm model and symptom byte.','https://static.nhtsa.gov/odi/tsbs/2014/MC-10112074-9999.pdf','Wiring, sensor signals and the hub/encoder may need assessment. A wheel-speed circuit code does not by itself identify the part to replace.')
 for c,d in [('B1401:11','Emergency-call speaker circuit short to ground'),('B1401:12','Emergency-call speaker circuit short to battery'),('B1401:13','Emergency-call speaker circuit open'),('B1401:2B','Emergency-call speaker wires shorted together'),('B143A:12','Microphone 1 circuit short to battery'),('B143A:13','Microphone 1 circuit open'),('B143A:2B','Microphone 1 wires shorted together'),('B1560:13','Cellular antenna 1 circuit open'),('B1561:11','Cellular antenna 2 circuit short to ground'),('B1561:13','Cellular antenna 2 circuit open'),('B1562:14','GPS antenna circuit short to ground or open')]:add(c,d,'Circuit & voltage','Maserati DS 25-24 application examples.','https://static.nhtsa.gov/odi/tsbs/2025/MC-11021161-0001.pdf')
 for c,d,cat in [('01044','Control module incorrectly coded','Coding & configuration'),('02095','Component protection active','Coding & configuration'),('B2005','Invalid parameter/data record','Coding & configuration'),('B201A','Software Version Management check required','Coding & configuration'),('B2010','Basic setting missing','Coding & configuration'),('01314','Engine-controller reference: distinguish no communication from check DTC memory','Network & communication'),('01316','ABS-controller reference: distinguish no communication from check DTC memory','Network & communication'),('01309','Steering-controller reference: full fault text distinguishes communication, implausibility or module failure','Network & communication'),('00778','Steering-angle sensor fault: retain basic-setting, implausibility or communication detail','Chassis & body')]:add(c,d,cat,'VAG application; exact controller and fault text required.',VAG+c)
 for c,d in [('U112100','Databus message missing'),('U112200','Databus message implausible'),('U112300','Databus error value received')]:add(c,d,'Network & communication','VAG; retain symptom number and reporting module.','https://static.nhtsa.gov/odi/tsbs/2024/MC-10252428-0001.pdf')
 return sorted(rows.values(),key=lambda x:x['code'])
def apply():
 root=Path('dist');rows=data();(root/'fault-codes.json').write_text(json.dumps(rows,ensure_ascii=False))
 src=root/'reference-source';src.mkdir(exist_ok=True)
 for n in ['codes.py','COPYING.txt']:shutil.copy('reference-source/'+n,src/n)
 shutil.copy('fault_reference.py',src/'fault_reference.py')
 for n in ['fault-codes.js','fault-codes.css']:shutil.copy(n,root/n)
 p=root/'services/index.html';s=p.read_text();s=s.replace('<p id="results" role="status"></p>','<p id="results" role="status"></p><div class="code-directory-link"><a href="/fault-codes/">Browse the fault-code reference →</a></div><section id="dtc-panel" class="dtc-panel" hidden aria-label="Fault-code results"><h2>Related fault-code descriptions</h2><p id="dtc-status" role="status"></p><div id="dtc-results"></div><button id="dtc-more" class="btn secondary" type="button" hidden>Show more codes</button></section>')
 s=s.replace('</head>','<link rel="stylesheet" href="/fault-codes.css"></head>').replace('</body>','<script src="/fault-codes.js" defer></script></body>');p.write_text(s)
 template=(root/'advanced-diagnostics/index.html').read_text();body='''<main><div class="crumb"><a href="/">MSBG Automotive</a> / Fault-code reference</div><section class="section wide"><div class="eyebrow">Technical reference · '''+str(len(rows))+''' entries</div><h1>A code is a starting point.<br>Find the next step.</h1><p class="lead">Search communication faults, circuit problems, configuration errors, crash-event records and powertrain concerns. Bring us the complete scan report and the work already done so we can help your shop plan the assessment.</p><div class="cataloguebar"><div><label for="dtc-search">Fault code or description</label><input id="dtc-search" type="search" placeholder="U3000:49, short circuit, crash, misfire…"></div><div><label for="dtc-category">Fault category</label><select id="dtc-category"><option value="">All categories</option>'''+''.join('<option>'+html.escape(k)+'</option>' for k in ROUTES)+'''</select></div></div><section id="dtc-panel" class="dtc-panel"><p id="dtc-status" role="status">Loading reference…</p><div id="dtc-results"></div><button id="dtc-more" class="btn secondary" type="button" hidden>Show more codes</button></section><noscript><p>Enable JavaScript to search this reference, or <a href="/fault-codes.json">open the complete reference data</a>.</p></noscript></section><section class="section wide"><h2>Keep the complete fault code.</h2><p>U3000 is a control-module fault. U3000:41 and U3000:49 describe different reported conditions. The module that stored it, vehicle details and full suffix determine which diagnostic procedure applies. A description does not prove that the named part has failed.</p><p>For three-byte DTC formats, a suffix can identify an open circuit, short to ground, voltage fault, memory failure or mechanical condition. Suffixes vary with diagnostic format and manufacturer. We show supported examples instead of applying one suffix table to every vehicle.</p><h2>Crash data is a separate concern.</h2><p>A crash-event record, a deployed pretensioner and a restraint-circuit fault need different assessments. A reset is not a substitute for manufacturer-required replacement or post-collision inspection. Send the module part number, collision history and full scan report to confirm the available service.</p><a class="btn" href="/#book">Request a diagnostic assessment →</a></section><section class="section wide"><h2>Reference coverage and sources</h2><p>This reference combines the openly licensed python-OBD P/U-code list with selected OEM and Ross-Tech application examples. It is not the complete current SAE annex or a complete manufacturer database. General descriptions are not individually validated for every model. Body, chassis and crash-event coverage is selected, not exhaustive. Vehicle coverage and the work MSBG can perform are confirmed before booking; a mechanical code appearing here does not establish repair availability.</p><p>Each result links to its source. Open reference data is derived from python-OBD revision e3be50335f7b96e53a02a1c0dbb9f888d9744c2f, under GPL-2.0-or-later. The upstream list is older than current OEM coverage.</p><p><a href="/reference-source/codes.py">Upstream reference source</a> · <a href="/reference-source/fault_reference.py">Reference builder source</a> · <a href="/reference-source/COPYING.txt">Licence</a> · <a href="/fault-codes.json">Reference data</a></p></section></main>'''
 s=re.sub(r'<main>.*?</main>',lambda m:body,template,flags=re.S);s=re.sub(r'<title>.*?</title>','<title>Fault Code Lookup | Electrical, CAN & Module Diagnostics | MSBG</title>',s)
 s=re.sub(r'<link rel="canonical" href="[^"]*">','<link rel="canonical" href="https://www.msbgautomotive.ca/fault-codes/">',s)
 s=re.sub(r'<meta (?:name="description"|property="og:description") content="[^"]*">','<meta name="description" content="Search fault-code descriptions for communication, electrical circuits, module configuration and powertrain concerns. MSBG Automotive, Winnipeg.">',s,count=1)
 for prop,val in [('title','Fault Code Lookup | Electrical, CAN & Module Diagnostics | MSBG'),('description','Search communication, circuit, configuration and powertrain fault descriptions. Bring MSBG the full scan report for a vehicle-specific assessment.'),('url','https://www.msbgautomotive.ca/fault-codes/')]:
  s=re.sub(r'<meta property="og:'+prop+r'" content="[^"]*">',lambda m:'<meta property="og:'+prop+'" content="'+html.escape(val,quote=True)+'">',s)
 s=re.sub(r'<script type="application/ld\+json">.*?</script>','',s,flags=re.S)
 s=s.replace('</head>','<link rel="stylesheet" href="/fault-codes.css"></head>').replace('</body>','<script src="/fault-codes.js" defer></script></body>')
 p=root/'fault-codes/index.html';p.parent.mkdir(exist_ok=True);p.write_text(s)
 p=root/'index.html';s=p.read_text().replace('Browse all services →</a>','Browse all services →</a> <a href="/fault-codes/">Fault-code reference →</a>');p.write_text(s)
 p=root/'sitemap.xml';s=p.read_text();s=re.sub(r'<url><loc>https://www.msbgautomotive.ca/fault-codes/</loc>.*?</url>','',s);s=s.replace('</urlset>','<url><loc>https://www.msbgautomotive.ca/fault-codes/</loc></url></urlset>');p.write_text(s)
 print('Built searchable fault reference:',len(rows),'described entries, with source links and service routes.')
