using PowderCoating.Core.Entities;

namespace PowderCoating.Application.Interfaces;


public interface INotificationService
{
    /// <summary>
    /// Notify when a quote is created/sent. Handles both registered customers and prospects.
    /// Optionally attaches the quote PDF to the email.
    /// </summary>
    Task NotifyQuoteSentAsync(Quote quote, byte[]? pdfAttachment = null, string? pdfFilename = null, string? overrideEmail = null);

    /// <summary>
    /// Sends the quote approval link to the customer via SMS.
    /// Handles both registered customers (respects NotifyBySms) and prospects (ProspectPhone).
    /// Returns (success, errorMessage) so the caller can surface the result to the user.
    /// </summary>
    Task<(bool Success, string? Error)> NotifyQuoteSentSmsAsync(Quote quote);

    /// <summary>
    /// Notify when a quote is approved by a customer.
    /// </summary>
    Task NotifyQuoteApprovedAsync(Quote quote);

    /// <summary>
    /// Notify customer of a job status change. Also sends SMS when status is READY_FOR_PICKUP.
    /// </summary>
    Task NotifyJobStatusChangedAsync(Job job, string newStatusCode, string newStatusDisplayName);

    /// <summary>
    /// Notify customer when a job is completed and ready for pickup.
    /// When <paramref name="suppressSms"/> is true the SMS is skipped so an admin can review
    /// the message via <see cref="RenderJobCompletedSmsAsync"/> before sending manually.
    /// </summary>
    Task NotifyJobCompletedAsync(Job job, bool suppressSms = false);

    /// <summary>
    /// Renders the job-completed SMS text for admin preview without sending it.
    /// Returns null when SMS is not allowed for the company or the customer has not opted in.
    /// </summary>
    Task<string?> RenderJobCompletedSmsAsync(Job job);

    /// <summary>
    /// Sends a manually-composed SMS for a job (Admin/Manager compose-before-send path).
    /// Appends "Reply STOP to opt out." if not already present, sends, and writes a NotificationLog row.
    /// Returns (success, errorMessage).
    /// </summary>
    Task<(bool Success, string? Error)> SendJobSmsAsync(Job job, string message);

    /// <summary>
    /// Sends a welcome/confirmation SMS after staff records verbal SMS consent.
    /// This message confirms enrollment and provides opt-out instructions per CTIA guidelines.
    /// </summary>
    Task NotifySmsConsentGrantedAsync(Customer customer);

    /// <summary>
    /// Notify customer when an invoice has been sent.
    /// Optionally includes an online payment link in the email body.
    /// </summary>
    Task NotifyInvoiceSentAsync(Invoice invoice, byte[]? pdfAttachment = null, string? pdfFilename = null, string? paymentUrl = null, string? overrideEmail = null, bool sendSms = false, string? viewUrl = null);

    /// <summary>
    /// Notify customer (internal) when a payment has been recorded on an invoice.
    /// </summary>
    Task NotifyPaymentReceivedAsync(Invoice invoice, Payment payment);

    /// <summary>
    /// Notify the company (internal) when a customer approves or declines a quote via the self-service portal.
    /// </summary>
    Task NotifyQuoteActedByCustomerAsync(Quote quote, bool approved, string? declineReason);

    /// <summary>
    /// Send a payment reminder to the customer for an overdue invoice.
    /// </summary>
    /// <param name="invoice">The overdue invoice (must have Customer loaded or CustomerId set).</param>
    /// <param name="daysOverdue">Number of days since the invoice was due.</param>
    Task NotifyPaymentReminderAsync(Invoice invoice, int daysOverdue);

    /// <summary>
    /// Send an online payment receipt to the customer after a successful Stripe payment.
    /// </summary>
    Task NotifyOnlinePaymentReceivedAsync(Invoice invoice, decimal amountPaid, decimal surchargePaid, string paymentIntentId);

    /// <summary>
    /// Notify the company (internal) when a customer pays a deposit online for a quote.
    /// </summary>
    Task NotifyDepositReceivedAsync(Quote quote, decimal amountPaid, decimal surchargePaid, string paymentIntentId);

    /// <summary>
    /// Alert company staff when a Stripe chargeback (dispute) is opened on an invoice payment.
    /// </summary>
    Task NotifyChargebackAlertAsync(Invoice invoice, string disputeId, decimal amount, string reason);

    /// <summary>
    /// Sends an appointment reminder email to the linked customer (if opted in) and writes a
    /// notification log row. Called by <see cref="PowderCoating.Web.BackgroundServices.AppointmentReminderBackgroundService"/>
    /// when the reminder window opens. In-app bell notification is handled by the caller.
    /// </summary>
    Task NotifyAppointmentReminderAsync(Appointment appointment);
}
