using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using SportsDivision.Application.DTOs;
using SportsDivision.Application.Interfaces;
using SportsDivision.Infrastructure.Identity;

namespace SportsDivision.Web.Controllers;

[Authorize(Roles = "Admin")]
public class UserManagementController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly RoleManager<IdentityRole> _roleManager;
    private readonly ISchoolService _schoolService;

    public UserManagementController(
        UserManager<ApplicationUser> userManager,
        RoleManager<IdentityRole> roleManager,
        ISchoolService schoolService)
    {
        _userManager = userManager;
        _roleManager = roleManager;
        _schoolService = schoolService;
    }

    public async Task<IActionResult> Index(string? role, bool? isActive)
    {
        var users = await _userManager.Users.ToListAsync();
        var schools = await _schoolService.GetAllAsync();
        var schoolLookup = schools.ToDictionary(s => s.SchoolId, s => s.Name);

        var userDtos = new List<UserDto>();
        foreach (var user in users)
        {
            var roles = await _userManager.GetRolesAsync(user);
            var dto = new UserDto
            {
                Id = user.Id,
                Email = user.Email ?? string.Empty,
                FirstName = user.FirstName,
                LastName = user.LastName,
                FullName = user.FullName,
                Role = roles.FirstOrDefault() ?? "None",
                SchoolId = user.SchoolId,
                SchoolName = user.SchoolId.HasValue && schoolLookup.TryGetValue(user.SchoolId.Value, out var name) ? name : null,
                IsActive = user.IsActive
            };
            userDtos.Add(dto);
        }

        if (!string.IsNullOrEmpty(role))
        {
            userDtos = userDtos.Where(u => u.Role == role).ToList();
        }

        if (isActive.HasValue)
        {
            userDtos = userDtos.Where(u => u.IsActive == isActive.Value).ToList();
        }

        ViewBag.Roles = await _roleManager.Roles.Select(r => r.Name).ToListAsync();
        ViewBag.SelectedRole = role;
        ViewBag.SelectedIsActive = isActive;

        return View(userDtos);
    }

    [HttpGet]
    public async Task<IActionResult> Create()
    {
        await PopulateDropdowns();
        return View(new UserCreateDto());
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(UserCreateDto dto)
    {
        if (!ModelState.IsValid)
        {
            await PopulateDropdowns();
            return View(dto);
        }

        var user = new ApplicationUser
        {
            UserName = dto.Email,
            Email = dto.Email,
            FirstName = dto.FirstName,
            LastName = dto.LastName,
            SchoolId = dto.SchoolId,
            IsActive = true,
            EmailConfirmed = true
        };

        var result = await _userManager.CreateAsync(user, dto.Password);
        if (!result.Succeeded)
        {
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
            await PopulateDropdowns();
            return View(dto);
        }

        if (!string.IsNullOrEmpty(dto.Role))
        {
            await _userManager.AddToRoleAsync(user, dto.Role);
        }

        TempData["SuccessMessage"] = "User created successfully.";
        return RedirectToAction(nameof(Index));
    }

    [HttpGet]
    public async Task<IActionResult> Edit(string id)
    {
        var user = await _userManager.FindByIdAsync(id);
        if (user == null) return NotFound();

        var roles = await _userManager.GetRolesAsync(user);
        var dto = new UserUpdateDto
        {
            Id = user.Id,
            FirstName = user.FirstName,
            LastName = user.LastName,
            Role = roles.FirstOrDefault() ?? string.Empty,
            SchoolId = user.SchoolId,
            IsActive = user.IsActive
        };

        ViewBag.Email = user.Email;
        await PopulateDropdowns();
        return View(dto);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(UserUpdateDto dto)
    {
        if (!ModelState.IsValid)
        {
            var u = await _userManager.FindByIdAsync(dto.Id);
            ViewBag.Email = u?.Email;
            await PopulateDropdowns();
            return View(dto);
        }

        var user = await _userManager.FindByIdAsync(dto.Id);
        if (user == null) return NotFound();

        user.FirstName = dto.FirstName;
        user.LastName = dto.LastName;
        user.SchoolId = dto.SchoolId;
        user.IsActive = dto.IsActive;

        var updateResult = await _userManager.UpdateAsync(user);
        if (!updateResult.Succeeded)
        {
            foreach (var error in updateResult.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
            ViewBag.Email = user.Email;
            await PopulateDropdowns();
            return View(dto);
        }

        // Update role if changed
        var currentRoles = await _userManager.GetRolesAsync(user);
        var currentRole = currentRoles.FirstOrDefault();
        if (currentRole != dto.Role)
        {
            if (!string.IsNullOrEmpty(currentRole))
            {
                await _userManager.RemoveFromRoleAsync(user, currentRole);
            }
            if (!string.IsNullOrEmpty(dto.Role))
            {
                await _userManager.AddToRoleAsync(user, dto.Role);
            }
        }

        TempData["SuccessMessage"] = "User updated successfully.";
        return RedirectToAction(nameof(Index));
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> ToggleActive(string id)
    {
        var user = await _userManager.FindByIdAsync(id);
        if (user == null) return NotFound();

        user.IsActive = !user.IsActive;
        await _userManager.UpdateAsync(user);

        TempData["SuccessMessage"] = $"User {(user.IsActive ? "activated" : "deactivated")} successfully.";
        return RedirectToAction(nameof(Index));
    }

    [HttpGet]
    public async Task<IActionResult> ResetPassword(string id)
    {
        var user = await _userManager.FindByIdAsync(id);
        if (user == null) return NotFound();

        return View(new ResetPasswordDto
        {
            Id = user.Id,
            Email = user.Email ?? string.Empty,
            FullName = user.FullName
        });
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> ResetPassword(ResetPasswordDto dto)
    {
        var user = await _userManager.FindByIdAsync(dto.Id);
        if (user == null) return NotFound();

        // Keep display fields populated regardless of the posted values.
        dto.Email = user.Email ?? string.Empty;
        dto.FullName = user.FullName;

        if (!ModelState.IsValid)
        {
            return View(dto);
        }

        var token = await _userManager.GeneratePasswordResetTokenAsync(user);
        var result = await _userManager.ResetPasswordAsync(user, token, dto.NewPassword);
        if (!result.Succeeded)
        {
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
            return View(dto);
        }

        TempData["SuccessMessage"] = $"Password reset successfully for {user.Email}.";
        return RedirectToAction(nameof(Index));
    }

    private async Task PopulateDropdowns()
    {
        ViewBag.Roles = await _roleManager.Roles.Select(r => r.Name).ToListAsync();
        ViewBag.Schools = (await _schoolService.GetAllAsync()).Where(s => s.IsActive).ToList();
    }
}
