# SPDX-FileCopyrightText: 2024 James R. Barlow
# SPDX-License-Identifier: MPL-2.0

"""Interface to verapdf executable."""

from __future__ import annotations

import json
import logging
from pathlib import Path
from subprocess import PIPE
from typing import NamedTuple

from ocrmypdf._exec._probe import ToolProbe
from ocrmypdf.exceptions import MissingDependencyError
from ocrmypdf.subprocess import run

log = logging.getLogger(__name__)


class ValidationResult(NamedTuple):
    """Result of PDF/A validation."""

    valid: bool
    failed_rules: int
    message: str


PROBE = ToolProbe(
    program='verapdf',
    version_regex=r'veraPDF (\d+(\.\d+)*)',
    also_catch=(OSError,),
)
version = PROBE.version
available = PROBE.available


def output_type_to_flavour(output_type: str) -> str:
    """Map OCRmyPDF output_type to verapdf flavour.

    Args:
        output_type: One of 'pdfa', 'pdfa-1', 'pdfa-2', 'pdfa-3'

    Returns:
        verapdf flavour string like '1b', '2b', '3b'
    """
    mapping = {
        'pdfa': '2b',
        'pdfa-1': '1b',
        'pdfa-2': '2b',
        'pdfa-3': '3b',
    }
    return mapping.get(output_type, '2b')


def validate(input_file: Path, flavour: str) -> ValidationResult:
    """Validate a PDF against a PDF/A profile.

    Args:
        input_file: Path to PDF file to validate
        flavour: verapdf flavour (1a, 1b, 2a, 2b, 2u, 3a, 3b, 3u)

    Returns:
        ValidationResult with validation status
    """
    args = [
        'verapdf',
        '--format',
        'json',
        '--flavour',
        flavour,
        str(input_file),
    ]

    try:
        proc = run(args, stdout=PIPE, stderr=PIPE, check=False)
    except FileNotFoundError as e:
        raise MissingDependencyError('verapdf') from e

    try:
        result = json.loads(proc.stdout)
        jobs = result.get('report', {}).get('jobs', [])
        if not jobs:
            return ValidationResult(False, -1, 'No validation jobs in result')
        validation_results = jobs[0].get('validationResult', [])
        if not validation_results:
            return ValidationResult(False, -1, 'No validation result in output')
        validation_result = validation_results[0]
        details = validation_result.get('details', {})
        failed_rules = details.get('failedRules', 0)

        if failed_rules == 0:
            return ValidationResult(True, 0, 'PDF/A validation passed')
        else:
            return ValidationResult(
                False,
                failed_rules,
                f'PDF/A validation failed with {failed_rules} rule violations',
            )
    except (json.JSONDecodeError, KeyError, TypeError) as e:
        log.debug('Failed to parse verapdf output: %s', e)
        return ValidationResult(False, -1, f'Failed to parse verapdf output: {e}')
