# coding: utf-8

"""
    API REST FactPulse

     API REST pour la facturation électronique en France : Factur-X, AFNOR PDP/PA, signatures électroniques.  ## 🎯 Fonctionnalités principales  ### 📄 Génération de factures Factur-X - **Formats** : XML seul ou PDF/A-3 avec XML embarqué - **Profils** : MINIMUM, BASIC, EN16931, EXTENDED - **Normes** : EN 16931 (directive UE 2014/55), ISO 19005-3 (PDF/A-3), CII (UN/CEFACT) - **🆕 Format simplifié** : Génération à partir de SIRET + auto-enrichissement (API Chorus Pro + Recherche Entreprises)  ### ✅ Validation et conformité - **Validation XML** : Schematron (45 à 210+ règles selon profil) - **Validation PDF** : PDF/A-3, métadonnées XMP Factur-X, signatures électroniques - **VeraPDF** : Validation stricte PDF/A (146+ règles ISO 19005-3) - **Traitement asynchrone** : Support Celery pour validations lourdes (VeraPDF)  ### 📡 Intégration AFNOR PDP/PA (XP Z12-013) - **Soumission de flux** : Envoi de factures vers Plateformes de Dématérialisation Partenaires - **Recherche de flux** : Consultation des factures soumises - **Téléchargement** : Récupération des PDF/A-3 avec XML - **Directory Service** : Recherche d'entreprises (SIREN/SIRET) - **Multi-client** : Support de plusieurs configs PDP par utilisateur (stored credentials ou zero-storage)  ### ✍️ Signature électronique PDF - **Standards** : PAdES-B-B, PAdES-B-T (horodatage RFC 3161), PAdES-B-LT (archivage long terme) - **Niveaux eIDAS** : SES (auto-signé), AdES (CA commerciale), QES (PSCO) - **Validation** : Vérification intégrité cryptographique et certificats - **Génération de certificats** : Certificats X.509 auto-signés pour tests  ### 🔄 Traitement asynchrone - **Celery** : Génération, validation et signature asynchrones - **Polling** : Suivi d'état via `/taches/{id_tache}/statut` - **Pas de timeout** : Idéal pour gros fichiers ou validations lourdes  ## 🔒 Authentification  Toutes les requêtes nécessitent un **token JWT** dans le header Authorization : ``` Authorization: Bearer YOUR_JWT_TOKEN ```  ### Comment obtenir un token JWT ?  #### 🔑 Méthode 1 : API `/api/token/` (Recommandée)  **URL :** `https://www.factpulse.fr/api/token/`  Cette méthode est **recommandée** pour l'intégration dans vos applications et workflows CI/CD.  **Prérequis :** Avoir défini un mot de passe sur votre compte  **Pour les utilisateurs inscrits via email/password :** - Vous avez déjà un mot de passe, utilisez-le directement  **Pour les utilisateurs inscrits via OAuth (Google/GitHub) :** - Vous devez d'abord définir un mot de passe sur : https://www.factpulse.fr/accounts/password/set/ - Une fois le mot de passe créé, vous pourrez utiliser l'API  **Exemple de requête :** ```bash curl -X POST https://www.factpulse.fr/api/token/ \\   -H \"Content-Type: application/json\" \\   -d '{     \"username\": \"votre_email@example.com\",     \"password\": \"votre_mot_de_passe\"   }' ```  **Réponse :** ```json {   \"access\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\",  // Token d'accès (validité: 30 min)   \"refresh\": \"eyJ0eXAiOiJKV1QiLCJhbGc...\"  // Token de rafraîchissement (validité: 7 jours) } ```  **Avantages :** - ✅ Automatisation complète (CI/CD, scripts) - ✅ Gestion programmatique des tokens - ✅ Support du refresh token pour renouveler automatiquement l'accès - ✅ Intégration facile dans n'importe quel langage/outil  #### 🖥️ Méthode 2 : Génération via Dashboard (Alternative)  **URL :** https://www.factpulse.fr/dashboard/  Cette méthode convient pour des tests rapides ou une utilisation occasionnelle via l'interface graphique.  **Fonctionnement :** - Connectez-vous au dashboard - Utilisez les boutons \"Generate Test Token\" ou \"Generate Production Token\" - Fonctionne pour **tous** les utilisateurs (OAuth et email/password), sans nécessiter de mot de passe  **Types de tokens :** - **Token Test** : Validité 24h, quota 1000 appels/jour (gratuit) - **Token Production** : Validité 7 jours, quota selon votre forfait  **Avantages :** - ✅ Rapide pour tester l'API - ✅ Aucun mot de passe requis - ✅ Interface visuelle simple  **Inconvénients :** - ❌ Nécessite une action manuelle - ❌ Pas de refresh token - ❌ Moins adapté pour l'automatisation  ### 📚 Documentation complète  Pour plus d'informations sur l'authentification et l'utilisation de l'API : https://www.factpulse.fr/documentation-api/     

    The version of the OpenAPI document: 1.0.0
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501


from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from factpulse.models.information_signature_api import InformationSignatureAPI
from typing import Optional, Set
from typing_extensions import Self

class ResultatValidationPDFAPI(BaseModel):
    """
    Résultat complet de la validation d'un PDF Factur-X.
    """ # noqa: E501
    est_conforme: StrictBool = Field(description="True si le PDF est conforme à tous les critères (XML, PDF/A, XMP)")
    xml_present: StrictBool = Field(description="True si un XML Factur-X est embarqué dans le PDF")
    xml_conforme: StrictBool = Field(description="True si le XML Factur-X est conforme aux règles Schematron")
    profil_detecte: Optional[StrictStr] = None
    erreurs_xml: Optional[List[StrictStr]] = Field(default=None, description="Liste des erreurs de validation XML")
    pdfa_conforme: StrictBool = Field(description="True si le PDF est conforme PDF/A")
    version_pdfa: Optional[StrictStr] = None
    methode_validation_pdfa: Optional[StrictStr] = Field(default='metadata', description="Méthode utilisée pour la validation PDF/A (metadata ou verapdf)")
    regles_validees: Optional[StrictInt] = None
    regles_echouees: Optional[StrictInt] = None
    erreurs_pdfa: Optional[List[StrictStr]] = Field(default=None, description="Liste des erreurs de conformité PDF/A")
    avertissements_pdfa: Optional[List[StrictStr]] = Field(default=None, description="Liste des avertissements PDF/A")
    xmp_present: StrictBool = Field(description="True si des métadonnées XMP sont présentes")
    xmp_conforme_facturx: StrictBool = Field(description="True si les métadonnées XMP contiennent des informations Factur-X")
    profil_xmp: Optional[StrictStr] = None
    version_xmp: Optional[StrictStr] = None
    erreurs_xmp: Optional[List[StrictStr]] = Field(default=None, description="Liste des erreurs de métadonnées XMP")
    metadonnees_xmp: Optional[Dict[str, Any]] = Field(default=None, description="Métadonnées XMP extraites du PDF")
    est_signe: StrictBool = Field(description="True si le PDF contient au moins une signature")
    nombre_signatures: Optional[StrictInt] = Field(default=0, description="Nombre de signatures électroniques trouvées")
    signatures: Optional[List[InformationSignatureAPI]] = Field(default=None, description="Liste des signatures trouvées avec leurs informations")
    erreurs_signatures: Optional[List[StrictStr]] = Field(default=None, description="Liste des erreurs lors de l'analyse des signatures")
    message_resume: StrictStr = Field(description="Message résumant le résultat de la validation")
    __properties: ClassVar[List[str]] = ["est_conforme", "xml_present", "xml_conforme", "profil_detecte", "erreurs_xml", "pdfa_conforme", "version_pdfa", "methode_validation_pdfa", "regles_validees", "regles_echouees", "erreurs_pdfa", "avertissements_pdfa", "xmp_present", "xmp_conforme_facturx", "profil_xmp", "version_xmp", "erreurs_xmp", "metadonnees_xmp", "est_signe", "nombre_signatures", "signatures", "erreurs_signatures", "message_resume"]

    model_config = ConfigDict(
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
    )


    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.model_dump(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of ResultatValidationPDFAPI from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        """
        excluded_fields: Set[str] = set([
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        # override the default output from pydantic by calling `to_dict()` of each item in signatures (list)
        _items = []
        if self.signatures:
            for _item_signatures in self.signatures:
                if _item_signatures:
                    _items.append(_item_signatures.to_dict())
            _dict['signatures'] = _items
        # set to None if profil_detecte (nullable) is None
        # and model_fields_set contains the field
        if self.profil_detecte is None and "profil_detecte" in self.model_fields_set:
            _dict['profil_detecte'] = None

        # set to None if version_pdfa (nullable) is None
        # and model_fields_set contains the field
        if self.version_pdfa is None and "version_pdfa" in self.model_fields_set:
            _dict['version_pdfa'] = None

        # set to None if regles_validees (nullable) is None
        # and model_fields_set contains the field
        if self.regles_validees is None and "regles_validees" in self.model_fields_set:
            _dict['regles_validees'] = None

        # set to None if regles_echouees (nullable) is None
        # and model_fields_set contains the field
        if self.regles_echouees is None and "regles_echouees" in self.model_fields_set:
            _dict['regles_echouees'] = None

        # set to None if profil_xmp (nullable) is None
        # and model_fields_set contains the field
        if self.profil_xmp is None and "profil_xmp" in self.model_fields_set:
            _dict['profil_xmp'] = None

        # set to None if version_xmp (nullable) is None
        # and model_fields_set contains the field
        if self.version_xmp is None and "version_xmp" in self.model_fields_set:
            _dict['version_xmp'] = None

        return _dict

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of ResultatValidationPDFAPI from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return cls.model_validate(obj)

        _obj = cls.model_validate({
            "est_conforme": obj.get("est_conforme"),
            "xml_present": obj.get("xml_present"),
            "xml_conforme": obj.get("xml_conforme"),
            "profil_detecte": obj.get("profil_detecte"),
            "erreurs_xml": obj.get("erreurs_xml"),
            "pdfa_conforme": obj.get("pdfa_conforme"),
            "version_pdfa": obj.get("version_pdfa"),
            "methode_validation_pdfa": obj.get("methode_validation_pdfa") if obj.get("methode_validation_pdfa") is not None else 'metadata',
            "regles_validees": obj.get("regles_validees"),
            "regles_echouees": obj.get("regles_echouees"),
            "erreurs_pdfa": obj.get("erreurs_pdfa"),
            "avertissements_pdfa": obj.get("avertissements_pdfa"),
            "xmp_present": obj.get("xmp_present"),
            "xmp_conforme_facturx": obj.get("xmp_conforme_facturx"),
            "profil_xmp": obj.get("profil_xmp"),
            "version_xmp": obj.get("version_xmp"),
            "erreurs_xmp": obj.get("erreurs_xmp"),
            "metadonnees_xmp": obj.get("metadonnees_xmp"),
            "est_signe": obj.get("est_signe"),
            "nombre_signatures": obj.get("nombre_signatures") if obj.get("nombre_signatures") is not None else 0,
            "signatures": [InformationSignatureAPI.from_dict(_item) for _item in obj["signatures"]] if obj.get("signatures") is not None else None,
            "erreurs_signatures": obj.get("erreurs_signatures"),
            "message_resume": obj.get("message_resume")
        })
        return _obj


