from __future__ import annotations

import logging
from datetime import datetime
from typing import Optional, List, Union
from uuid import UUID

from pydantic import BaseModel, Field, EmailStr
from sysnet_pyutils.data_utils import get_dict_value, get_dict_value_float, get_dict_value_datetime, get_dict_value_bool
from sysnet_pyutils.models.general import PersonBaseType, WorkflowType, UserType, MetadataType, BaseEnum
from sysnet_pyutils.utils import is_valid_uuid, is_valid_pid, is_valid_unid, parse_ldap_name

from cites_model.cites_swin import SingleWindowType

LOGGER = logging.getLogger(__name__)

class PermitTypeEnum(BaseEnum):
    IMPORT = 'IMPORT'
    EXPORT = 'EXPORT'
    RE_EXPORT = 'RE-EXPORT'
    OTHER = 'OTHER'
    EMPTY = ''
    NULL = None


class PersonTypeEnum(BaseEnum):
    LEGAL_ENTITY = 'legalEntity'
    LEGAL_ENTITY_WO_ICO = 'legalEntityWithoutIco'
    FOREIGN_LEGAL_ENTITY = 'foreignLegalEntity'
    NATURAL_PERSON = 'naturalPerson'
    BUSINESS_NATURAL_PERSON = 'businessNaturalPerson'
    FOREIGN_NATURAL_PERSON = 'foreignNaturalPerson'
    EMPTY = ''
    NULL = None


class CertifiedEnum(BaseEnum):
    CERTIFIED_1 = '1'
    CERTIFIED_2 = '2'
    CERTIFIED_3 = '3'
    CERTIFIED_4 = '4'
    CERTIFIED_5 = '5'
    CERTIFIED_6 = '6'
    CERTIFIED_7 = '7'
    CERTIFIED_8 = '8'
    CERTIFIED_EMPTY = ''


class ValidityEnum(BaseEnum):
    VAL_1 = '1'
    VAL_2 = '2'
    VAL_3 = '3'
    VAL_4 = '4'
    VAL_EMPTY = ''


class IssuingPurposeEnum(BaseEnum):
    PURPOSE_1 = '1'
    PURPOSE_2 = '2'
    PURPOSE_3 = '3'
    PURPOSE_4 = '4'
    PURPOSE_5 = '5'
    PURPOSE_EMPTY = ''


class MetricEnum(BaseEnum):
    WEIGHT = 'weight'
    NUMBER = 'number'
    VOLUME = 'volume'
    OTHER = 'other'


class BirthTypeEnum(BaseEnum):
    DATE = 'DATE'
    INTERVAL = 'INTERVAL'
    MONTH = 'MONTH'
    OTHER = 'OTHER'


class DeliveryEnum(BaseEnum):
    OSOBNE = 'O'
    POSTOU = 'P'


class BaseEntryListType(BaseModel):
    start: Optional[int] = Field(default=0, description='Počáteční dokument na stránce', examples=[0])
    page_size: Optional[int] = Field(default=10, description='Velikost stránky', examples=[10])
    page: Optional[int] = Field(default=0, description='Požadovaná stránka', examples=[0])
    count: Optional[int] = Field(default=0, description='celkový počet vrácených položek', examples=[25])
    hits: Optional[int] = Field(default=0, description='celkový počet položek', examples=[25])


class PhoneNumberType(BaseModel):
    name: Optional[str] = Field(
        default=None,
        description="Název telefonního čísla (mobil, práce, domů)",
        examples=['mobil'],
    )
    prefix: Optional[str] = Field(default=None, description='Národní prefix', examples=[420])
    number: Optional[str] = Field(default=None, description='Vlastní telefonní číslo', examples=['123456789'])


class MailAddressType(BaseModel):
    name: Optional[str] = Field(default=None, description='Název adresa elektronické pošty (práce, domů)',examples=['domů'])
    email: Optional[EmailStr] = Field(default=None, description='Adresa elektronické pošty', examples=['josef.svejk@example.com'])


class PersonExtendedType(PersonBaseType):
    identifier: Optional[str] = Field(default=None, description='Hlavní identifikátor osoby')
    person_type: Optional[PersonTypeEnum] = Field(
        default=None,
        description='Typ osoby (zdroj CRŽP): \n- legalEntity: tuzemská právnická osoba\n- legalEntityWithoutIco: tuzemská právnická osoba bez IČO\n- foreignLegalEntity: zahraniční právnická osoba\n- businessNaturalPerson: tuzemská fyzická osoba podnikající\n- naturalPerson: tuzemská fyzická osoba nepodnikající\n- foreignNaturalPerson: zahraniční fyzická osoba podnikající\n',
        examples=['legalEntity'],
    )
    person_printable: Optional[str] = Field(default=None, description='Název osoby pro tisk', examples=['B.A.R. Reptofilia'])
    birthdate: Optional[datetime] = Field(default=None, examples=['2021-08-30T23:01:14.274085491+15:55'])
    credential: Optional[str] = Field(default=None, description='Číslo průkazu totožnosti')
    credential_type: Optional[str] = Field(default=None, description='Typ průkazu totožnosti')
    phone: Optional[List[Optional[PhoneNumberType]]] = Field(default=None, description='Telefonní číslo')
    email: Optional[List[Optional[MailAddressType]]] = Field(default=None, description='Elektronická pošta')
    special_flags: Optional[List[Optional[str]]] = Field(
        default=None,
        description='Speciální textové značení',
        examples=['importer_special=0', 'importer_transit=0'],
    )

    def parse_identifier(self):
        if self.identifier in [None, '']:
            return
        if is_valid_uuid(str(self.identifier)):
            self.uuid = str(UUID(str(self.identifier)))
        elif is_valid_pid(str(self.identifier)):
            self.pid = str(str(self.identifier))
        elif is_valid_unid(str(self.identifier)):
            self.unid = str(str(self.identifier))


