using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using PowderCoating.Application.Interfaces;
using PowderCoating.Core.Entities;
using PowderCoating.Core.Interfaces;
using PowderCoating.Shared.Constants;
using System.ComponentModel.DataAnnotations;

namespace PowderCoating.Web.Controllers;

[Authorize]
public class ContactController : Controller
{
    private readonly IAdminNotificationService _adminNotification;
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly ITenantContext _tenantContext;
    private readonly IUnitOfWork _unitOfWork;
    private readonly ILogger<ContactController> _logger;

    public ContactController(
        IAdminNotificationService adminNotification,
        UserManager<ApplicationUser> userManager,
        ITenantContext tenantContext,
        IUnitOfWork unitOfWork,
        ILogger<ContactController> logger)
    {
        _adminNotification = adminNotification;
        _userManager = userManager;
        _tenantContext = tenantContext;
        _unitOfWork = unitOfWork;
        _logger = logger;
    }

    /// <summary>
    /// Renders the Contact Us page pre-filled with the current user's name, email, and company.
    /// </summary>
    [HttpGet]
    public async Task<IActionResult> Index()
    {
        var model = await BuildViewModelAsync();
        return View(model);
    }

    /// <summary>
    /// Handles the contact form submission. Saves to the database and sends an email notification
    /// to configured admin addresses with reply-to set to the submitter.
    /// </summary>
    [HttpPost, ValidateAntiForgeryToken]
    public async Task<IActionResult> Submit(ContactFormModel form)
    {
        if (!ModelState.IsValid)
        {
            var vm = await BuildViewModelAsync();
            vm.Form = form;
            return View("Index", vm);
        }

        var user = await _userManager.GetUserAsync(User);
        var companyId = _tenantContext.GetCurrentCompanyId() ?? 0;

        // Persist first — email is best-effort, record must survive even if email fails
        var submission = new ContactSubmission
        {
            CompanyId   = companyId,
            SenderName  = form.Name,
            SenderEmail = form.Email,
            CompanyName = form.CompanyName,
            Category    = form.Category,
            Subject     = form.Subject,
            Message     = form.Message,
            CreatedBy = user?.Id,
        };

        await _unitOfWork.ContactSubmissions.AddAsync(submission);
        await _unitOfWork.CompleteAsync();

        _logger.LogInformation("Contact form saved (id {Id}) from {Email} ({Company}): [{Category}] {Subject}",
            submission.Id, form.Email, form.CompanyName, form.Category, form.Subject);

        // Email notification is best-effort — a failure doesn't prevent the success message
        try
        {
            await _adminNotification.NotifyContactFormSubmittedAsync(
                senderName:  form.Name,
                senderEmail: form.Email,
                companyName: form.CompanyName,
                category:    form.Category,
                subject:     form.Subject,
                message:     form.Message);
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Contact form email notification failed for submission {Id} — record was saved", submission.Id);
        }

        TempData["Success"] = "Your message has been sent. We'll get back to you as soon as possible.";
        return RedirectToAction(nameof(Index));
    }

    /// <summary>
    /// Admin-only list of all contact form submissions, newest first.
    /// Unread submissions are highlighted. SuperAdmin sees all companies; company admins see their own.
    /// </summary>
    [HttpGet]
    [Authorize(Policy = AppConstants.Policies.SuperAdminOnly)]
    public async Task<IActionResult> Submissions()
    {
        var all = await _unitOfWork.ContactSubmissions.GetAllAsync();
        var list = all.OrderByDescending(s => s.CreatedAt).ToList();
        return View(list);
    }

    /// <summary>
    /// Marks a submission as read and optionally saves an admin note. SuperAdmin only.
    /// </summary>
    [HttpPost, ValidateAntiForgeryToken]
    [Authorize(Policy = AppConstants.Policies.SuperAdminOnly)]
    public async Task<IActionResult> MarkRead(int id, string? adminNotes)
    {
        var submission = await _unitOfWork.ContactSubmissions.GetByIdAsync(id, ignoreQueryFilters: true);
        if (submission == null) return NotFound();

        var user = await _userManager.GetUserAsync(User);

        submission.IsRead         = true;
        submission.ReadAt         = DateTime.UtcNow;
        submission.ReadByUserId   = user?.Id;
        submission.ReadByUserName = user != null ? $"{user.FirstName} {user.LastName}".Trim() : null;
        if (adminNotes != null)
            submission.AdminNotes = adminNotes.Trim();

        await _unitOfWork.CompleteAsync();
        return RedirectToAction(nameof(Submissions));
    }

    // ─── Helpers ─────────────────────────────────────────────────────────────

    /// <summary>
    /// Builds the ContactViewModel pre-filled with the current user's identity and company name.
    /// </summary>
    private async Task<ContactViewModel> BuildViewModelAsync()
    {
        var user = await _userManager.GetUserAsync(User);
        var companyId = _tenantContext.GetCurrentCompanyId();
        var company = companyId.HasValue
            ? await _unitOfWork.Companies.GetByIdAsync(companyId.Value)
            : null;

        return new ContactViewModel
        {
            Form = new ContactFormModel
            {
                Name        = user != null ? $"{user.FirstName} {user.LastName}".Trim() : string.Empty,
                Email       = user?.Email ?? string.Empty,
                CompanyName = company?.CompanyName ?? string.Empty,
            }
        };
    }
}

// ─── View models ─────────────────────────────────────────────────────────────

public class ContactViewModel
{
    public ContactFormModel Form { get; set; } = new();
}

public class ContactFormModel
{
    [Required, MaxLength(150)]
    [Display(Name = "Your Name")]
    public string Name { get; set; } = string.Empty;

    [Required, EmailAddress, MaxLength(200)]
    [Display(Name = "Your Email")]
    public string Email { get; set; } = string.Empty;

    [Required, MaxLength(200)]
    [Display(Name = "Company")]
    public string CompanyName { get; set; } = string.Empty;

    [Required]
    [Display(Name = "Category")]
    public string Category { get; set; } = string.Empty;

    [Required, MaxLength(200)]
    [Display(Name = "Subject")]
    public string Subject { get; set; } = string.Empty;

    [Required, MaxLength(4000)]
    [Display(Name = "Message")]
    public string Message { get; set; } = string.Empty;

    /// <summary>Standard contact reason categories shown in the dropdown.</summary>
    public static readonly string[] Categories =
    [
        "General Question",
        "Technical Issue / Bug",
        "Billing & Subscription",
        "Feature Request",
        "Account Access Issue",
        "Data Import / Migration Help",
        "Training & Onboarding",
        "Other",
    ];
}
