using Microsoft.AspNetCore.Mvc;
using Berufsschule_HAM.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Security.Claims;
using Berufsschule_HAM.Services;
using ElmahCore;
using Berufsschule_HAM.Exceptions;
using Microsoft.AspNetCore.Authorization;

[ApiExplorerSettings(IgnoreApi = true)]
[Route("[controller]")]
public class HomeController : Controller
{
    private readonly LdapService _ldap;

    public HomeController(LdapService ldap)
    {
        _ldap = ldap ?? throw new ArgumentNullException(nameof(ldap));
    }

    [Authorize]
    [HttpGet("Index")]
    [HttpGet("/")]
    public ActionResult Index()
    {
        return View();
    }

    [HttpGet("Assets")]
    public async Task<IActionResult> Assets()
    {
        IEnumerable<UserModel> users = await _ldap.ListUsersAsync();
        IEnumerable<AssetModel> assets = await _ldap.ListDeviceAsync();
        IEnumerable<LocationModel> locations = await _ldap.ListLocationsAsync();
        List<AssetsTableViewModel> assetsTableViewModels = [];
        foreach (AssetModel asset in assets)
        {
            assetsTableViewModels.Add(new()
            {
                AssetCn = asset.Cn,
                AssetName = asset.Name,
                LocationName = asset.Location,
                UserUID = asset.Owner?.Split('=')[1],
            });
        }
        return View(new HomeIndexViewModel() { AssetsTableViewModels = assetsTableViewModels });
    }

    [HttpGet("Inventory")]
    public ActionResult Inventory()
    {
        return View();
    }

    [HttpGet("Locations")]
    public ActionResult Locations()
    {
        return View();
    }

    [HttpGet("Users")]
    public ActionResult Users()
    {
        return View();
    }

    [HttpPost("Login")]
    public async Task<ActionResult> Login(string username, string password)
    {
        var authenticationResult = await _ldap.AuthenticateUser(username, password);
        if (authenticationResult.Success)
        {
            List<Claim> claims =
            [
                new(ClaimTypes.Name, username)
            ];

            var claimsIdentity = new ClaimsIdentity(
                claims,
                CookieAuthenticationDefaults.AuthenticationScheme);

            var authProperties = new AuthenticationProperties
            {
                IsPersistent = true,
                ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(300)
            };

            await HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme,
                new ClaimsPrincipal(claimsIdentity),
                authProperties);

            return RedirectToAction("Index", "Home");
        }
        switch (authenticationResult.AuthenticationState)
        {
            case UserNotAuthenticatedReason.InvalidCredentials:
                return View(new LoginViewModel() { ErrorText = "Invalid login credentials" }); // TODO add localization (e.g. T["Invalid login credentials"]; see: https://learn.microsoft.com/de-de/dotnet/core/extensions/localization)
            case UserNotAuthenticatedReason.UserLockedOut:
                return View(new LoginViewModel() { ErrorText = "Your account has been locked. Wait a few minutes or ask an administrator to unlock you" }); // TODO add localization (e.g. T["Invalid login credentials"]; see: https://learn.microsoft.com/de-de/dotnet/core/extensions/localization)
            case UserNotAuthenticatedReason.UserNotAuthorized:
                return View(new LoginViewModel() { ErrorText = "You are not authorized for login. Ask an administrator to authorize you." }); // TODO add localization (e.g. T["Invalid login credentials"]; see: https://learn.microsoft.com/de-de/dotnet/core/extensions/localization)
            default:
                await HttpContext.RaiseError(new HellFrozeOverException());
                return View(new LoginViewModel() { ErrorText = "Hell froze over. Make a screenshot and send it to an administrator." }); // TODO add localization (e.g. T["Invalid login credentials"]; see: https://learn.microsoft.com/de-de/dotnet/core/extensions/localization)
        }
    }

    [HttpGet("Login")]
    public ActionResult Login()
    {
        return View(new LoginViewModel());
    }

    [HttpGet("Logout")]
    public ActionResult Logout()
    {
        HttpContext.SignOutAsync();
        return RedirectToAction("Index", "Home");
    }

    [HttpGet("AccessDenied")]
    public ActionResult AccessDenied()
    {
        return View();
    }
}