class PersonHistoryItemType(PersonBaseType):
    date_from: Optional[datetime] = Field(default=None, description='Počáteční datum vlastnictví', examples=['2021-08-30T23:01:14.274085491+15:55'])
    date_to: Optional[datetime] = Field(default=None, description='Konečné datum vlastnictví', examples=['2021-08-30T23:01:14.274085491+15:55'])


class GeneralType(BaseModel):
    id_no: Optional[str] = Field(default=None, description='Číslo dokumentu', examples=['23CZ123456'])
    id_no_local: Optional[str] = Field(default=None, description='Lokální číslo dokumentu', examples=['23CZ123456'])
    id_no_list: Optional[List[Optional[str]]] = Field(default=None, description='Seznam všech čísel dokumentu', examples=['23CZ123456'])
    authorized: Optional[bool] = Field(default=False, description='Indikuje, zda je dokument autorizován a připraven pro publikaci')
    permit_type: Optional[PermitTypeEnum] = Field(default=None, description='typ permitu')
    permit_type_other: Optional[str] = Field(default=None, description='popis typu permitu, když OTHER')
    location: Optional[str] = Field(default=None, description='Povolené místo určení živých exemplářů druhů z přílohy A odebraných z volné přílohy\n')
    applicant: Optional[PersonExtendedType] = Field(default=None, description='Žadatel')
    applicant_agent: Optional[PersonExtendedType] = Field(default=None, description='Zástupce žadatele')
    exporter: Optional[PersonExtendedType] = Field(default=None, description='Vývozce')
    importer: Optional[PersonExtendedType] = Field(default=None, description='Dovozce')
    holder: Optional[PersonExtendedType] = Field(default=None, description='Držitel')
    holder_history: Optional[List[Optional[PersonHistoryItemType]]] = Field(default=None, description='Historie vlastníků nebo držitelů')
    country_export: Optional[str] = Field(default=None, description='Země (zpětného) vývozu', examples=['CZ'])
    country_import: Optional[str] = Field(default=None, description='Země dovozu', examples=['US'])
    stamp_no: Optional[str] = Field(default=None, description='Bezpečnostní známka č.')
    date_acquired: Optional[datetime] = Field(default=None, description='Datum získání', examples=['2021-08-30T23:01:14.274085491+15:55'])
    date_delivered: Optional[datetime] = Field(default=None, description='Datum přijetí', examples=['2021-08-30T23:01:14.274085491+15:55'])
    date_valid: Optional[datetime] = Field(default=None, description='Poslední den platnosti', examples=['2021-08-30T23:01:14.274085491+15:55'])
    exhibition_no: Optional[str] = Field(default=None, description='Evidenční číslo výstavy')
    status: Optional[str] = Field(default=None, description='Aktuální stav dokumentu', examples=['AUTHORIZED'])
    used: Optional[str] = Field(default=None, description='Aktuální stav použití dokumentu', examples=['I'])


class TransactionType(BaseModel):
    name: Optional[str] = Field(
        default=None,
        description='Název transakce (IMPORT, EXPORT, RE-EXPORT, OTHER, ...)',
        examples=['IMPORT'],
    )
    permit: Optional[str] = Field(default=None, description='Číslo dokumentu', examples=['23US123456'])
    date_issued: Optional[datetime] = Field(default=None, description='datum vydání dokumentu', examples=['2021-08-30T23:01:14.274085491+15:55'])
    date_realized: Optional[datetime] = Field(default=None, description='datum provedení transakce', examples=['2021-08-30T23:01:14.274085491+15:55'])
    date_canceled: Optional[datetime] = Field(default=None, description='datum zrušení transakce', examples=['2021-08-30T23:01:14.274085491+15:55'])
    country: Optional[str] = Field(default=None, description='Země transakce', examples=['US'])


