#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
JSON Schema definitions for configuration file validation.
"""

from typing import Any, Dict, List

# JSON Schema for header_config.json
HEADER_CONFIG_SCHEMA = {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "Header Configuration",
    "description": "Configuration for static header fields in PADneXt XML",
    "type": "object",
    "properties": {
        "nachrichtentyp_version": {
            "type": "string",
            "description": "Version of the message type",
            "default": "1.0"
        },
        "rechnungsersteller_name": {
            "type": "string",
            "description": "Name of the billing entity"
        },
        "rechnungsersteller_kundennr": {
            "type": "string",
            "description": "Customer number of billing entity"
        },
        "rechnungsersteller_strasse": {
            "type": "string",
            "description": "Street address of billing entity"
        },
        "rechnungsersteller_plz": {
            "type": "string",
            "description": "Postal code of billing entity",
            "pattern": "^[0-9]{5}$"
        },
        "rechnungsersteller_ort": {
            "type": "string",
            "description": "City of billing entity"
        },
        "rechnungsersteller_iknr": {
            "type": "string",
            "description": "IK number of billing entity (optional)"
        },
        "leistungserbringer_id": {
            "type": "string",
            "description": "ID of the service provider"
        },
        "leistungserbringer_titel": {
            "type": "string",
            "description": "Title of service provider (optional)"
        },
        "leistungserbringer_vorname": {
            "type": "string",
            "description": "First name of service provider"
        },
        "leistungserbringer_name": {
            "type": "string",
            "description": "Last name of service provider"
        },
        "empfaenger_anrede": {
            "type": "string",
            "description": "Salutation for recipient"
        },
        "empfaenger_vorname": {
            "type": "string",
            "description": "First name of recipient"
        },
        "empfaenger_name": {
            "type": "string",
            "description": "Last name of recipient"
        },
        "empfaenger_strasse": {
            "type": "string",
            "description": "Street address of recipient"
        },
        "empfaenger_plz": {
            "type": "string",
            "description": "Postal code of recipient"
        },
        "empfaenger_ort": {
            "type": "string",
            "description": "City of recipient"
        },
        "empfaenger_gebdatum": {
            "type": "string",
            "description": "Birth date of recipient",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
        },
        "behandelter_anrede": {
            "type": "string",
            "description": "Salutation for patient"
        },
        "behandelter_vorname": {
            "type": "string",
            "description": "First name of patient"
        },
        "behandelter_name": {
            "type": "string",
            "description": "Last name of patient"
        },
        "behandelter_gebdatum": {
            "type": "string",
            "description": "Birth date of patient",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
        },
        "behandelter_geschlecht": {
            "type": "string",
            "description": "Gender of patient",
            "enum": ["m", "w", "u"]
        },
        "versicherter_anrede": {
            "type": "string",
            "description": "Salutation for insured person"
        },
        "versicherter_vorname": {
            "type": "string",
            "description": "First name of insured person"
        },
        "versicherter_name": {
            "type": "string",
            "description": "Last name of insured person"
        },
        "versicherter_gebdatum": {
            "type": "string",
            "description": "Birth date of insured person",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
        },
        "versicherter_geschlecht": {
            "type": "string",
            "description": "Gender of insured person",
            "enum": ["m", "w", "u"]
        },
        "behandlungsart": {
            "type": "string",
            "description": "Type of treatment",
            "pattern": "^[0-5]$"
        },
        "vertragsart": {
            "type": "string",
            "description": "Type of contract",
            "pattern": "^[0-9]{1,3}$"
        },
        "aktenzeichen": {
            "type": "string",
            "description": "File reference (optional)"
        },
        "diagnose_text": {
            "type": "string",
            "description": "Diagnosis text"
        },
        "diagnose_datum": {
            "type": "string",
            "description": "Diagnosis date",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
        },
        "eabgabe": {
            "type": "string",
            "description": "Electronic submission (optional)"
        },
        "aisaktenzeichen": {
            "type": "string",
            "description": "AIS file reference (optional)"
        },
        "aisendbetrag": {
            "type": "string",
            "description": "AIS total amount (optional)"
        }
    },
    "additionalProperties": True  # Allow additional fields for flexibility
}

# JSON Schema for placeholder_config.json
PLACEHOLDER_CONFIG_SCHEMA = {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "Placeholder Configuration",
    "description": "Fallback values for missing required fields",
    "type": "object",
    "properties": {
        "rechnungsersteller": {
            "type": "object",
            "properties": {
                "name": {"type": "string"},
                "plz": {"type": "string", "pattern": "^[0-9]{5}$"},
                "ort": {"type": "string"},
                "strasse": {"type": "string"}
            },
            "required": ["name", "plz", "ort", "strasse"]
        },
        "leistungserbringer": {
            "type": "object",
            "properties": {
                "vorname": {"type": "string"},
                "name": {"type": "string"},
                "titel": {"type": ["string", "null"]}
            },
            "required": ["vorname", "name"]
        },
        "empfaenger": {
            "type": "object",
            "properties": {
                "anrede": {"type": "string"},
                "vorname": {"type": "string"},
                "name": {"type": "string"},
                "plz": {"type": "string"},
                "ort": {"type": "string"},
                "strasse": {"type": "string"},
                "gebdatum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},
                "geschlecht": {"type": "string", "enum": ["m", "w", "u"]}
            },
            "required": ["anrede", "vorname", "name", "plz", "ort", "strasse", "gebdatum"]
        },
        "behandelter": {
            "type": "object",
            "properties": {
                "anrede": {"type": ["string", "null"]},
                "vorname": {"type": "string"},
                "name": {"type": "string"},
                "gebdatum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},
                "geschlecht": {"type": "string", "enum": ["m", "w", "u"]}
            },
            "required": ["vorname", "name", "gebdatum", "geschlecht"]
        },
        "versicherter": {
            "type": "object",
            "properties": {
                "anrede": {"type": "string"},
                "vorname": {"type": "string"},
                "name": {"type": "string"},
                "gebdatum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},
                "geschlecht": {"type": "string", "enum": ["m", "w", "u"]}
            },
            "required": ["anrede", "vorname", "name", "gebdatum", "geschlecht"]
        },
        "rechnung": {
            "type": "object",
            "properties": {
                "eabgabe": {"type": ["string", "null"]},
                "aisaktenzeichen": {"type": ["string", "null"]},
                "aisendbetrag": {"type": ["string", "null"]}
            }
        },
        "abrechnungsfall": {
            "type": "object",
            "properties": {
                "behandlungsart": {"type": "string", "pattern": "^[0-5]$"},
                "vertragsart": {"type": "string", "pattern": "^[0-9]{1,3}$"}
            },
            "required": ["behandlungsart", "vertragsart"]
        },
        "zeitraum": {
            "type": "object",
            "properties": {
                "startdatum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},
                "endedatum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"}
            },
            "required": ["startdatum", "endedatum"]
        },
        "goziffer": {
            "type": "object",
            "properties": {
                "go": {"type": "string", "enum": ["GOAE", "UVGOAE", "EBM", "GOZ"]},
                "ziffer": {"type": "string", "maxLength": 8, "minLength": 1},
                "datum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"}
            },
            "required": ["go", "ziffer", "datum"]
        },
        "diagnose": {
            "type": "object",
            "properties": {
                "datum": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"}
            },
            "required": ["datum"]
        }
    },
    "required": ["rechnungsersteller", "leistungserbringer", "goziffer"],
    "additionalProperties": True
}

# JSON Schema for mapping_config.json
MAPPING_CONFIG_SCHEMA = {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "Mapping Configuration",
    "description": "Mapping rules from FHIR resources to PAD positions",
    "type": "object",
    "properties": {
        "resources": {
            "type": "object",
            "description": "Resource type to position mappings",
            "additionalProperties": {
                "type": "object",
                "properties": {
                    "target": {
                        "type": "string",
                        "description": "Target PAD element type",
                        "enum": ["goziffer"]
                    },
                    "fields": {
                        "type": "object",
                        "description": "Field mappings",
                        "additionalProperties": {
                            "type": "object",
                            "properties": {
                                "source": {
                                    "type": "string",
                                    "description": "Source field path in FHIR resource"
                                },
                                "default": {
                                    "type": "string",
                                    "description": "Default value if source is missing"
                                },
                                "required": {
                                    "type": "boolean",
                                    "description": "Whether this field is required"
                                },
                                "placeholder": {
                                    "type": "string",
                                    "description": "Placeholder value for required fields"
                                },
                                "translate": {
                                    "type": "object",
                                    "description": "Code translation rules",
                                    "properties": {
                                        "source_system_field": {"type": "string"},
                                        "source_code_field": {"type": "string"}
                                    }
                                }
                            }
                        }
                    }
                },
                "required": ["target", "fields"]
            }
        }
    },
    "required": ["resources"]
}


def validate_config(config: Dict[str, Any], schema: Dict[str, Any], config_name: str) -> List[str]:
    """
    Validate configuration against JSON schema.

    Args:
        config: The configuration dict to validate
        schema: The JSON schema to validate against
        config_name: Name of the config for error messages

    Returns:
        List of validation warnings (non-fatal issues)

    Raises:
        ValueError: If validation fails with errors

    Example:
        >>> config = {"rechnungsersteller": {...}}
        >>> warnings = validate_config(config, PLACEHOLDER_CONFIG_SCHEMA, "placeholder_config")
    """
    warnings = []

    try:
        import jsonschema
    except ImportError:
        warnings.append(f"jsonschema not available - skipping {config_name} validation")
        warnings.append("Install with: pip install jsonschema")
        return warnings

    try:
        jsonschema.validate(config, schema)
    except jsonschema.ValidationError as e:
        # Collect detailed error information
        error_path = " -> ".join(str(p) for p in e.path) if e.path else "root"
        error_msg = f"Validation error in {config_name} at {error_path}: {e.message}"
        raise ValueError(error_msg) from e
    except jsonschema.SchemaError as e:
        raise ValueError(f"Invalid schema for {config_name}: {e.message}") from e

    return warnings


def validate_header_config(config: Dict[str, Any]) -> List[str]:
    """Validate header configuration."""
    return validate_config(config, HEADER_CONFIG_SCHEMA, "header_config")


def validate_placeholder_config(config: Dict[str, Any]) -> List[str]:
    """Validate placeholder configuration."""
    return validate_config(config, PLACEHOLDER_CONFIG_SCHEMA, "placeholder_config")


def validate_mapping_config(config: Dict[str, Any]) -> List[str]:
    """Validate mapping configuration."""
    return validate_config(config, MAPPING_CONFIG_SCHEMA, "mapping_config")
