using MemberCenter.Application.Abstractions;
using MemberCenter.Application.Constants;
using MemberCenter.Application.Models.Admin;
using MemberCenter.Infrastructure.Identity;
using MemberCenter.Web.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Net.Mail;

namespace MemberCenter.Web.Areas.Admin.Controllers;

[Area("Admin")]
[Authorize(Policy = "Admin")]
[AdminPermission(AdminPermissions.Security)]
[Route("admin/security")]
public class SecurityController : Controller
{
    private readonly ISecuritySettingsService _settingsService;
    private readonly UserManager<ApplicationUser> _userManager;

    public SecurityController(ISecuritySettingsService settingsService, UserManager<ApplicationUser> userManager)
    {
        _settingsService = settingsService;
        _userManager = userManager;
    }

    [HttpGet("")]
    [AdminPermission(AdminPermissions.SecurityIndex)]
    public async Task<IActionResult> Index()
    {
        var settings = await _settingsService.GetAsync();
        return View(settings);
    }

    [HttpPost("")]
    [AdminPermission(AdminPermissions.SecuritySave)]
    public async Task<IActionResult> Save(SecuritySettingsDto model)
    {
        if (!ModelState.IsValid)
        {
            return View("Index", model);
        }

        try
        {
            await _settingsService.SaveAsync(model, await GetCurrentUserIdAsync());
            var saved = await _settingsService.GetAsync();
            ViewData["Result"] = "Saved";
            return View("Index", saved);
        }
        catch (InvalidOperationException ex)
        {
            ModelState.AddModelError(string.Empty, ex.Message);
            return View("Index", model);
        }
    }

    [HttpPost("test-email")]
    [AdminPermission(AdminPermissions.SecurityTestEmail)]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> TestEmail(SecuritySettingsDto model)
    {
        if (string.IsNullOrWhiteSpace(model.TestToEmail))
        {
            ModelState.AddModelError(nameof(model.TestToEmail), "Test recipient email is required.");
            return View("Index", model);
        }

        try
        {
            _ = new MailAddress(model.TestToEmail);
        }
        catch
        {
            ModelState.AddModelError(nameof(model.TestToEmail), "Test recipient email is invalid.");
            return View("Index", model);
        }

        try
        {
            var actorUserId = await GetCurrentUserIdAsync();
            await _settingsService.SaveAsync(model, actorUserId);
            var sentCount = await _settingsService.SendTestEmailAsync(model.TestToEmail, actorUserId);
            var saved = await _settingsService.GetAsync() with { TestToEmail = model.TestToEmail };
            ViewData["Result"] = $"SMTP accepted request (sent_count={sentCount}) to {model.TestToEmail}.";
            return View("Index", saved);
        }
        catch (Exception ex)
        {
            ModelState.AddModelError(string.Empty, $"Test email failed: {ex.Message}");
            return View("Index", model);
        }
    }

    private async Task<Guid?> GetCurrentUserIdAsync()
    {
        var user = await _userManager.GetUserAsync(User);
        return user?.Id;
    }
}