class ConditionsType(BaseModel):
    certified: Optional[List[Optional[CertifiedEnum]]] = Field(
        default=None,
        description='Tímto se potvrzuje, že uvedené exempláře (podmínka 1 až 8)',
        examples=['2', '5', '7'])
    validity: Optional[List[Optional[ValidityEnum]]] = Field(
        default=None,
        description='Zvláštní podmínky platnosti dokladu',
        examples=['1', '3'])
    valid_for_holder: Optional[bool] = Field(default=None, description='Platí pouze pro držitele', examples=[True])
    conditions: Optional[str] = Field(
        default=None,
        description='Zvláštní podmínky (permit)',
        examples=['Návrat z dočasného vývozu./ Return from temporary stay abroad.'],
    )
    issuing_purpose: Optional[List[Optional[IssuingPurposeEnum]]] = Field(
        default=None,
        description='Tento doklad je vydáván za účelem',
        examples=['1', '3', '4'])


class IssuingType(BaseModel):
    issuing_authority_identifier: Optional[str] = Field(default=None, description='Identifikátorr vydávající autorita', examples=['env'])
    issuing_authority: Optional[str] = Field(default=None, description='Vydávající autorita', examples=['MŽP'])
    issuing_signature: Optional[str] = Field(default=None, description='Oprávněná úřední osoba', examples=['Mgr. Jiří Novák, MBA'])
    issuing_official: Optional[str] = Field(default=None, description='Jméno vydávajícího úředníka', examples=['Mgr. Jiří Novák, MBA'])
    issuing_place: Optional[str] = Field(default=None, description='Místo vydání', examples=['Praha'])
    date_issued: Optional[datetime] = Field(default=None, description='Datum vydání (IssuingDate)', examples=['2021-08-30T23:01:14.274085491+15:55'])
    issuer: Optional[PersonBaseType] = Field(default=None, description='Vydavatel')


class OtherType(BaseModel):
    certificate_type: Optional[str] = Field(
        default=None,
        description='Typ potvrzení podle číselníku:\n  * LEG - Potvrzení o zákonném získání\n  * COM - Potvrzení pro obchodní činnosti\n  * MOV - Potvrzení pro přemístění živých exemplářů\n',
    )
    certificate_form_version: Optional[str] = Field(default=None, description='Verze formuláře potvrzení (aktuálně 2)')
    customs: Optional[str] = Field(default=None, description='Celní údaje')
    documentation: Optional[str] = Field(default=None, description=' Doklady k (zpětnému) vývozu ze země (zpětného) vývozu')
    documents_to_authority: Optional[bool] = Field(default=None, description='Doklady byly předány vydávajícímu orgánu')
    documents_to_customs: Optional[bool] = Field(default=None, description='Doklady byly předány celnímu orgánu')
    consignment_note: Optional[str] = Field(default=None, description='Nákladní/pořepravní list')
    subject_permitted: Optional[str] = Field(default=None, description='Předmět povolení')


class PermitSpecialConditionsType(BaseModel):
    annex_pages: Optional[int] = Field(default=None, description='Počet stran příloh', examples=[6])
    permit_canceled: Optional[str] = Field(default=None, description='Vydáno namísto zrušeného povolení (permit)', examples=['23CZ000022'])
    max_length: Optional[str] = Field(default=None, description='Maximální délka exempláře v cm', examples=['32'])
    photo_pages: Optional[int] = Field(default=None, description='Počet stran fotografií exemplářů', examples=[0])
    plastron: Optional[str] = Field(default=None, description='Délka plastronu v cm', examples=['4.6'])
    karapax: Optional[str] = Field(default=None, description='Délka karapaxu v cm', examples=['3.4'])
    other: Optional[List[Optional[str]]] = Field(default=None, description='Další podmínky', examples=['Podmínka 1', 'Podmínka 2'])
    text: Optional[List[Optional[str]]] = Field(default=None, description='Položky s volným textem podmínek')
    transaction: Optional[List[Optional[str]]] = Field(
        default=None,
        description='Souhrn transakčních podmínek',
        examples=[
            'bezpečnostní známka č./ security stamp No. 2098148',
            'příloha/ annex: =6= stran/ pages'])


class DocumentPrincipalCustomsPermitType(BaseModel):
    certificate: Optional[str] = Field(default=None, description='Číslo celního dokladu', examples=['23CZ6100002BJNUMP0'])
    comment: Optional[str] = Field(default=None, description='Poznámka k celním údajům')
    date_customs: Optional[datetime] = Field(
        default=None,
        description='Datum použití permitu',
        examples=['2021-08-30T23:01:14.274085491+15:55'],
    )
    date_returned: Optional[datetime] = Field(
        default=None,
        description='Datum vrácení nepoužitého permitu',
        examples=['2021-08-30T23:01:14.274085491+15:55'],
    )
    type_customs: Optional[str] = Field(default=None, description='Typ celního dokladu', examples=['SWIN'])


