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;

/// <summary>
/// Company-scoped notification log viewer accessible to users with the
/// <c>CanManageJobs</c> policy (Managers and above within a company).
/// The platform-wide equivalent for SuperAdmins lives in
/// <see cref="PlatformNotificationsController"/>.
/// </summary>
[Authorize(Policy = AppConstants.Policies.CanManageJobs)]
public class NotificationLogsController : Controller
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly ILogger<NotificationLogsController> _logger;

    public NotificationLogsController(IUnitOfWork unitOfWork, ILogger<NotificationLogsController> logger)
    {
        _unitOfWork = unitOfWork;
        _logger = logger;
    }

    /// <summary>
    /// 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).
    /// </summary>
    // GET: /NotificationLogs
    public async Task<IActionResult> 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<NotificationChannel>(channelFilter, out var ch) ? ch : null;
        NotificationStatus? status   = Enum.TryParse<NotificationStatus>(statusFilter, out var st) ? st : null;
        NotificationType? type       = Enum.TryParse<NotificationType>(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<NotificationLogDto>
        {
            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);
    }

    /// <summary>
    /// 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.
    /// </summary>
    // GET: /NotificationLogs/Details/5
    public async Task<IActionResult> 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));
        }
    }
}
