from pathlib import Path
import compileall
import re
import zipfile

ROOT = Path(__file__).resolve().parents[1]
BACKEND = ROOT / "backend"

def read(rel):
    return (BACKEND / rel).read_text(encoding="utf-8")



def verify_documentation_version():
    expected = "v0.39.4-dev Consolidated"
    stale = re.compile(r"v0\.37\.(0|1)")
    history = {"CHANGELOG.txt", "UI-PATCH-v0.37.1.txt", "TRIAL-RELEASE-NOTES.txt", "PACKAGE-CONTENTS.txt"}
    for path in ROOT.rglob("*"):
        if not path.is_file() or "__pycache__" in path.parts:
            continue
        if path.name in history or path.suffix.lower() in {".pdf", ".zip", ".png", ".jpg", ".jpeg", ".pyc"}:
            continue
        if path.name in {"p2_static_verify.py", "package_consistency_check.py", "SHA256SUMS.txt"}:
            continue
        if path.suffix.lower() == ".docx":
            with zipfile.ZipFile(path) as zf:
                content = zf.read("word/document.xml").decode("utf-8", errors="ignore")
            if expected not in content:
                return False, f"DOCX current version missing: {path.relative_to(ROOT)}"
            if stale.search(content):
                return False, f"DOCX stale version: {path.relative_to(ROOT)}"
            continue
        try:
            content = path.read_text(encoding="utf-8-sig")
        except Exception:
            continue
        if stale.search(content):
            return False, f"Stale version outside history: {path.relative_to(ROOT)}"
    return True, "documentation/source version consistency"

checks = {
    "QA-015": [("templates/dashboard.html", "brand_company"), ("templates/base.html", "brand_company")],
    "QA-026": [("apps/organization/models.py", "uq_holiday_company_date_all_branches"), ("apps/organization/models.py", "condition=Q(branch__isnull=True)")],
    "QA-027": [("apps/attendance/models.py", "requested_by_user = models.ForeignKey"), ("apps/attendance/models.py", "requester_employee = models.ForeignKey"), ("apps/attendance/services.py", "is_self_service = bool(requester_employee and requester_employee.pk == attendance.employee_id)"), ("apps/workflow/services.py", "item.requested_by_user_id")],
    "QA-041": [("apps/reports/services.py", "HRPAY_BANGLA_FONT"), ("apps/reports/services.py", "shaping=True")],
    "QA-042": [("apps/payroll/forms.py", "def clean_payroll_month"), ("apps/payroll/models.py", "self.payroll_month = self.payroll_month.replace(day=1)")],
    "QA-052": [("apps/accounts/security.py", 'username="*"'), ("config/settings.py", "LOGIN_IP_MAX_FAILED_ATTEMPTS")],
    "QA-053": [("apps/accounts/management/commands/purge_login_attempts.py", "LOGIN_ATTEMPT_RETENTION_DAYS")],
    "QA-055": [("apps/core/management/commands/verify_backup.py", "Mandatory SHA-256 sidecar is missing")],
    "QA-067": [("apps/attendance/forms.py", "no_punch_statuses"), ("apps/attendance/forms.py", "Present/Late attendance requires a check-in timestamp")],
    "QA-078": [("apps/reports/views.py", "Days in Selected Window"), ("apps/leave/services.py", "def count_leave_days")],
    "QA-080": [("apps/reports/services.py", "def payroll_calculation_summary"), ("templates/reports/payslip.html", "Calculation Summary")],
    "QA-087": [("apps/organization/context_processors.py", "can_view_team"), ("templates/base.html", "can_manage_payroll")],
    "QA-088": [("apps/organization/context_processors.py", "role_label"), ("templates/base.html", "{{ role_label }}")],
    "QA-091": [("templates/employees/employee_detail.html", "Employee Documents"), ("templates/employees/employee_detail.html", "Additional / Custom Fields")],
    "QA-092": [("apps/attendance/views.py", "Paginator("), ("apps/leave/views.py", "Paginator("), ("apps/payroll/views.py", "Paginator("), ("apps/exits/views.py", "Paginator(")],
    "QA-093": [("apps/organization/views.py", "def master_lifecycle"), ("templates/employees/employee_detail.html", "Employment Action"), ("apps/employees/views.py", "def employee_lifecycle")],
    "QA-095": [("apps/employees/views.py", "def company_choice_options"), ("templates/employees/employee_form.html", "data-company-choices-url")],
}

ok_compile = compileall.compile_dir(str(BACKEND), quiet=1)
qa16_ok, qa16_msg = verify_documentation_version()
print("QA-016:", "STATIC EVIDENCE PASS" if qa16_ok else "FAIL", "-", qa16_msg)
print("Python compileall:", "PASS" if ok_compile else "FAIL")
failed=[]
if not qa16_ok:
    failed.append("QA-016")
for qa, evidences in checks.items():
    good=True
    for rel, needle in evidences:
        p=BACKEND/rel
        if not p.exists() or needle not in p.read_text(encoding="utf-8"):
            good=False
            print(f"{qa}: MISSING {rel} :: {needle}")
    if good:
        print(f"{qa}: STATIC EVIDENCE PASS")
    else:
        failed.append(qa)
if failed or not ok_compile:
    raise SystemExit(1)
print(f"{len(checks)+1} P2/P3 items have source-level remediation evidence. Runtime/UAT proof is still required where applicable.")