class TaxonItemType(BaseModel):
    pid: Optional[str] = Field(default=None, description='PID taxonu', examples=['MBOA7HNBDJTR'])
    uuid: Optional[str] = Field(default=None, description='identifikátor položky zboží', examples=['9d6e2fc9-ca1f-4504-a54b-c8263a21c678'])
    id_species_plus: Optional[List[Optional[str]]] = Field(default=None, description='Identifikátor species+')
    name_scientific: Optional[str] = Field(default=None, description='Vědecký název', examples=['Atelopus zeteki'])
    name_common_cz: Optional[str] = Field(default=None, description='Obecný název (česky))', examples=['atelopus panamský'])
    name_common_en: Optional[str] = Field(default=None, description='Obecný název (anglicky)', examples=['Golden Arrow Poison Frog'])
    regulation_cites: Optional[str] = Field(default=None, description='Příloha CITES', examples=['I'])
    regulation_eu: Optional[str] = Field(default=None, description='Příloha EU', examples=['A'])
    regulation_411: Optional[bool] = Field(default=None, description='Zvláštní ochrana', examples=[False])
    error: Optional[bool] = Field(default=False, description='Taxon error')


class GoodsQuantityType(BaseModel):
    metric: Optional[MetricEnum] = Field(default=MetricEnum.NUMBER, description='Metrika (hmotnost, počet, objem, jiná)')
    amount: Optional[float] = Field(default=float(1), description='Množství')
    units: Optional[str] = Field(default=None, description='Jednotky', examples=['PCS'])


class GoodsIdetificationType(BaseModel):
    identification: Optional[str] = Field(
        default=None,
        description='Identifikace exemplářů (čip, kroužek, fotografie, jiné)',
        examples=['C'])
    identifier: Optional[str] = Field(default=None, description='číslo identifikačníchh prostředků', examples=['941000025010989'])


class GoodsIdetificationHistoryItemType(GoodsIdetificationType):
    date_valid_from: Optional[datetime] = Field(default=None, examples=['2021-08-30T23:01:14.274085491+15:55'])
    date_valid_to: Optional[datetime] = Field(default=None, examples=['2021-08-30T23:01:14.274085491+15:55'])


class GoodsBirthType(BaseModel):
    birth_place: Optional[str] = Field(default=None, description='místo narození', examples=['LIV'])
    birth_type: Optional[BirthTypeEnum] = Field(default=None, description='Typ určení data narození')
    birth_value: Optional[str] = Field(default=None, description='Hodnota data narození, není-li DATE')
    birth_date: Optional[datetime] = Field(default=None, description='Datum narození', examples=['2021-08-30T23:01:14.274085491+15:55'])


class GoodsItemBaseType(BaseModel):
    species: Optional[TaxonItemType] = Field(default=None, description='Název zboží')
    amount: Optional[float] = Field(default=float(1), description='Množství')
    quantity: Optional[List[Optional[GoodsQuantityType]]] = Field(default=None, description='Strukturované množství')
    identification: Optional[List[Optional[GoodsIdetificationType]]] = Field(default=None, description='Identifikace exemplářů')
    identification_history: Optional[List[Optional[GoodsIdetificationHistoryItemType]]] = Field(default=None, description='Historie identifikací')
    birth: Optional[GoodsBirthType] = Field(default=None, description='Údaje o narození exempláře')
    code: Optional[str] = Field(default=None, description='Kód exempláře', examples=['LIV'])
    gender: Optional[str] = Field(default=None, description='Pohlaví exempláře', examples=['JUV'])
    origin: Optional[str] = Field(default=None, description='Původ', examples=['T'])
    purpose: Optional[str] = Field(default=None, description='Účel', examples=['T'])
    transaction_origin: Optional[TransactionType] = Field(default=None, description='Transakce původ')
    transaction_import: Optional[TransactionType] = Field(default=None, description='Transakce dovoz')
    transaction_re_export: Optional[TransactionType] = Field(default=None, description='Transakce re-export')
    goods_description: Optional[str] = Field(default=None, description='Popis exempláře - pole Notes: description')


class GoodsOrderType(BaseModel):
    text_value: Optional[str] = Field(default=None, description='pořadí zboží v permitu', examples=['A'])
    num_value: Optional[int] = Field(default=None, description='pořadové číslo zboží v permitu', examples=[1])


class DocumentPrincipalCustomsGoodsType(BaseModel):
    certificate: Optional[str] = Field(default=None, description='Číslo celního dokladu', examples=['23CZ6100002BJNUMP0'])
    comment: Optional[str] = Field(default=None, description='Poznámka k celním údajům')
    date_customs: Optional[datetime] = Field(default=None, description='Datum použití permitu', examples=['2021-08-30T23:01:14.274085491+15:55'])
    dead: Optional[float] = Field(default=None, description='Počet uhynulých exemplářů')
    id_customs: Optional[str] = Field(default=None, description='Celní identifikátor')
    quantity: Optional[float] = Field(default=None, description='Proclené množství')
    type_customs: Optional[str] = Field(default=None, description='Typ celního dokladu', examples=['SWIN'])


