using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using PowderCoating.Application.DTOs.Common;
using PowderCoating.Application.DTOs.Notification;
using PowderCoating.Core.Enums;
using PowderCoating.Core.Interfaces;
using PowderCoating.Shared.Constants;
namespace PowderCoating.Web.Controllers;
///
/// Company-scoped notification log viewer accessible to users with the
/// CanManageJobs policy (Managers and above within a company).
/// The platform-wide equivalent for SuperAdmins lives in
/// .
///
[Authorize(Policy = AppConstants.Policies.CanManageJobs)]
public class NotificationLogsController : Controller
{
private readonly IUnitOfWork _unitOfWork;
private readonly ILogger _logger;
public NotificationLogsController(IUnitOfWork unitOfWork, ILogger logger)
{
_unitOfWork = unitOfWork;
_logger = logger;
}
///
/// Displays a paginated, filterable list of notification log entries for the current company.
/// Supports filtering by free-text search, channel, delivery status, notification type, and
/// an optional job context. Page size is validated against an allowlist (10/25/50/100).
///
// GET: /NotificationLogs
public async Task Index(
string? searchTerm,
string? channelFilter,
string? statusFilter,
string? typeFilter,
int? jobId,
string? sortColumn,
string sortDirection = "desc",
int pageNumber = 1,
int pageSize = 25)
{
pageNumber = Math.Max(1, pageNumber);
pageSize = pageSize is 10 or 25 or 50 or 100 ? pageSize : 25;
NotificationChannel? channel = Enum.TryParse(channelFilter, out var ch) ? ch : null;
NotificationStatus? status = Enum.TryParse(statusFilter, out var st) ? st : null;
NotificationType? type = Enum.TryParse(typeFilter, out var ty) ? ty : null;
var (logs, totalCount) = await _unitOfWork.NotificationLogs.GetPagedFilteredAsync(
pageNumber, pageSize, searchTerm, channel, status, type, jobId,
sortColumn ?? "SentAt", sortDirection);
var items = logs.Select(n => new NotificationLogDto
{
Id = n.Id,
Channel = n.Channel,
NotificationType = n.NotificationType,
Status = n.Status,
RecipientName = n.RecipientName,
Recipient = n.Recipient,
Subject = n.Subject,
Message = n.Message,
ErrorMessage = n.ErrorMessage,
SentAt = n.SentAt,
CustomerId = n.CustomerId,
JobId = n.JobId,
QuoteId = n.QuoteId,
JobNumber = n.Job?.JobNumber,
QuoteNumber = n.Quote?.QuoteNumber,
CustomerName = n.Customer != null
? (n.Customer.CompanyName ?? $"{n.Customer.ContactFirstName} {n.Customer.ContactLastName}".Trim())
: null
}).ToList();
var pagedResult = new PagedResult
{
Items = items,
TotalCount = totalCount,
PageNumber = pageNumber,
PageSize = pageSize
};
ViewBag.SearchTerm = searchTerm;
ViewBag.ChannelFilter = channelFilter;
ViewBag.StatusFilter = statusFilter;
ViewBag.TypeFilter = typeFilter;
ViewBag.JobId = jobId;
ViewBag.SortColumn = sortColumn ?? "SentAt";
ViewBag.SortDirection = sortDirection;
return View(pagedResult);
}
///
/// Displays the full details of a single notification log entry including the complete message
/// body and any error message, which are omitted from the list view. Loads related Customer,
/// Job, and Quote navigation properties to resolve display names.
///
// GET: /NotificationLogs/Details/5
public async Task Details(int id)
{
try
{
var log = await _unitOfWork.NotificationLogs.GetByIdAsync(
id, false, n => n.Customer, n => n.Job, n => n.Quote);
if (log == null) return NotFound();
var dto = new NotificationLogDto
{
Id = log.Id,
Channel = log.Channel,
NotificationType = log.NotificationType,
Status = log.Status,
RecipientName = log.RecipientName,
Recipient = log.Recipient,
Subject = log.Subject,
Message = log.Message,
ErrorMessage = log.ErrorMessage,
SentAt = log.SentAt,
CustomerId = log.CustomerId,
JobId = log.JobId,
QuoteId = log.QuoteId,
JobNumber = log.Job?.JobNumber,
QuoteNumber = log.Quote?.QuoteNumber,
CustomerName = log.Customer != null
? (log.Customer.CompanyName ?? $"{log.Customer.ContactFirstName} {log.Customer.ContactLastName}".Trim())
: null
};
return View(dto);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error loading notification log {Id}", id);
return RedirectToAction(nameof(Index));
}
}
}