use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};

use crate::{
    InvoiceKind, InvoiceLineItem, InvoiceType, SWIFTType, TDataT, TFormaPlatnosci, TIlosci,
    TKodFormularza, TKodKraju, TKodWaluty, TKodyKrajowUE, TKwotowy, TNIPIdWew, TNrRB, TNrVatUE,
    TNumerKSeF, TNumerTelefonu, TRachunekWlasnyBanku, TRodzajFaktury, TStatusInfoPodatnika,
    TTypKorekty, TZnakowy, TZnakowy20, TZnakowy50, VatRateInfo,
};

use super::adnotacje::Adnotacje;
use super::common::{DaneKontaktowe, TAdres};
use super::correction::CorrectionData;
use super::platnosc::Platnosc;
use super::podmiot3::Podmiot3Info;
use super::podmiot_upowazniony::PodmiotUpowaznionyInfo;
use super::rozliczenie::Rozliczenie;
use super::stopka::Stopka;
use super::warunki_transakcji::WarunkiTransakcji;
use super::zalacznik::Zalacznik;
use super::zaliczka::{DodatkowyOpis, FakturaZaliczkowaRef, ZaliczkaCzesciowa};
use super::zamowienie_data::ZamowienieData;

/// Faktura VAT (Faktura).
///
/// Główna struktura faktury VAT zgodna ze schematem FA(3) v1-0E.
/// Na podstawie art. 106a - 106q ustawy. Pola dotyczące wartości sprzedaży
/// i podatku wypełnia się w walucie, w której wystawiono fakturę,
/// z wyjątkiem pól dotyczących podatku przeliczonego zgodnie z przepisami
/// działu VI w związku z art. 106e ust. 11 ustawy.
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
#[serde(default)]
pub struct Invoice {
    // ====== Metadata (application-level, not XSD) ======
    /// Identyfikator faktury (aplikacyjny).
    pub id: String,
    /// Referencja KSeF (aplikacyjna).
    #[serde(rename = "ksefReference")]
    pub ksef_reference: String,
    /// Data utworzenia rekordu (aplikacyjna).
    #[serde(rename = "createdAt")]
    pub created_at: DateTime<Utc>,
    /// Data aktualizacji rekordu (aplikacyjna).
    #[serde(rename = "updatedAt")]
    pub updated_at: DateTime<Utc>,

    // ====== Naglowek (TNaglowek) ======
    /// Symbol wzoru formularza (KodFormularza).
    ///
    /// Wartość stała: "FA". TKodFormularza.
    #[serde(rename = "formCode", skip_serializing_if = "Option::is_none")]
    pub form_code: Option<TKodFormularza>,
    /// Kod systemowy formularza (kodSystemowy).
    ///
    /// Atrybut KodFormularza/@kodSystemowy. Wartość stała: "FA (3)".
    #[serde(rename = "formSystemCode", skip_serializing_if = "Option::is_none")]
    pub form_system_code: Option<TZnakowy>,
    /// Wersja schematu (wersjaSchemy).
    ///
    /// Atrybut KodFormularza/@wersjaSchemy. Wartość stała: "1-0E".
    #[serde(rename = "formSchemaVersion", skip_serializing_if = "Option::is_none")]
    pub form_schema_version: Option<TZnakowy>,
    /// Wariant formularza (WariantFormularza).
    ///
    /// Wartość stała: 3.
    #[serde(rename = "formVariant", skip_serializing_if = "Option::is_none")]
    pub form_variant: Option<u8>,
    /// Data i czas wytworzenia faktury (DataWytworzeniaFa).
    ///
    /// Data i czas wytworzenia faktury. Zakres: 2025-09-01T00:00:00Z do 2050-01-01T23:59:59Z.
    #[serde(rename = "creationDate", skip_serializing_if = "Option::is_none")]
    pub creation_date: Option<TDataT>,
    /// Nazwa systemu teleinformatycznego (SystemInfo).
    ///
    /// Nazwa systemu teleinformatycznego, z którego korzysta podatnik.
    /// minOccurs="0".
    #[serde(rename = "systemInfo", skip_serializing_if = "Option::is_none")]
    pub system_info: Option<TZnakowy>,

