#!/usr/bin/env python3
"""Validate an OpenPMX 2026 private exchange file against its public profile."""

from __future__ import annotations

import argparse
import sys
from pathlib import Path

from lxml import etree, isoschematron


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


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("file", type=Path, help="OpenPMX XML file to validate")
    args = parser.parse_args()

    try:
        parser = etree.XMLParser(
            resolve_entities=False,
            load_dtd=False,
            no_network=True,
        )
        document = etree.parse(str(args.file), parser)
        if document.docinfo.doctype:
            print("OpenPMX XML validation failed: DOCTYPE declarations are not permitted.", file=sys.stderr)
            return 1
        xml_schema = etree.XMLSchema(etree.parse(str(ROOT / "schemas/openpmx.xsd")))
        if not xml_schema.validate(document):
            print("OpenPMX XML Schema validation failed:", file=sys.stderr)
            for error in xml_schema.error_log:
                print(f"  {error.message} (line {error.line})", file=sys.stderr)
            return 1

        rules = isoschematron.Schematron(
            etree.parse(str(ROOT / "schemas/openpmx.sch")),
            store_report=True,
        )
        if not rules.validate(document):
            print("OpenPMX publish-profile validation failed:", file=sys.stderr)
            report = rules.validation_report
            if report is not None:
                for failure in report.xpath(
                    "//*[local-name()='failed-assert']/*[local-name()='text']"
                ):
                    print(f"  {''.join(failure.itertext()).strip()}", file=sys.stderr)
            return 1

    except (OSError, etree.XMLSyntaxError, etree.XMLSchemaParseError, etree.SchematronParseError) as error:
        print(f"OpenPMX validation error: {error}", file=sys.stderr)
        return 2

    print(f"Valid OpenPMX property file: {args.file}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
