using PowderCoating.Core.Entities;
using PowderCoating.Core.Enums;

namespace PowderCoating.Core.Interfaces.Repositories;

/// <summary>
/// Typed repository for <see cref="Invoice"/> that adds domain-specific queries on top of
/// the generic CRUD interface.
/// </summary>
public interface IInvoiceRepository : IRepository<Invoice>
{
    /// <summary>
    /// Loads a single invoice with the full eight-table include chain required by the Details
    /// view and PDF generation: Customer, Job, PreparedBy, SalesTaxAccount, InvoiceItems with
    /// RevenueAccount and GeneratedGiftCertificate, Payments with RecordedBy and DepositAccount,
    /// Refunds with IssuedBy, CreditApplications with CreditMemo, and GiftCertificateRedemptions.
    /// Filtered includes exclude soft-deleted children. Returns null if not found or soft-deleted.
    /// </summary>
    Task<Invoice?> LoadForViewAsync(int id, int companyId);

    /// <summary>
    /// Returns the invoice linked to a job, or null if none exists. Pass
    /// <paramref name="includeDeleted"/> = true to also surface soft-deleted invoices (used by
    /// the 1:1 uniqueness guard that prevents duplicate invoices for the same job).
    /// </summary>
    Task<Invoice?> GetForJobAsync(int jobId, bool includeDeleted = false);

    /// <summary>
    /// Looks up an invoice by its online-payment token. Ignores query filters so the payment
    /// portal can load the invoice even when the anonymous request has no tenant context.
    /// Returns null if the token does not match any invoice.
    /// </summary>
    Task<Invoice?> GetByPaymentTokenAsync(string token);

    /// <summary>
    /// Returns the last invoice number that starts with <paramref name="prefix"/> for the given
    /// company (including soft-deleted invoices) for sequential number generation.
    /// </summary>
    Task<string?> GetLastInvoiceNumberByPrefixAsync(int companyId, string prefix);

    /// <summary>
    /// Returns all non-deleted invoices that have at least one online payment for the given company
    /// and date window, with Customer navigation loaded. Used by the Online Payments reconciliation view.
    /// </summary>
    Task<List<Invoice>> GetOnlineInvoicesForPeriodAsync(int companyId, DateTime from, DateTime to);

    /// <summary>
    /// Returns all non-deleted CreditDebitCard refunds for the given company and date window,
    /// with Invoice→Customer navigation loaded. Used by the Online Payments reconciliation view.
    /// </summary>
    Task<List<Refund>> GetOnlineRefundsForPeriodAsync(int companyId, DateTime from, DateTime to);
}