class RelatedType(BaseModel):
    title: Optional[str] = Field(default=None, description='Název souvisejícího dokumentu')
    unid: Optional[str] = Field(default=None, description='Domino universal ID', examples=['3005277CB984B7FFC12587890060E2BF'])
    pid: Optional[str] = Field(default=None, description='Unique identifier', examples=['MBOA7HNBDJTR'])
    uuid: Optional[str] = Field(default=None, description='Unique identifier')
    id_no: Optional[str] = Field(default=None, description='Číslo dokumentu', examples=['23CZ123456'])
    form: Optional[str] = Field(default=None, description='Formulář', examples=['certificate'])


class GoodsPrincipalType(GoodsItemBaseType):
    identifier: Optional[str] = Field(default=None, description='identifikátor položky zboží', examples=['24CZ123456*1'])
    unid: Optional[str] = Field(default=None, description='Notes UNID - pro zpětnou kompatibilitu', examples=['C125868C0046C8EAC1258778007FB80D'])
    pid: Optional[str] = Field(default=None, description='Dvanaáctimístný identifikátor - pro zpětnou kompatibilitu', examples=['CIT123456789'])
    order: Optional[GoodsOrderType] = Field(default=None, description='Pořadí zboží v permitu')
    goods_customs: Optional[DocumentPrincipalCustomsGoodsType] = Field(default=None, description='Celní údaje zboží')
    goods_additional: Optional[str] = Field(default=None, description='Další popis exempláře - pole Notes goods_additional')
    goods_description_base: Optional[str] = Field(default=None, description='Základní popis exempláře - pole Notes: goods_description')
    net_mass: Optional[float] = Field(default=None, description='Čistá hmotnost exempláře/ů', examples=[8.54])
    units: Optional[str] = Field(default=None, description='Jednotky', examples=['PCS'])
    amount_printable: Optional[str] = Field(default=None, description='Tištitelná podoba množství', examples=['=== 12 ks/pcs ==='])
    goods_cloning: Optional[str] = Field(default=None, description='Klonování exempláře')
    requested_document: Optional[str] = Field(default=None, description='Požadovaný dokument')
    requested_statement: Optional[str] = Field(default=None, description='Požadované stanovisko')
    authority_decision_id: Optional[str] = Field(default=None, description='Rozhodnutí úřadu')
    statement_type: Optional[str] = Field(default=None, description='Typ stanoviska vědeckého orgánu AOPK/Generální [A/G] (env_resolution)', examples=['G'])
    statement_issued: Optional[bool] =  Field(default=None, description='Stanovisko vydáno (is_statement)')
    single_window: Optional[SingleWindowType] = Field(default=None, description='Údaje získané ze SWIN')
    used: Optional[str] = Field(default=None, description='Aktuální stav použití položky dokumentu', examples=['I'])
    comment: Optional[str] = Field(default=None, description='Komentář ke zboží')
    related: Optional[List[Optional[RelatedType]]] = Field(default=None, description='Související dokumenty')

    def load_dds(self, goods_item):
        log = logging.getLogger(__name__)
        log.info(f"{__name__}.load_dds: {type(goods_item)}")

        try:
            quantity = get_dict_value_float(goods_item, 'quantity')
            q_units = get_dict_value(goods_item, 'quantity_unit')
            net_mass: Union[float, None] = get_dict_value_float(goods_item, 'net_mass')
            nm_units = get_dict_value(goods_item, 'mass')
            amount = quantity
            units = q_units
            if net_mass > float(0):
                amount = net_mass
                units = nm_units
            swin_transaction = get_dict_value(goods_item, 'transaction')
            if swin_transaction not in [None, '']:
                lines = swin_transaction.split('\n')
                swin_transaction = [line for line in lines if line.strip()]
            swin_identifier = get_dict_value(goods_item, 'identifier_customs')
            swin_identifier_list = None
            if swin_identifier not in [None, '']:
                lines = swin_identifier.split('\n')
                swin_identifier_list = [line for line in lines if line.strip()]
            swin_change = []
            for i in range(200):
                item_name = f"swin_change_{i + 1}"
                v = get_dict_value(goods_item, item_name)
                if v is not None:
                    swin_change.append(v)
                else:
                    break
            if not bool(swin_change):
                swin_change = None
            self.species = TaxonItemType(
                pid=None,
                name_scientific=get_dict_value(goods_item, 'species'),
                name_common_cz=get_dict_value(goods_item, 'common'),
                name_common_en=get_dict_value(goods_item, 'common_en'),
                regulation_cites=get_dict_value(goods_item, 'appendix_cites'),
                regulation_eu=get_dict_value(goods_item, 'annex_ec'),
                regulation_411=False,
                error=get_dict_value_bool(goods_item, 'taxonError')
            )
            log.info(f"{__name__}.load_dds SPECIES")
            self.amount = amount
            self.quantity = [
                GoodsQuantityType(
                    metric=MetricEnum.NUMBER,
                    units=q_units,
                    amount=quantity
                ),
                GoodsQuantityType(
                    metric=MetricEnum.WEIGHT,
                    units=nm_units,
                    amount=net_mass
                )
            ]
            log.info(f"{__name__}.load_dds QUANTITY")
            self.identification = []
            self.identification_history = []
            self.birth = GoodsBirthType()
            self.code = get_dict_value(goods_item, 'goods_code')
            self.gender = None
            self.origin = get_dict_value(goods_item, 'origin')
            self.purpose = get_dict_value(goods_item, 'purpose')
            self.transaction_origin = TransactionType(
                name='ORIGIN',
                country=get_dict_value(goods_item, 'origin_country'),
                permit=get_dict_value(goods_item, 'origin_permit'),
                date_issued=get_dict_value_datetime(goods_item, 'origin_permit_issued'),
                date_realized=None,
                date_canceled=None)
            log.info(f"{__name__}.load_dds TRANSACTION_ORIGIN")

            self.transaction_import = TransactionType()
            self.transaction_re_export = TransactionType(
                name='LAST_RE_EXPORT',
                country=get_dict_value(goods_item, 'last_reexport_country'),
                permit=get_dict_value(goods_item, 'last_reexport_permit'),
                date_issued=get_dict_value_datetime(goods_item, 'last_reexport_permit_issued'),
                date_realized=None,
                date_canceled=None)
            log.info(f"{__name__}.load_dds TRANSACTION_RE_EXPORT")
            self.goods_description = get_dict_value(goods_item, 'description')
            self.goods_additional = get_dict_value(goods_item, 'goods_additional')
            self.goods_description_base = get_dict_value(goods_item, 'goods_description')
            self.identifier = f"{get_dict_value(goods_item, 'PID')}*{get_dict_value(goods_item, 'order')}"
            self.unid = get_dict_value(goods_item, '@unid')
            self.pid = get_dict_value(goods_item, 'PID')
            self.order = GoodsOrderType(
                text_value=get_dict_value(goods_item, 'orderString'),
                num_value=get_dict_value(goods_item, 'order'))
            log.info(f"{__name__}.load_dds ORDER")

            self.goods_customs = DocumentPrincipalCustomsGoodsType(
                certificate=get_dict_value(goods_item, 'certificate_customs'),
                comment=None,
                date_customs=get_dict_value_datetime(goods_item, 'date_customs'),
                dead=get_dict_value_float(goods_item, 'dead_customs'),
                id_customs=swin_identifier,
                quantity=get_dict_value_float(goods_item, 'quantity_customs'),
                type_customs=get_dict_value(goods_item, 'type_customs'),
            )
            log.info(f"{__name__}.load_dds GOODS_CUSTOMS")
            self.net_mass = net_mass
            self.units = get_dict_value(goods_item, 'mass')
            self.amount_printable = f"={amount}= {units}"
            self.goods_cloning = None
            self.requested_document = None
            self.requested_statement = None
            self.authority_decision_id = None
            self.statement_type = get_dict_value(goods_item, 'env_resolution')
            self.single_window = SingleWindowType(
                version=get_dict_value(goods_item, 'swin'),
                transaction_list=swin_transaction,
                identifier_list=swin_identifier_list,
                change_json_list=swin_change,
                note=None
            )
            self.used = get_dict_value(goods_item, 'used')
            self.comment = get_dict_value(goods_item, 'comment')
            self.related = []
            log.info(f"{__name__}.load_dds DONE")
            return self
        except Exception as e:
            LOGGER.error(f"{__name__}.GoodsPrincipalType.load_dds: {str(e)}")
            return None

    @property
    def field_common(self) -> Optional[str]:
        common = ''
        common_cz = self.species.name_common_cz
        common_en = self.species.name_common_en
        if common_cz not in [None, ''] and common_en not in [None, '']:
            common = '{}/{}'.format(common_cz, common_en)
        elif common_cz in [None, ''] and common_en not in [None, '']:
            common = common_en
        elif common_cz not in [None, ''] and common_en in [None, '']:
            common = common_cz
        return common

    @property
    def field_description(self) -> Optional[str]:
        dl = []
        if self.code not in [None, '']:
            dl.append(self.code)
        if self.goods_description not in [None, '']:
            dl.append(self.goods_description)
        if self.goods_additional not in [None, '']:
            dl.append(self.goods_additional)
        out = '\n'.join(dl)
        return out


