from pydantic import constr
from pydantic_xml import BaseXmlModel, RootXmlModel, attr, element

NSMAP = {
    'a': 'http://www.w3.org/2005/08/addressing',
    'b': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
    's': 'http://www.w3.org/2003/05/soap-envelope',
    'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
    'xsd': 'http://www.w3.org/2001/XMLSchema',
    'd2p1': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
    'd3p1': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
}

SECURITY_NSMAP = NSMAP | {
    '': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
}
SIGNATURE_NSMAP = NSMAP | {'': 'http://www.w3.org/2000/09/xmldsig#'}
RESPONSE_NSMAP = NSMAP | {'': 'http://egisz.rosminzdrav.ru/iehr/emdr/service/'}


class Action(BaseXmlModel, tag='Action', ns='a', nsmap=NSMAP):
    id: str = attr(name='Id', ns='d3p1')


class MessageID(BaseXmlModel, tag='MessageID', ns='a', nsmap=NSMAP):
    id: str = attr(name='Id', ns='d3p1')
    description: constr(strip_whitespace=True)  # type: ignore


class BinarySecurityToken(
    BaseXmlModel, tag='BinarySecurityToken', nsmap=NSMAP
):
    id: str = attr(name='Id', ns='b')
    ValueType: str = attr(name='ValueType')
    EncodingType: str = attr(name='EncodingType')
    description: constr(strip_whitespace=True)  # type: ignore


class CanonicalizationMethod(
    BaseXmlModel, tag='CanonicalizationMethod', nsmap=SIGNATURE_NSMAP
):
    algorithm: str = attr(name='Algorithm')


class SignatureMethod(
    BaseXmlModel, tag='SignatureMethod', nsmap=SIGNATURE_NSMAP
):
    algorithm: str = attr(name='Algorithm')


class Transform(BaseXmlModel, tag='Transform', nsmap=SIGNATURE_NSMAP):
    algorithm: str = attr(name='Algorithm')


class Transforms(RootXmlModel, tag='Transforms', nsmap=SIGNATURE_NSMAP):  # type: ignore
    root: list[Transform] = element()


class DigestMethod(BaseXmlModel, tag='DigestMethod', nsmap=SIGNATURE_NSMAP):
    algorithm: str = attr(name='Algorithm')


class DigestValue(BaseXmlModel, tag='DigestValue', nsmap=SIGNATURE_NSMAP):
    value: str


class Reference(BaseXmlModel, tag='Reference', nsmap=SIGNATURE_NSMAP):
    uri: str = attr(name='URI')
    transforms: Transforms = element()
    digest_method: DigestMethod = element()
    digest_value: DigestValue = element()


class SignedInfo(BaseXmlModel, tag='SignedInfo', nsmap=SIGNATURE_NSMAP):
    canonicalization_method: CanonicalizationMethod = element()
    signature_method: SignatureMethod = element()
    references: list[Reference] = element()


class SignatureValue(
    BaseXmlModel, tag='SignatureValue', nsmap=SIGNATURE_NSMAP
):
    description: constr(strip_whitespace=True)  # type: ignore


class SecurityTokenReference(
    BaseXmlModel, tag='Reference', nsmap=SECURITY_NSMAP
):
    ValueType: str = attr(name='ValueType')
    URI: str = attr(name='URI')


class SecurityToken(
    BaseXmlModel, tag='SecurityTokenReference', ns='', nsmap=SECURITY_NSMAP
):
    reference: SecurityTokenReference = element()


class KeyInfo(BaseXmlModel, tag='KeyInfo', nsmap=SIGNATURE_NSMAP):
    security_token_reference: SecurityToken = element()


class Signature(BaseXmlModel, tag='Signature', ns='', nsmap=SIGNATURE_NSMAP):
    signed_info: SignedInfo = element()
    signature_value: SignatureValue = element()
    key_info: KeyInfo = element()


class Security(BaseXmlModel, tag='Security', ns='', nsmap=SECURITY_NSMAP):
    binary_security_token: BinarySecurityToken = element()
    signature: Signature = element()


class Header(BaseXmlModel, tag='Header', ns='s', nsmap=NSMAP):
    action: Action = element()
    message_id: MessageID = element()
    security: Security = element()


class searchRegistryItemResponseItem(
    BaseXmlModel, tag='item', nsmap=RESPONSE_NSMAP
):
    emdrId: str = element()
    localUid: str = element()
    registrationDate: str = element()
    registrationDateTime: str = element()
    storeTillDate: str = element()
    IsSemd: bool = element()


class searchRegistryItemResponseMatches(
    BaseXmlModel, tag='matches', nsmap=RESPONSE_NSMAP
):
    items: list[searchRegistryItemResponseItem] = element()


class searchRegistryItemResponse(
    BaseXmlModel, tag='searchRegistryItemResponse', ns='', nsmap=RESPONSE_NSMAP
):
    status: str = element()
    matches: searchRegistryItemResponseMatches


class Body(BaseXmlModel, tag='Body', ns='s', nsmap=NSMAP):
    id: str = attr(name='Id', ns='d2p1')
    response: searchRegistryItemResponse = element()


class Envelope(BaseXmlModel, tag='Envelope', ns='s', nsmap=NSMAP):
    header: Header = element()
    body: Body = element()


class Acknowledgment(
    BaseXmlModel, tag='acknowledgment', ns='', nsmap=RESPONSE_NSMAP
):
    status: str = element()


class DemandContentBody(BaseXmlModel, tag='Body', ns='s', nsmap=NSMAP):
    id: str = attr(name='Id', ns='d2p1')
    acknowledgment: Acknowledgment


class DemandContentEnvelope(BaseXmlModel, tag='Envelope', ns='s', nsmap=NSMAP):
    header: Header = element()
    body: DemandContentBody = element()
