using System.Text.Json.Serialization;
using AyCode.Core.Serializers.Attributes;
using AyCode.Core.Serializers.Toons;
using AyCode.Interfaces.TimeStampInfo;
using LinqToDB;
using LinqToDB.Mapping;
using Mango.Nop.Core.Entities;


namespace FruitBank.Common.Entities;

[AcBinarySerializable(false, true, false, true, false, false)]
[ToonDescription("NAV EKÁER declaration lifecycle record", Purpose = "Work-queue and audit row for one EKÁER road-freight declaration. One declaration covers one or more source records via EkaerHistoryMapping (the link lives in that junction table, NOT here): inbound, the ShippingDocuments of one (Shipping, Partner, PartnerDepot) group aggregated into a single tradeCard; outbound, a single completed Order. Tracks the declaration through generation, validation and submission to the Hungarian tax authority (NAV).")]
[Table(Name = FruitBankConstClient.EkaerHistoryDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.EkaerHistoryDbTableName)]

public sealed class EkaerHistory: MgEntityBase, ITimeStampInfo
{
    [ToonDescription(Purpose = "Direction of the goods movement: false = incoming shipment (Shipping), true = outgoing delivery (Order).")]
    public bool IsOutgoing { get; set; }

    [ToonDescription(Purpose = "Declaration-level date snapshot (group-invariant): inbound = the ShippingDocument's ShippingDate, outbound = the Order's DateOfReceipt. Set at create, refreshed on Generate. NO fallback — null if missing (the data gap is visible in the grid).")]
    public DateTime? ShippingDate { get; set; }

    [ToonDescription(Purpose = "Declaration-level other-party name snapshot (group-invariant): inbound = the supplier Partner.Name, outbound = the buyer Customer.Company. Set at create, refreshed on Generate. NO fallback — null/empty if missing.")]
    public string? Partner { get; set; }

    [ToonDescription(Purpose = "Lifecycle state of the declaration, stored as int (see EkaerStatus): 0 Pending (auto-created, not yet generated), 1 Generated (tradeCard XML produced and valid), 2 ValidationError (generation produced errors, see ErrorText), 3 Sent (accepted by NAV, EkaerNumber filled), 4 SendError (NAV call failed, see ErrorText).")]
    public int StatusId { get; set; }

    /// <summary>A <see cref="StatusId"/> enum-nézete. A tárolt érték az int oszlop (StatusId) — a linq2db réteg
    /// az enum-property-t nem perzisztálta (az oszlop kimaradt az insertből, a DB default írt 0-t), ezért a nop-minta:
    /// int oszlop + nem-mappelt enum wrapper.</summary>
    [NotColumn, System.ComponentModel.DataAnnotations.Schema.NotMapped, Newtonsoft.Json.JsonIgnore, JsonIgnore]
    public EkaerStatus Status
    {
        get => (EkaerStatus)StatusId;
        set => StatusId = (int)value;
    }

    [ToonDescription(Purpose = "The generated NAV EKÁER tradeCard request XML exactly as it was (or will be) submitted — audit copy and source of the read-only detail view. Null until the first Generate.")]
    public string? XmlDoc { get; set; }

    [Column(DataType = DataType.DecFloat)]
    [ToonDescription(Purpose = "The conversion rate actually applied when computing this declaration's item values to HUF: 1 for domestic (HUF) suppliers (no conversion), the FX rate (e.g. EUR→HUF) for foreign suppliers. Null before the first Generate. Currency-agnostic by design — works for any source currency. Audit trail: the invoice amount times this rate yields the HUF value in the tradeCard; the NAV schema has no rate field, so this column preserves how the value was derived.")]
    public double? ConversionRate { get; set; }

    [ToonDescription(Purpose = "The EKÁER number (TCN) assigned by NAV after a successful submission. Null until the declaration is accepted.")]
    public string? EkaerNumber { get; set; }

    [ToonDescription(Purpose = "When the declaration was successfully submitted to NAV. Null until sent.")]
    public DateTime? SentDate { get; set; }

    [ToonDescription(Purpose = "Validation or NAV submission error details for the ValidationError / SendError states. Null when the last operation succeeded.")]
    public string? ErrorText { get; set; }

    /// <summary>A deklarációhoz tartozó forrás-rekordok (EkaerHistoryMapping): bejövő → N szállítólevél (ShippingDocument.Id),
    /// kimenő → 1 rendelés (Order.Id). NEM auto-loadol — a DbTable GetAll(loadRelations: true) tölti (LoadWith).</summary>
    [Association(ThisKey = nameof(Id), OtherKey = nameof(EkaerHistoryMapping.EkaerHistoryId), CanBeNull = true)]
    public List<EkaerHistoryMapping>? Mappings { get; set; }

    public DateTime Created { get; set; }
    public DateTime Modified { get; set; }
}