    // ====== Podmiot1 (issuer / seller) — flat ======
    /// Imię i nazwisko lub nazwa sprzedawcy (Podmiot1/DaneIdentyfikacyjne/Nazwa).
    ///
    /// Dane podatnika. Imię i nazwisko lub nazwa sprzedawcy towarów lub usług.
    #[serde(rename = "issuerName")]
    pub issuer_name: TZnakowy,
    /// Identyfikator podatkowy NIP sprzedawcy (Podmiot1/DaneIdentyfikacyjne/NIP).
    #[serde(rename = "issuerNip")]
    pub issuer_nip: TNIPIdWew,
    /// Adres sprzedawcy - linia adresowa (Podmiot1/Adres/AdresL1).
    #[serde(rename = "issuerAddress", skip_serializing_if = "Option::is_none")]
    pub issuer_address: Option<TZnakowy>,
    /// Kod pocztowy sprzedawcy (aplikacyjny).
    #[serde(rename = "issuerPostalCode", skip_serializing_if = "Option::is_none")]
    pub issuer_postal_code: Option<TZnakowy>,
    /// Miejscowość sprzedawcy (aplikacyjny).
    #[serde(rename = "issuerCity", skip_serializing_if = "Option::is_none")]
    pub issuer_city: Option<TZnakowy>,
    /// Kod kraju sprzedawcy (Podmiot1/Adres/KodKraju).
    #[serde(rename = "issuerCountry", skip_serializing_if = "Option::is_none")]
    pub issuer_country: Option<TKodyKrajowUE>,
    /// Numer KRS sprzedawcy (Stopka/Rejestry/KRS).
    #[serde(rename = "issuerKrs", skip_serializing_if = "Option::is_none")]
    pub issuer_krs: Option<TZnakowy>,
    /// Numer REGON sprzedawcy (Stopka/Rejestry/REGON).
    #[serde(rename = "issuerRegon", skip_serializing_if = "Option::is_none")]
    pub issuer_regon: Option<TZnakowy>,
    /// Kod (prefiks) podatnika VAT UE (Podmiot1/PrefiksPodatnika).
    ///
    /// Kod (prefiks) podatnika VAT UE dla przypadków określonych w art. 97
    /// ust. 10 pkt 2 i 3 ustawy oraz w przypadku, o którym mowa w art. 136
    /// ust. 1 pkt 3 ustawy. Wartość stała: "PL". minOccurs="0".
    #[serde(rename = "issuerTaxPrefix", skip_serializing_if = "Option::is_none")]
    pub issuer_tax_prefix: Option<TKodyKrajowUE>,
    /// Numer EORI podatnika (Podmiot1/NrEORI).
    ///
    /// Numer EORI podatnika (sprzedawcy). minOccurs="0".
    #[serde(rename = "issuerNrEori", skip_serializing_if = "Option::is_none")]
    pub issuer_nr_eori: Option<TZnakowy20>,
    /// Status podatnika (Podmiot1/StatusInfoPodatnika).
    ///
    /// TStatusInfoPodatnika. minOccurs="0".
    #[serde(rename = "issuerTaxStatus", skip_serializing_if = "Option::is_none")]
    pub issuer_tax_status: Option<TStatusInfoPodatnika>,
    /// Adres e-mail sprzedawcy (Podmiot1/DaneKontaktowe/Email).
    #[serde(rename = "sellerEmail", skip_serializing_if = "Option::is_none")]
    pub seller_email: Option<String>,
    /// Numer telefonu sprzedawcy (Podmiot1/DaneKontaktowe/Telefon).
    #[serde(rename = "sellerPhone", skip_serializing_if = "Option::is_none")]
    pub seller_phone: Option<TNumerTelefonu>,
    /// Adres korespondencyjny podatnika (Podmiot1/AdresKoresp).
    ///
    /// Adres korespondencyjny podatnika. TAdres. minOccurs="0".
    #[serde(
        rename = "issuerCorrespondenceAddress",
        skip_serializing_if = "Option::is_none"
    )]
    pub issuer_correspondence_address: Option<TAdres>,
    /// Dodatkowe dane kontaktowe podatnika (Podmiot1/DaneKontaktowe).
    ///
    /// minOccurs="0", maxOccurs="3".
    #[serde(rename = "issuerContacts", skip_serializing_if = "Option::is_none")]
    pub issuer_contacts: Option<Vec<DaneKontaktowe>>,

    // ====== Podmiot2 (recipient / buyer) — flat ======
    /// Imię i nazwisko lub nazwa nabywcy (Podmiot2/DaneIdentyfikacyjne/Nazwa).
    ///
    /// Dane nabywcy.
    #[serde(rename = "recipientName")]
    pub recipient_name: TZnakowy,
    /// Identyfikator podatkowy NIP nabywcy (Podmiot2/DaneIdentyfikacyjne/NIP).
    #[serde(rename = "recipientNip")]
    pub recipient_nip: TNIPIdWew,
    /// Adres nabywcy - linia adresowa (Podmiot2/Adres/AdresL1).
    ///
    /// Pola opcjonalne dla przypadków określonych w art. 106e ust. 5 pkt 3 ustawy.
    #[serde(rename = "recipientAddress", skip_serializing_if = "Option::is_none")]
    pub recipient_address: Option<TZnakowy>,
    /// Kod pocztowy nabywcy (aplikacyjny).
    #[serde(
        rename = "recipientPostalCode",
        skip_serializing_if = "Option::is_none"
    )]
    pub recipient_postal_code: Option<TZnakowy>,
    /// Miejscowość nabywcy (aplikacyjny).
    #[serde(rename = "recipientCity", skip_serializing_if = "Option::is_none")]
    pub recipient_city: Option<TZnakowy>,
    /// Kod kraju nabywcy (Podmiot2/Adres/KodKraju).
    #[serde(rename = "recipientCountry", skip_serializing_if = "Option::is_none")]
    pub recipient_country: Option<TKodyKrajowUE>,
    /// Numer KRS nabywcy (aplikacyjny).
    #[serde(rename = "recipientKrs", skip_serializing_if = "Option::is_none")]
    pub recipient_krs: Option<TZnakowy>,
    /// Numer REGON nabywcy (aplikacyjny).
    #[serde(rename = "recipientRegon", skip_serializing_if = "Option::is_none")]
    pub recipient_regon: Option<TZnakowy>,
    /// Numer EORI nabywcy (Podmiot2/NrEORI).
    ///
    /// Numer EORI nabywcy towarów. minOccurs="0".
    #[serde(rename = "recipientNrEori", skip_serializing_if = "Option::is_none")]
    pub recipient_nr_eori: Option<TZnakowy20>,
    /// Kod (prefiks) nabywcy VAT UE (Podmiot2/DaneIdentyfikacyjne/KodUE).
    ///
    /// Kod (prefiks) nabywcy VAT UE, o którym mowa w art. 106e ust. 1 pkt 24 ustawy.
    #[serde(rename = "recipientKodUe", skip_serializing_if = "Option::is_none")]
    pub recipient_kod_ue: Option<TKodyKrajowUE>,
    /// Numer Identyfikacyjny VAT kontrahenta UE (Podmiot2/DaneIdentyfikacyjne/NrVatUE).
    #[serde(rename = "recipientNrVatUe", skip_serializing_if = "Option::is_none")]
    pub recipient_nr_vat_ue: Option<TNrVatUE>,
    /// Kod kraju nadania identyfikatora podatkowego (Podmiot2/DaneIdentyfikacyjne/KodKraju).
    #[serde(rename = "recipientKodKraju", skip_serializing_if = "Option::is_none")]
    pub recipient_kod_kraju: Option<TKodKraju>,
    /// Identyfikator podatkowy inny (Podmiot2/DaneIdentyfikacyjne/NrID).
    #[serde(rename = "recipientNrId", skip_serializing_if = "Option::is_none")]
    pub recipient_nr_id: Option<TZnakowy50>,
    /// Podmiot nie posiada identyfikatora podatkowego (Podmiot2/DaneIdentyfikacyjne/BrakID).
    ///
    /// 1 - tak.
    #[serde(rename = "recipientBrakId", skip_serializing_if = "Option::is_none")]
    pub recipient_brak_id: Option<u8>,
    /// Adres e-mail nabywcy (Podmiot2/DaneKontaktowe/Email).
    #[serde(rename = "buyerEmail", skip_serializing_if = "Option::is_none")]
    pub buyer_email: Option<String>,
    /// Numer telefonu nabywcy (Podmiot2/DaneKontaktowe/Telefon).
    #[serde(rename = "buyerPhone", skip_serializing_if = "Option::is_none")]
    pub buyer_phone: Option<TNumerTelefonu>,
    /// Numer klienta nabywcy (Podmiot2/NrKlienta).
    ///
    /// Numer klienta dla przypadków, w których nabywca posługuje się nim
    /// w umowie lub zamówieniu. minOccurs="0".
    #[serde(rename = "buyerClientNumber", skip_serializing_if = "Option::is_none")]
    pub buyer_client_number: Option<TZnakowy>,
    /// Unikalny klucz powiązania danych nabywcy (Podmiot2/IDNabywcy).
    ///
    /// Unikalny klucz powiązania danych nabywcy na fakturach korygujących,
    /// w przypadku gdy dane nabywcy na fakturze korygującej zmieniły się
    /// w stosunku do danych na fakturze korygowanej. maxLength="32". minOccurs="0".
    #[serde(rename = "buyerIdNabywcy", skip_serializing_if = "Option::is_none")]
    pub buyer_id_nabywcy: Option<TZnakowy>,
    /// Adres korespondencyjny nabywcy (Podmiot2/AdresKoresp).
    ///
    /// TAdres. minOccurs="0".
    #[serde(
        rename = "recipientCorrespondenceAddress",
        skip_serializing_if = "Option::is_none"
    )]
    pub recipient_correspondence_address: Option<TAdres>,
    /// Dodatkowe dane kontaktowe nabywcy (Podmiot2/DaneKontaktowe).
    ///
    /// minOccurs="0", maxOccurs="3".
    #[serde(rename = "recipientContacts", skip_serializing_if = "Option::is_none")]
    pub recipient_contacts: Option<Vec<DaneKontaktowe>>,
    /// Znacznik jednostki podrzędnej JST (Podmiot2/JST).
    ///
    /// 1 = faktura dotyczy jednostki podrzędnej JST (wypełnić Podmiot3 z rolą 8);
    /// 2 = faktura nie dotyczy jednostki podrzędnej JST.
    #[serde(rename = "recipientJst", skip_serializing_if = "Option::is_none")]
    pub recipient_jst: Option<u8>,
    /// Znacznik członka grupy VAT (Podmiot2/GV).
    ///
    /// 1 = faktura dotyczy członka grupy VAT (wypełnić Podmiot3 z rolą 10);
    /// 2 = faktura nie dotyczy członka grupy VAT.
    #[serde(rename = "recipientGv", skip_serializing_if = "Option::is_none")]
    pub recipient_gv: Option<u8>,

    // ====== Podmiot3 (third parties) ======
    /// Dane podmiotów trzecich (Podmiot3).
    ///
    /// minOccurs="0", maxOccurs="100".
    #[serde(rename = "podmiot3", skip_serializing_if = "Option::is_none")]
    pub podmiot3: Option<Vec<Podmiot3Info>>,

    // ====== PodmiotUpowazniony ======
    /// Dane podmiotu upoważnionego (PodmiotUpowazniony).
    ///
    /// minOccurs="0".
    #[serde(rename = "podmiotUpowazniony", skip_serializing_if = "Option::is_none")]
    pub podmiot_upowazniony: Option<PodmiotUpowaznionyInfo>,

    // ====== Fa section ======
    /// Kod waluty (Fa/KodWaluty).
    ///
    /// Kod waluty (ISO 4217). Defaults to "PLN".
    #[serde(default = "default_currency")]
    pub currency: TKodWaluty,
    /// Kolejny numer faktury (Fa/P_2).
    ///
    /// Kolejny numer faktury, nadany w ramach jednej lub więcej serii,
    /// który w sposób jednoznaczny identyfikuje fakturę.
    #[serde(rename = "invoiceNumber")]
    pub invoice_number: TZnakowy50,
    /// Typ faktury (aplikacyjny).
    #[serde(rename = "invoiceType")]
    pub invoice_type: InvoiceType,
    /// Data wystawienia (Fa/P_1).
    ///
    /// Data wystawienia, z zastrzeżeniem art. 106na ust. 1 ustawy.
    #[serde(rename = "issueDate")]
    pub issue_date: TDataT,
    /// Miejsce wystawienia faktury (Fa/P_1M).
    ///
    /// minOccurs="0".
    #[serde(rename = "issuePlace", skip_serializing_if = "Option::is_none")]
    pub issue_place: Option<TZnakowy>,
    /// Numery dokumentów magazynowych WZ (Fa/WZ).
    ///
    /// Numery dokumentów magazynowych WZ (wydanie na zewnątrz) związane z fakturą.
    /// minOccurs="0", maxOccurs="1000".
    #[serde(rename = "wz", skip_serializing_if = "Option::is_none")]
    pub wz: Option<Vec<TZnakowy>>,
    /// Data dokonania/zakończenia dostawy lub wykonania usługi (Fa/P_6).
    ///
    /// Data dokonania lub zakończenia dostawy towarów lub wykonania usługi
    /// lub data otrzymania zapłaty, o której mowa w art. 106b ust. 1 pkt 4 ustawy,
    /// o ile taka data jest określona i różni się od daty wystawienia faktury.
    #[serde(rename = "saleDate")]
    pub sale_date: TDataT,
    /// Data usługi (alias, kept for compat).
    #[serde(rename = "serviceDate", skip_serializing_if = "Option::is_none")]
    pub service_date: Option<TDataT>,
    /// Data początkowa okresu fakturowania (Fa/OkresFa/P_6_Od).
    ///
    /// Okres, którego dotyczy faktura - art. 19a ust. 3, 4, 5 pkt 4 ustawy.
    #[serde(rename = "billingPeriodFrom", skip_serializing_if = "Option::is_none")]
    pub billing_period_from: Option<TDataT>,
    /// Data końcowa okresu fakturowania (Fa/OkresFa/P_6_Do).
    ///
    /// Data dokonania lub zakończenia dostawy towarów lub wykonania usługi.
    #[serde(rename = "billingPeriodTo", skip_serializing_if = "Option::is_none")]
    pub billing_period_to: Option<TDataT>,

    // --- VAT rate summaries (P_13_x / P_14_x) ---
    /// Suma wartości sprzedaży netto - stawka podstawowa 23%/22% (Fa/P_13_1).
    ///
    /// Suma wartości sprzedaży netto objętej stawką podstawową - aktualnie 23% albo 22%.
    /// W przypadku faktur zaliczkowych - wartość zaliczki netto.
    /// W przypadku faktur korygujących - kwota różnicy (art. 106j ust. 2 pkt 5).
    #[serde(rename = "p131", alias = "p13_1", skip_serializing_if = "Option::is_none")]
    pub p_13_1: Option<TKwotowy>,
    /// Kwota podatku - stawka podstawowa 23%/22% (Fa/P_14_1).
    ///
    /// Kwota podatku od sumy wartości sprzedaży netto objętej stawką podstawową.
    #[serde(rename = "p141", alias = "p14_1", skip_serializing_if = "Option::is_none")]
    pub p_14_1: Option<TKwotowy>,
    /// Kwota podatku w walucie obcej - stawka 23%/22% (Fa/P_14_1W).
    ///
    /// W przypadku gdy faktura jest wystawiona w walucie obcej - kwota podatku
    /// przeliczona zgodnie z przepisami działu VI w związku z art. 106e ust. 11 ustawy.
    /// minOccurs="0".
    #[serde(rename = "p141w", alias = "p14_1w", skip_serializing_if = "Option::is_none")]
    pub p_14_1w: Option<TKwotowy>,
    /// Suma wartości sprzedaży netto - stawka obniżona 8%/7% (Fa/P_13_2).
    #[serde(rename = "p132", alias = "p13_2", skip_serializing_if = "Option::is_none")]
    pub p_13_2: Option<TKwotowy>,
    /// Kwota podatku - stawka obniżona 8%/7% (Fa/P_14_2).
    #[serde(rename = "p142", alias = "p14_2", skip_serializing_if = "Option::is_none")]
    pub p_14_2: Option<TKwotowy>,
    /// Kwota podatku w walucie obcej - stawka 8%/7% (Fa/P_14_2W).
    ///
    /// minOccurs="0".
    #[serde(rename = "p142w", alias = "p14_2w", skip_serializing_if = "Option::is_none")]
    pub p_14_2w: Option<TKwotowy>,
    /// Suma wartości sprzedaży netto - stawka obniżona 5% (Fa/P_13_3).
    #[serde(rename = "p133", alias = "p13_3", skip_serializing_if = "Option::is_none")]
    pub p_13_3: Option<TKwotowy>,
    /// Kwota podatku - stawka obniżona 5% (Fa/P_14_3).
    #[serde(rename = "p143", alias = "p14_3", skip_serializing_if = "Option::is_none")]
    pub p_14_3: Option<TKwotowy>,
    /// Kwota podatku w walucie obcej - stawka 5% (Fa/P_14_3W).
    ///
    /// minOccurs="0".
    #[serde(rename = "p143w", alias = "p14_3w", skip_serializing_if = "Option::is_none")]
    pub p_14_3w: Option<TKwotowy>,
    /// Suma wartości sprzedaży netto - ryczałt dla taksówek (Fa/P_13_4).
    ///
    /// Suma wartości sprzedaży netto objętej ryczałtem dla taksówek osobowych.
    #[serde(rename = "p134", alias = "p13_4", skip_serializing_if = "Option::is_none")]
    pub p_13_4: Option<TKwotowy>,
    /// Kwota podatku - ryczałt dla taksówek (Fa/P_14_4).
    #[serde(rename = "p144", alias = "p14_4", skip_serializing_if = "Option::is_none")]
    pub p_14_4: Option<TKwotowy>,
    /// Kwota podatku w walucie obcej - ryczałt dla taksówek (Fa/P_14_4W).
    ///
    /// minOccurs="0".
    #[serde(rename = "p144w", alias = "p14_4w", skip_serializing_if = "Option::is_none")]
    pub p_14_4w: Option<TKwotowy>,
    /// Suma wartości sprzedaży netto - dział XII rozdział 6a (Fa/P_13_5).
    ///
    /// Procedura szczególna, o której mowa w dziale XII w rozdziale 6a ustawy.
    #[serde(rename = "p135", alias = "p13_5", skip_serializing_if = "Option::is_none")]
    pub p_13_5: Option<TKwotowy>,
    /// Kwota podatku - dział XII rozdział 6a (Fa/P_14_5).
    ///
    /// minOccurs="0".
    #[serde(rename = "p145", alias = "p14_5", skip_serializing_if = "Option::is_none")]
    pub p_14_5: Option<TKwotowy>,
    /// Suma wartości sprzedaży 0% - krajowa (Fa/P_13_6_1).
    ///
    /// Suma wartości sprzedaży objętej stawką 0% z wyłączeniem WDT i eksportu.
    /// minOccurs="0".
    #[serde(rename = "p1361", alias = "p13_6_1", skip_serializing_if = "Option::is_none")]
    pub p_13_6_1: Option<TKwotowy>,
    /// Suma wartości sprzedaży 0% - WDT (Fa/P_13_6_2).
    ///
    /// Suma wartości sprzedaży objętej stawką 0% w przypadku
    /// wewnątrzwspólnotowej dostawy towarów. minOccurs="0".
    #[serde(rename = "p1362", alias = "p13_6_2", skip_serializing_if = "Option::is_none")]
    pub p_13_6_2: Option<TKwotowy>,
    /// Suma wartości sprzedaży 0% - eksport (Fa/P_13_6_3).
    ///
    /// Suma wartości sprzedaży objętej stawką 0% w przypadku eksportu.
    /// minOccurs="0".
    #[serde(rename = "p1363", alias = "p13_6_3", skip_serializing_if = "Option::is_none")]
    pub p_13_6_3: Option<TKwotowy>,
    /// Suma wartości sprzedaży zwolnionej (Fa/P_13_7).
    ///
    /// Suma wartości sprzedaży zwolnionej od podatku. minOccurs="0".
    #[serde(rename = "p137", alias = "p13_7", skip_serializing_if = "Option::is_none")]
    pub p_13_7: Option<TKwotowy>,
    /// Suma wartości sprzedaży poza terytorium kraju (Fa/P_13_8).
    ///
    /// Suma wartości sprzedaży w przypadku dostawy towarów oraz świadczenia
    /// usług poza terytorium kraju, z wyłączeniem P_13_5 i P_13_9.
    /// minOccurs="0".
    #[serde(rename = "p138", alias = "p13_8", skip_serializing_if = "Option::is_none")]
    pub p_13_8: Option<TKwotowy>,
    /// Suma wartości usług art. 100 (Fa/P_13_9).
    ///
    /// Suma wartości świadczenia usług, o których mowa w art. 100 ust. 1 pkt 4 ustawy.
    /// minOccurs="0".
    #[serde(rename = "p139", alias = "p13_9", skip_serializing_if = "Option::is_none")]
    pub p_13_9: Option<TKwotowy>,
    /// Suma wartości sprzedaży - odwrotne obciążenie (Fa/P_13_10).
    ///
    /// Suma wartości sprzedaży w procedurze odwrotnego obciążenia,
    /// dla której podatnikiem jest nabywca zgodnie z art. 17 ust. 1 pkt 7 i 8 ustawy.
    /// minOccurs="0".
    #[serde(rename = "p1310", alias = "p13_10", skip_serializing_if = "Option::is_none")]
    pub p_13_10: Option<TKwotowy>,
    /// Suma wartości sprzedaży - procedura marży (Fa/P_13_11).
    ///
    /// Suma wartości sprzedaży w procedurze marży, o której mowa
    /// w art. 119 i art. 120 ustawy. minOccurs="0".
    #[serde(rename = "p1311", alias = "p13_11", skip_serializing_if = "Option::is_none")]
    pub p_13_11: Option<TKwotowy>,

    /// Agregacja stawek VAT (aplikacyjna).
    ///
    /// Wygodne grupowanie pól P_13_x / P_14_x.
    #[serde(rename = "vatRates", skip_serializing_if = "Option::is_none")]
    pub vat_rates: Option<Vec<VatRateInfo>>,

    /// Kwota należności ogółem (Fa/P_15).
    ///
    /// Kwota należności ogółem. W przypadku faktur zaliczkowych - kwota zapłaty
    /// dokumentowana fakturą. W przypadku faktur, o których mowa w art. 106f ust. 3
    /// ustawy - kwota pozostała do zapłaty. W przypadku faktur korygujących -
    /// korekta kwoty wynikającej z faktury korygowanej.
    #[serde(rename = "grossAmount")]
    pub gross_amount: TKwotowy,
    /// Kwota netto ogółem (aplikacyjna).
    #[serde(rename = "netAmount")]
    pub net_amount: TKwotowy,
    /// Kwota podatku ogółem (aplikacyjna).
    #[serde(rename = "taxAmount")]
    pub tax_amount: TKwotowy,
    /// Kurs waluty dla zaliczek (Fa/KursWalutyZ).
    ///
    /// Kurs waluty stosowany do wyliczenia kwoty podatku w przypadkach,
    /// o których mowa w dziale VI ustawy na fakturach, o których mowa
    /// w art. 106b ust. 1 pkt 4 ustawy. minOccurs="0".
    #[serde(
        rename = "exchangeRateAdvance",
        skip_serializing_if = "Option::is_none"
    )]
    pub exchange_rate_advance: Option<TIlosci>,
    /// Kurs waluty (KursWaluty) - legacy compat.
    #[serde(rename = "exchangeRate", skip_serializing_if = "Option::is_none")]
    pub exchange_rate: Option<TIlosci>,

    // ====== Adnotacje ======
    /// Inne adnotacje na fakturze (Fa/Adnotacje).
    #[serde(rename = "adnotacje", skip_serializing_if = "Option::is_none")]
    pub adnotacje: Option<Adnotacje>,
    /// Mechanizm podzielonej płatności (legacy flat, P_18A).
    #[serde(
        rename = "annotationSplitPayment",
        skip_serializing_if = "Option::is_none"
    )]
    pub annotation_split_payment: Option<bool>,
    /// Odwrotne obciążenie (legacy flat, P_18).
    #[serde(
        rename = "annotationReverseCharge",
        skip_serializing_if = "Option::is_none"
    )]
    pub annotation_reverse_charge: Option<bool>,
    /// Samofakturowanie (legacy flat, P_17).
    #[serde(
        rename = "annotationSelfBilling",
        skip_serializing_if = "Option::is_none"
    )]
    pub annotation_self_billing: Option<bool>,
    /// Metoda kasowa (legacy flat, P_16).
    #[serde(
        rename = "annotationCashMethod",
        skip_serializing_if = "Option::is_none"
    )]
    pub annotation_cash_method: Option<bool>,
    /// Podstawa zwolnienia od podatku (legacy flat, P_19A/B/C).
    #[serde(rename = "taxExemptionBasis", skip_serializing_if = "Option::is_none")]
    pub tax_exemption_basis: Option<TZnakowy>,

    // ====== RodzajFaktury ======
    /// Rodzaj faktury - enum aplikacyjny (InvoiceKind).
    #[serde(rename = "invoiceKind", skip_serializing_if = "Option::is_none")]
    pub invoice_kind: Option<InvoiceKind>,
    /// Rodzaj faktury (Fa/RodzajFaktury).
    ///
    /// TRodzajFaktury: VAT, KOR, ZAL, ROZ, UPR, KOR_ZAL, KOR_ROZ.
    #[serde(rename = "rodzajFaktury", skip_serializing_if = "Option::is_none")]
    pub rodzaj_faktury: Option<TRodzajFaktury>,

    // ====== Correction data ======
    /// Przyczyna korekty (Fa/PrzyczynaKorekty) - legacy flat.
    #[serde(rename = "correctionReason", skip_serializing_if = "Option::is_none")]
    pub correction_reason: Option<TZnakowy>,
    /// Typ korekty (Fa/TypKorekty) - legacy flat.
    #[serde(rename = "correctionType", skip_serializing_if = "Option::is_none")]
    pub correction_type: Option<TTypKorekty>,
    /// Numer faktury korygowanej (Fa/DaneFaKorygowanej/NrFaKorygowanej) - legacy flat.
    #[serde(
        rename = "correctedInvoiceNumber",
        skip_serializing_if = "Option::is_none"
    )]
    pub corrected_invoice_number: Option<TZnakowy>,
    /// Data wystawienia faktury korygowanej (Fa/DaneFaKorygowanej/DataWystFaKorygowanej) - legacy flat.
    #[serde(
        rename = "correctedInvoiceDate",
        skip_serializing_if = "Option::is_none"
    )]
    pub corrected_invoice_date: Option<TDataT>,
    /// Numer KSeF faktury korygowanej (Fa/DaneFaKorygowanej/NrKSeFFaKorygowanej) - legacy flat.
    #[serde(
        rename = "correctedKsefNumber",
        skip_serializing_if = "Option::is_none"
    )]
    pub corrected_ksef_number: Option<TNumerKSeF>,
    /// Znacznik faktury korygowanej wystawionej poza KSeF (NrKSeFN) - legacy flat.
    #[serde(rename = "nrKsefN", skip_serializing_if = "Option::is_none")]
    pub nr_ksef_n: Option<TNumerKSeF>,
    /// Pełne strukturalne dane korekty (CorrectionData).
    ///
    /// Dane dla przypadków, gdy pole RodzajFaktury przyjmuje wartości
    /// KOR, KOR_ZAL lub KOR_ROZ.
    #[serde(rename = "correctionData", skip_serializing_if = "Option::is_none")]
    pub correction_data: Option<CorrectionData>,

    // ====== ZaliczkaCzesciowa (0..31) ======
    /// Zaliczki częściowe (Fa/ZaliczkaCzesciowa).
    ///
    /// Dane dla przypadków faktur dokumentujących otrzymanie więcej niż jednej
    /// płatności (art. 106b ust. 1 pkt 4 ustawy). minOccurs="0", maxOccurs="31".
    #[serde(rename = "zaliczkiCzesciowe", skip_serializing_if = "Option::is_none")]
    pub zaliczki_czesciowe: Option<Vec<ZaliczkaCzesciowa>>,

    // ====== FP, TP ======
    /// Faktura do paragonu (Fa/FP).
    ///
    /// Faktura, o której mowa w art. 109 ust. 3d ustawy. TWybor1. minOccurs="0".
    #[serde(rename = "fp", skip_serializing_if = "Option::is_none")]
    pub fp: Option<u8>,
    /// Powiązania między nabywcą a sprzedawcą (Fa/TP).
    ///
    /// Istniejące powiązania między nabywcą a dokonującym dostawy towarów
    /// lub usługodawcą, zgodnie z § 10 ust. 4 pkt 3, z zastrzeżeniem ust. 4b
    /// rozporządzenia. TWybor1. minOccurs="0".
    #[serde(rename = "tp", skip_serializing_if = "Option::is_none")]
    pub tp: Option<u8>,

    // ====== DodatkowyOpis (0..10000) ======
    /// Dodatkowe opisy na fakturze (Fa/DodatkowyOpis).
    ///
    /// Pola przeznaczone dla wykazywania dodatkowych danych na fakturze,
    /// w tym wymaganych przepisami prawa, dla których nie przewidziano
    /// innych pól/elementów. TKluczWartosc. minOccurs="0", maxOccurs="10000".
    #[serde(rename = "dodatkowyOpis", skip_serializing_if = "Option::is_none")]
    pub dodatkowy_opis: Option<Vec<DodatkowyOpis>>,
    /// Dodatkowe opisy (legacy compat).
    #[serde(
        rename = "additionalDescriptions",
        skip_serializing_if = "Option::is_none"
    )]
    pub additional_descriptions: Option<Vec<DodatkowyOpis>>,

    // ====== FakturaZaliczkowa refs (0..100) ======
    /// Referencje do faktur zaliczkowych (Fa/FakturaZaliczkowa).
    ///
    /// Numery faktur zaliczkowych lub ich numery KSeF, jeśli zostały wystawione
    /// z użyciem KSeF. minOccurs="0", maxOccurs="100".
    #[serde(
        rename = "fakturaZaliczkowaRef",
        skip_serializing_if = "Option::is_none"
    )]
    pub faktura_zaliczkowa_ref: Option<Vec<FakturaZaliczkowaRef>>,

    /// Zwrot akcyzy (Fa/ZwrotAkcyzy).
    ///
    /// Informacja dodatkowa niezbędna dla rolników ubiegających się o zwrot
    /// podatku akcyzowego zawartego w cenie oleju napędowego.
    /// TWybor1. minOccurs="0".
    #[serde(rename = "zwrotAkcyzy", skip_serializing_if = "Option::is_none")]
    pub zwrot_akcyzy: Option<u8>,

    // ====== FaWiersz (line items) ======
    /// Wiersze faktury (Fa/FaWiersz).
    ///
    /// Szczegółowe pozycje faktury. minOccurs="0", maxOccurs="10000".
    #[serde(rename = "lineItems", skip_serializing_if = "Option::is_none")]
    pub line_items: Option<Vec<InvoiceLineItem>>,

    // ====== Rozliczenie ======
    /// Dodatkowe rozliczenia na fakturze (Fa/Rozliczenie).
    ///
    /// minOccurs="0".
    #[serde(rename = "rozliczenie", skip_serializing_if = "Option::is_none")]
    pub rozliczenie: Option<Rozliczenie>,
    /// Rozliczenie - legacy text (compat).
    #[serde(rename = "settlement", skip_serializing_if = "Option::is_none")]
    pub settlement: Option<TZnakowy>,

    // ====== Platnosc ======
    /// Warunki płatności (Fa/Platnosc).
    ///
    /// minOccurs="0".
    #[serde(rename = "platnosc", skip_serializing_if = "Option::is_none")]
    pub platnosc: Option<Platnosc>,
    // Legacy flat payment fields (kept for compat)
    /// Forma płatności (legacy flat).
    #[serde(rename = "paymentMethod", skip_serializing_if = "Option::is_none")]
    pub payment_method: Option<TFormaPlatnosci>,
    /// Termin płatności (legacy flat).
    #[serde(rename = "paymentDueDate", skip_serializing_if = "Option::is_none")]
    pub payment_due_date: Option<TDataT>,
    /// Data płatności (legacy flat).
    #[serde(rename = "paymentDate", skip_serializing_if = "Option::is_none")]
    pub payment_date: Option<TDataT>,
    /// Data zapłaty (legacy flat).
    #[serde(rename = "paidDate", skip_serializing_if = "Option::is_none")]
    pub paid_date: Option<TDataT>,
    /// Czy zapłacono (legacy flat).
    #[serde(rename = "isPaid", skip_serializing_if = "Option::is_none")]
    pub is_paid: Option<bool>,
    /// Numer rachunku bankowego (legacy flat).
    #[serde(rename = "bankAccount", skip_serializing_if = "Option::is_none")]
    pub bank_account: Option<TNrRB>,
    /// Nazwa banku (legacy flat).
    #[serde(rename = "bankName", skip_serializing_if = "Option::is_none")]
    pub bank_name: Option<TZnakowy>,
    /// Kod SWIFT banku (legacy flat).
    #[serde(rename = "bankSwift", skip_serializing_if = "Option::is_none")]
    pub bank_swift: Option<SWIFTType>,
    /// Opis rachunku bankowego (legacy flat).
    #[serde(rename = "bankDescription", skip_serializing_if = "Option::is_none")]
    pub bank_description: Option<TZnakowy>,
    /// Rachunek własny banku (legacy flat).
    #[serde(rename = "bankOwnAccount", skip_serializing_if = "Option::is_none")]
    pub bank_own_account: Option<TRachunekWlasnyBanku>,
    /// Kwota rabatu (legacy flat).
    #[serde(rename = "discountAmount", skip_serializing_if = "Option::is_none")]
    pub discount_amount: Option<TKwotowy>,

    // ====== WarunkiTransakcji ======
    /// Warunki transakcji (Fa/WarunkiTransakcji).
    ///
    /// Warunki transakcji, o ile występują. minOccurs="0".
    #[serde(rename = "warunkiTransakcji", skip_serializing_if = "Option::is_none")]
    pub warunki_transakcji: Option<WarunkiTransakcji>,
    /// Warunki dostawy (legacy flat).
    #[serde(rename = "deliveryTerms", skip_serializing_if = "Option::is_none")]
    pub delivery_terms: Option<TZnakowy>,
    /// Numer zamówienia (legacy flat).
    #[serde(rename = "orderNumber", skip_serializing_if = "Option::is_none")]
    pub order_number: Option<TZnakowy>,
    /// Numery zamówień (legacy flat).
    #[serde(rename = "orderNumbers", skip_serializing_if = "Option::is_none")]
    pub order_numbers: Option<Vec<TZnakowy>>,

    // ====== Zamowienie (advance invoice order) ======
    /// Zamówienie lub umowa - faktury zaliczkowe (Fa/Zamowienie).
    ///
    /// Zamówienie lub umowa, o których mowa w art. 106f ust. 1 pkt 4 ustawy
    /// (dla faktur zaliczkowych), w walucie, w której wystawiono fakturę
    /// zaliczkową. minOccurs="0".
    #[serde(rename = "zamowienie", skip_serializing_if = "Option::is_none")]
    pub zamowienie: Option<ZamowienieData>,

    // ====== Stopka ======
    /// Pozostałe dane na fakturze (Stopka).
    ///
    /// minOccurs="0".
    #[serde(rename = "stopka", skip_serializing_if = "Option::is_none")]
    pub stopka: Option<Stopka>,
    /// Stopka faktury - tekst (legacy flat).
    #[serde(rename = "footerText", skip_serializing_if = "Option::is_none")]
    pub footer_text: Option<TZnakowy>,

    // ====== Zalacznik ======
    /// Załącznik do faktury VAT (Zalacznik).
    ///
    /// minOccurs="0".
    #[serde(rename = "zalacznik", skip_serializing_if = "Option::is_none")]
    pub zalacznik: Option<Zalacznik>,

    // ====== App-level/KSeF metadata (not XSD Fa children) ======
    /// Numer identyfikujący fakturę w KSeF (aplikacyjny).
    #[serde(rename = "ksefNumber", skip_serializing_if = "Option::is_none")]
    pub ksef_number: Option<TNumerKSeF>,
    /// Data przetworzenia w KSeF (aplikacyjny).
    #[serde(rename = "processingDate", skip_serializing_if = "Option::is_none")]
    pub processing_date: Option<String>,
    /// Referencja sesji KSeF (aplikacyjny).
    #[serde(rename = "sessionRef", skip_serializing_if = "Option::is_none")]
    pub session_ref: Option<String>,
    /// Czy UPO jest dostępne (aplikacyjny).
    #[serde(rename = "upoAvailable", skip_serializing_if = "Option::is_none")]
    pub upo_available: Option<bool>,
    /// Referencja UPO (aplikacyjny).
    #[serde(rename = "upoReference", skip_serializing_if = "Option::is_none")]
    pub upo_reference: Option<String>,
    /// URL kodu QR (aplikacyjny).
    #[serde(rename = "qrCodeUrl", skip_serializing_if = "Option::is_none")]
    pub qr_code_url: Option<String>,
    /// Znacznik samofakturowania (aplikacyjny).
    #[serde(rename = "isSelfBilling", default)]
    pub is_self_billing: bool,
    /// Faktura uproszczona - UPR (aplikacyjny).
    #[serde(rename = "isSimplified", skip_serializing_if = "Option::is_none")]
    pub is_simplified: Option<bool>,
    /// Numer BDO (aplikacyjny).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub bdo: Option<TZnakowy>,
    /// Uwagi (aplikacyjny).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub notes: Option<TZnakowy>,
    /// Obowiązek art. 42 ust. 5 ustawy (Adnotacje/NoweSrodkiTransportu/P_42_5).
    ///
    /// Jeśli występuje obowiązek, o którym mowa w art. 42 ust. 5 ustawy,
    /// wartość "1"; w przeciwnym przypadku - wartość "2". TWybor1_2.
    #[serde(rename = "p425", skip_serializing_if = "Option::is_none")]
    pub p_42_5: Option<u8>,
}

fn default_currency() -> TKodWaluty {
    "PLN".to_string()
}
