using PowderCoating.Core.Enums;

namespace PowderCoating.Core.Entities;

public class Invoice : BaseEntity
{
    public string InvoiceNumber { get; set; } = string.Empty;
    public int? JobId { get; set; }
    public int CustomerId { get; set; }
    public string? PreparedById { get; set; }

    public InvoiceStatus Status { get; set; } = InvoiceStatus.Draft;

    // Dates
    public DateTime InvoiceDate { get; set; } = DateTime.UtcNow;
    public DateTime? DueDate { get; set; }
    public DateTime? SentDate { get; set; }
    public DateTime? PaidDate { get; set; }

    // Financials
    public decimal SubTotal { get; set; }
    public decimal TaxPercent { get; set; }
    public decimal TaxAmount { get; set; }
    public decimal DiscountAmount { get; set; }
    public decimal Total { get; set; }
    public decimal AmountPaid { get; set; }
    public decimal CreditApplied { get; set; }              // Sum of credit memo applications
    public decimal GiftCertificateRedeemed { get; set; }   // Sum of gift certificate redemptions
    public decimal BalanceDue => Total - AmountPaid - CreditApplied - GiftCertificateRedeemed;

    /// <summary>
    /// Permanent public token for the customer-facing invoice view page (/invoice/{token}).
    /// Generated when the invoice is first sent (regardless of Stripe status) and never expires.
    /// Distinct from PaymentLinkToken which is Stripe-gated and expires in 5 days.
    /// </summary>
    public string? PublicViewToken { get; set; }

    // Online payments (Stripe Connect)
    public OnlinePaymentStatus OnlinePaymentStatus { get; set; } = OnlinePaymentStatus.NotApplicable;
    public string? PaymentLinkToken { get; set; }           // Signed token for /pay/{token}
    public DateTime? PaymentLinkExpiresAt { get; set; }     // 5 days from generation
    public string? StripePaymentIntentId { get; set; }      // Most recent PaymentIntent ID
    public decimal OnlineAmountPaid { get; set; } = 0;      // Running total of online payments received
    public decimal OnlineSurchargeCollected { get; set; } = 0; // Surcharge amount collected (for records)

    // Text
    public string? Notes { get; set; }
    public string? InternalNotes { get; set; }
    public string? Terms { get; set; }
    public string? CustomerPO { get; set; }
    public string? ProjectName { get; set; }

    /// <summary>
    /// Early payment discount percentage (e.g., 2 means 2% discount).
    /// Parsed from the customer's payment terms when the invoice is created (e.g., "2/10 Net 30").
    /// Informational only — does not automatically reduce the amount due.
    /// </summary>
    public decimal EarlyPaymentDiscountPercent { get; set; }

    /// <summary>
    /// Number of days after invoice date within which the early payment discount applies.
    /// Parsed from the customer's payment terms (e.g., "2/10 Net 30" → 10 days).
    /// </summary>
    public int EarlyPaymentDiscountDays { get; set; }

    /// <summary>
    /// Original invoice number from an external system (e.g. QuickBooks invoice # "3048").
    /// Stored for searchability and traceability after import. Searchable from the invoice list.
    /// </summary>
    public string? ExternalReference { get; set; }

    /// <summary>
    /// Liability account where collected sales tax is tracked (e.g., 2200 Sales Tax Payable).
    /// Populated automatically when TaxAmount > 0.
    /// </summary>
    public int? SalesTaxAccountId { get; set; }

    // Navigation
    public virtual Job? Job { get; set; }
    public virtual Customer Customer { get; set; } = null!;
    public virtual ApplicationUser? PreparedBy { get; set; }
    public virtual Account? SalesTaxAccount { get; set; }
    public virtual ICollection<InvoiceItem> InvoiceItems { get; set; } = new List<InvoiceItem>();
    public virtual ICollection<Payment> Payments { get; set; } = new List<Payment>();
    public virtual ICollection<Refund> Refunds { get; set; } = new List<Refund>();
    public virtual ICollection<CreditMemoApplication> CreditApplications { get; set; } = new List<CreditMemoApplication>();
    public virtual ICollection<GiftCertificateRedemption> GiftCertificateRedemptions { get; set; } = new List<GiftCertificateRedemption>();
}