class WorkflowCitesType(WorkflowType):

    def load_data(self, node_code, node_name, responsible, date_execution, executor, status_from, status_to):
        self.node_code = node_code
        self.node_name = node_name
        self.responsible = responsible
        self.date_execution = date_execution
        self.executor = executor
        self.status_from = status_from
        self.status_to = status_to



class WorkflowListType(BaseEntryListType):
    status: Optional[str] = Field(default=None, description='Aktuální status dokumentu')
    entries: Optional[List[Optional[WorkflowCitesType]]] = Field(default=None, description='seznam uzlů životního cyklu')

    def load_dds(self, data):
        self.entries = []
        rejected = get_dict_value_bool(data, 'rejected')
        id_no = get_dict_value(data, 'id_no')
        id_local = get_dict_value(data, 'ID_NO_Local')
        # authorized = get_dict_value_bool(data, 'Authorized')
        # statement = get_dict_value(data, 'statement')           # TODO statement
        # processing = get_dict_value(data, 'processing')
        s1_date_created = get_dict_value_datetime(data, '@created')
        # s1_creator = None
        s2_date_authorized = get_dict_value_datetime(data, 'Date_Authorized')
        s2_authorized_by = get_dict_value(data, 'AuthorizedBy')
        s3_date_delivered = get_dict_value_datetime(data, 'Date_Delivered')
        s3_delivered_by = get_dict_value(data, 'User_Delivered')
        s4_date_processing = get_dict_value_datetime(data, 'Date_Processing')
        s4_processing_by = get_dict_value(data, 'User_Processing')
        s5_date_statement_request = get_dict_value_datetime(data, 'Date_StatementType')
        s5_statement_request_by = get_dict_value(data, 'StatementRequestBy')
        s6_date_processed = get_dict_value_datetime(data, 'Date_Processed')
        s6_processed_by = get_dict_value(data, 'User_Processed')
        s7_date_approved = get_dict_value_datetime(data, 'date_approved')
        s7_approved_by = get_dict_value(data, 'ApprovedBy')
        s8_date_in_process = get_dict_value_datetime(data, 'Date_inProcess')
        s8_date_in_process_opr = get_dict_value_datetime(data, 'Date_inProcess_opr')
        if isinstance(s8_date_in_process_opr, datetime):
            s8_date_in_process = s8_date_in_process_opr
        s8_in_process_by = get_dict_value(data, 'inProcessBy')
        s9_date_statement_issued = get_dict_value_datetime(data, 'Date_statementsIssued')
        s9_statement_issued_by = get_dict_value(data, 'statementsIssuedBy')
        s99_date_rejected = get_dict_value_datetime(data, 'Date_Rejected')
        s99_rejected_by = get_dict_value(data, 'User_Processed')
        status = None
        if s1_date_created is not None:
            w1 = WorkflowCitesType()
            w1.load_data(
                '1-created', 'vytvořeno', None, s1_date_created, None,
                None, '2-authorized')
            # w1.date_execution=s1_date_created.strftime('%Y-%m-%dT%H:%M:%SZ')
            status = w1.node_code
            self.entries.append(w1)
        if s2_date_authorized is not None:
            cn, ldap_name = parse_ldap_name(s2_authorized_by)
            w2 = WorkflowCitesType()
            w2.node_code = '2-authorized'
            w2.node_name = 'autorizováno'
            w2.responsible = None
            # w2.date_execution=s2_date_authorized.strftime('%Y-%m-%dT%H:%M:%SZ')
            w2.date_execution = s2_date_authorized
            w2.executor = UserType(dn=ldap_name, name=cn)
            w2.status_from = '1-created'
            w2.status_to = '3-delivered'
            status = w2.node_code
            self.entries.append(w2)
        if s3_date_delivered is not None:
            cn, ldap_name = parse_ldap_name(s3_delivered_by)
            w3 = WorkflowCitesType()
            w3.node_code = '3-delivered'
            w3.node_name = f'doručeno podatelnou pod čj. CE {id_no}, čj. {id_local}'
            w3.responsible = None
            # date_execution=s3_date_delivered.strftime('%Y-%m-%dT%H:%M:%SZ')
            w3.date_execution = s3_date_delivered
            w3.executor = UserType(dn=ldap_name, name=cn)
            w3.status_from = '2-authorized'
            w3.status_to = '4-processing'
            status = w3.node_code
            self.entries.append(w3)
        if s4_date_processing is not None:
            cn, ldap_name = parse_ldap_name(s4_processing_by)
            w4 = WorkflowCitesType()
            w4.node_code = '4-processing'
            w4.node_name = 'vyřizuje se'
            w4.responsible = None
            # date_execution=s4_date_processing.strftime('%Y-%m-%dT%H:%M:%SZ')
            w4.date_execution = s4_date_processing
            w4.executor = UserType(dn=ldap_name, name=cn)
            w4.status_from = '3-delivered'
            w4.status_to = '5-statement'
            status = w4.node_code
            self.entries.append(w4)
        if s5_date_statement_request is not None:
            cn, ldap_name = parse_ldap_name(s5_statement_request_by)
            w5 = WorkflowCitesType()
            w5.node_code = '5-statement'
            w5.node_name = 'vyřizuje se (požadavek na stanovisko)'
            w5.responsible = None
            # w5.date_execution=s5_date_statement_request.strftime('%Y-%m-%dT%H:%M:%SZ')
            w5.date_execution = s5_date_statement_request
            w5.executor = UserType(dn=ldap_name, name=cn)
            w5.status_from = '4-processing'
            w5.status_to = '6-processed'
            status = w5.node_code
            self.entries.append(w5)
        if s6_date_processed is not None:
            cn, ldap_name = parse_ldap_name(s6_processed_by)
            w6 = WorkflowCitesType()
            w6.node_code = '6-processed'
            w6.node_name = 'vyřízeno'
            w6.responsible = None
            w6.date_execution = s6_date_processed
            w6.executor = UserType(dn=ldap_name, name=cn)
            w6.status_from = '5-statement'
            w6.status_to = None
            status = w6.node_code
            self.entries.append(w6)
        if s7_date_approved is not None:
            cn, ldap_name = parse_ldap_name(s7_approved_by)
            w7 = WorkflowCitesType()
            w7.node_code = '7-approved'
            w7.node_name = 'schváleno'
            w7.responsible = None
            w7.date_execution = s7_date_approved
            w7.executor = UserType(dn=ldap_name, name=cn)
            w7.status_from = '2-authorized'
            w7.status_to = None
            status = w7.node_code
            self.entries.append(w7)
        if s8_date_in_process is not None:
            cn, ldap_name = parse_ldap_name(s8_in_process_by)
            w8 = WorkflowCitesType()
            w8.node_code = '3-in_process'
            w8.node_name = 'zpracovává se'
            w8.responsible = None
            w8.date_execution = s8_date_in_process
            w8.executor = UserType(dn=ldap_name, name=cn)
            w8.status_from = '2-authorized'
            w8.status_to = None
            status = w8.node_code
            self.entries.append(w8)
        if s9_date_statement_issued is not None:
            cn, ldap_name = parse_ldap_name(s9_statement_issued_by)
            w9 = WorkflowCitesType()
            w9.node_code = '4-statement_issued'
            w9.node_name = 'vydáno stanovisko'
            w9.responsible = None
            w9.date_execution = s9_date_statement_issued
            w9.executor = UserType(dn=ldap_name, name=cn)
            w9.status_from = '3-in_process'
            w9.status_to = None
            status = w9.node_code
            self.entries.append(w9)
        if rejected:
            cn, ldap_name = parse_ldap_name(s99_rejected_by)
            w99 = WorkflowCitesType()
            w99.node_code = '99-rejected'
            w99.node_name = 'zamítnuto'
            w99.responsible = None
            w99.date_execution = s99_date_rejected
            w99.executor = UserType(dn=ldap_name, name=cn)
            w99.status_from = None
            w99.status_to = None
            status = w99.node_code
            self.entries.append(w99)
        if status is None:
            status = get_dict_value(data, 'status')
        self.count = len(self.entries)
        self.page = 0
        self.page_size = 100
        self.start = 0
        self.status = status
        return self