/// <summary>Az EKÁER-bejelentés életciklus + kimenet állapota. Append-only: új érték a végére, meglévő értéke nem
/// változhat (DB-ben int-ként tárolt). Az állapot egyetlen mező; a kategorizálás a <see cref="EkaerStatusExtensions"/>
/// segédekkel megy (külön oszlop nélkül) — a folyamat lineáris, ezért a single-enum állapotgép a tiszta illeszkedés.</summary>
public enum EkaerStatus
{
    /// <summary>Automatikusan létrejött, még nem volt Generate.</summary>
    Pending = 0,
    /// <summary>A tradeCard XML legenerálva és valid — küldhető.</summary>
    Generated = 1,
    /// <summary>A Generate BLOKKOLÓ (error) hibákkal zárult (ErrorText) — a forrásadat javítandó, nem küldhető.</summary>
    ValidationError = 2,
    /// <summary>NAV által befogadva (EkaerNumber + SentDate töltve), hiánytalanul.</summary>
    Sent = 3,
    /// <summary>A NAV-hívás hibával zárult (ErrorText) — újraküldhető.</summary>
    SendError = 4,
    /// <summary>Legenerálva és KÜLDHETŐ, de warninggal (pl. hiányzó rendszám, ami a felrakodás megkezdéséig pótolható).</summary>
    GeneratedWithWarning = 5,
    /// <summary>NAV-hoz beküldve, de PÓTLÁSRA VÁR (pl. a rendszám a felrakodás megkezdéséig megadandó).</summary>
    SentWithMissingData = 6,
}

/// <summary>Állapot-kategóriák — a tárolás egy mező (Status), a csoportosítás ezekkel (külön oszlop nélkül).</summary>
public static class EkaerStatusExtensions
{
    /// <summary>Blokkoló hibás állapot (a bejelentés nem küldhető / a NAV-hívás bukott).</summary>
    public static bool IsError(this EkaerStatus status) => status is EkaerStatus.ValidationError or EkaerStatus.SendError;

    /// <summary>Beküldhető: legenerálva, blokkoló hiba nélkül (warninggal is) — innen mehet a NAV-hoz.</summary>
    public static bool IsSubmittable(this EkaerStatus status) => status is EkaerStatus.Generated or EkaerStatus.GeneratedWithWarning;

    /// <summary>A NAV-nál van (akár hiányosan).</summary>
    public static bool IsSent(this EkaerStatus status) => status is EkaerStatus.Sent or EkaerStatus.SentWithMissingData;

    /// <summary>Elküldve, de pótlásra vár (hiányos adat — pl. rendszám).</summary>
    public static bool NeedsCompletion(this EkaerStatus status) => status is EkaerStatus.SentWithMissingData;
}

/// <summary>EkaerHistory-lekérdezés szűrő a tabokhoz, <see cref="FlagsAttribute"/>. A kategóriák diszjunkt
/// StatusId-partíciók, ezért kombinálhatók (pl. <c>ToSubmit | NeedsCompletion</c> = minden, ami még nincs lezárva).
/// <see cref="All"/> = 0 (nincs bit = nincs szűrő → minden), egyúttal a biztonságos default; szándékosan NEM nullable.
/// Vigyázat: <c>HasFlag(All)</c> mindig true (0 bit), ezért a szerver előbb a <c>== All</c> ágat nézi.</summary>
[Flags]
public enum EkaerHistoryFilter
{
    /// <summary>Minden rekord (nincs szűrés). 0 = nincs bit → minden; egyúttal a biztonságos default.</summary>
    All = 0,
    /// <summary>Beküldésre váró: minden, ami még NINCS a NAV-nál (Pending/Generated/GeneratedWithWarning/ValidationError/SendError).</summary>
    ToSubmit = 1,
    /// <summary>Elküldött és hiánytalan (<see cref="EkaerStatus.Sent"/>).</summary>
    Sent = 2,
    /// <summary>Elküldve, de pótlásra vár (<see cref="EkaerStatus.SentWithMissingData"/>).</summary>
    NeedsCompletion = 4,
}

//public sealed class EkaerHistoryShipping : EkaerHistoryBase
//{
//    public int ShippingId
//    {
//        get => ForeignItemId;
//        set => ForeignItemId = value;
//    }

//    [Association(ThisKey = nameof(ShippingId), OtherKey = nameof(Shipping.Id), CanBeNull = true)]
//    public Shipping? Shipping { get; set; }
//}

//public sealed class EkaerHistoryOrder : EkaerHistoryBase
//{
//    public int ShippingId
//    {
//        get => ForeignItemId;
//        set => ForeignItemId = value;
//    }

//    [Association(ThisKey = nameof(ShippingId), OtherKey = nameof(Shipping.Id), CanBeNull = true)]
//    public Shipping? Shipping { get; set; }
//}

//public abstract class EkaerHistoryBase : MgEntityBase, ITimeStampInfo
//{
//    [NotColumn]
//    protected int ForeignItemId;

//    [NotColumn]
//    [ToonDescription(BusinessRule = "get => ForeignItemId", Constraints = "[#SmartTypeConstraints]")]
//    public int ForeignKey => ForeignItemId;

//    public DateTime Created { get; set; }
//    public DateTime Modified { get; set; }
//}