using System.Collections.Generic;
using System.IO;
namespace BulkArchiveMailer.Core
{
/// Status of one preview row / send attempt.
public enum SendStatus
{
/// Exactly one archive found for this login, nothing sent for it yet - safe to send.
Ready,
/// A prior log entry shows this exact archive (by SHA-256) was already sent to this address.
AlreadySent,
/// Blocking data problem (e.g. both archive kinds present for one login) - never sendable.
Error,
/// File in the folder did not match the expected naming pattern - listed for visibility, not sendable.
Skipped
}
///
/// One row of the send preview: everything needed to either display the
/// row in the grid or hand it to MailSender.
///
public sealed class SendJob
{
public string Login { get; set; } = "";
public string Email { get; set; } = "";
/// File suffix ("ssh_access", "config_update", or any other configured template's FileSuffix). Null for Error rows caused by a login/kind conflict, and for Skipped (unrecognized file) rows.
public string Kind { get; set; }
/// Null for conflict Error rows (see ) - otherwise the single archive to attach.
public string ArchivePath { get; set; }
/// Populated only for the "both kinds present" Error case: every archive path found for that login.
public IReadOnlyList ConflictingArchivePaths { get; set; }
public string Subject { get; set; } = "";
public string BodyHtml { get; set; } = "";
public SendStatus Status { get; set; } = SendStatus.Ready;
/// Human-readable explanation, set for Error/Skipped rows and for AlreadySent rows (when it was sent).
public string ErrorMessage { get; set; }
/// SHA-256 of ArchivePath's current bytes, computed when a SendLogStore is available. Used for the AlreadySent dedup key.
public string FileSha256 { get; set; }
/// Whether this row is even eligible to be checked/sent in the preview grid.
public bool IsSelectable => Status == SendStatus.Ready || Status == SendStatus.AlreadySent;
public string FileName => string.IsNullOrEmpty(ArchivePath) ? "" : Path.GetFileName(ArchivePath);
///
/// Human-readable label for the matched template (its
/// DisplayName), explicitly set by ArchiveScanner when it renders
/// this job - "-" for conflict Error rows and Skipped rows, which
/// never had a matched template. No longer computed from a fixed
/// enum switch, since the set of templates is now open-ended.
///
public string KindDisplay { get; set; } = "-";
public override string ToString() => $"{Login} <{Email}> [{Status}]";
}
}