class TransportType(BaseModel):
    vehicle: Optional[str] = Field(default=None, description='dopravní porstředek')
    border: Optional[str] = Field(default=None, description='hraniční přechod')
    date_transit: Optional[datetime] = Field(default=None, description='datum přechodu hranice', examples=['2021-08-30T23:01:14.274085491+15:55'])


class EntryType(MetadataType):
    doc_code: Optional[str] = Field(
        default=None,
        description='Kód dokumentu - vazba na šablony',
        examples=['DD01'],
    )
    doc_class: Optional[str] = Field(
        default=None,
        description="Třída dokumentu: ['DocumentPrincipalType', 'DocumentRegistrationCardType'] \n",
        examples=['DocumentPrincipalType'],
    )
    date_issued: Optional[datetime] = Field(
        default=None,
        description='Datum vydání dokumentu',
        examples=['2021-08-30T23:01:14.274085491+15:55'],
    )

# verze 1.1.0 --------------------------------------------------------------------------

class AdditionalType(BaseModel):
    special_conditions: Optional[str] = Field(default=None, description='Nějaký HTML text pro AOPK')
    fertility: Optional[int] = Field(default=None, description='maximální možná plodnost jednoho exempláře')


class HybridType(BaseModel):
    name: Optional[str] = Field(default=None, description='Název křížence')
    source: Optional[List[str]] = Field(default=None, description='Seznam vědeckých názvů zdrojových druhů')
    comment: Optional[str] = Field(default=None, description='Popis křížence')


class Regulation449Enum(BaseEnum):
    A = 'A'
    B = 'B'
    EMPTY = ''


class RegulationCitesEnum(BaseEnum):
    I = 'I'
    I_II = 'I/II'
    II = 'II'
    II_III = 'II/III'
    III = 'III'
    NC = 'NC'
    Not_CITES_114_1992 = 'Not CITES. Protected by the Act 114/1992.'
    Not_CITES = 'Not CITES'
    EMPTY = ''


class RegulationEuEnum(BaseEnum):
    A = 'A'
    A_B = 'A/B'
    B = 'B'
    B_D = 'B/D'
    C = 'C'
    D = 'D'
    EMPTY = ''


class PublishedEnum(BaseEnum):
    NOT_PUBLISHED = '0'
    PUBLISHED = '1'
    ALL = 'all'
