using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using administration.Models.Finances;
using administration.Models;
using User = administration.Models.User;

public class AccountController : Controller
{
    private readonly LayoutDataContext _db;
    private readonly IPasswordHasher<User> _hasher;

    public AccountController(LayoutDataContext db, IPasswordHasher<User> hasher)
    {
        _db = db;
        _hasher = hasher;
    }

    // GET /Account/Login
    [HttpGet]
    public IActionResult Login(string? returnUrl = null)
    {
        ViewBag.ReturnUrl = returnUrl;
        return View();
    }

    // POST /Account/Login
    [HttpPost, ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(string username, string password, string? returnUrl = null)
    {
        if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
        {
            ModelState.AddModelError("", "Identifiants requis.");
            return View();
        }

        var user = await _db.Users.FirstOrDefaultAsync(u => u.Username == username);
        if (user == null)
        {
            ModelState.AddModelError("", "Identifiants invalides.");
            return View();
        }

        var verify = _hasher.VerifyHashedPassword(user, user.PasswordHash, password);
        if (verify == PasswordVerificationResult.Failed)
        {
            ModelState.AddModelError("", "Identifiants invalides.");
            return View();
        }

        // Claims pour cookie d’auth
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
            new Claim(ClaimTypes.Name, user.Username)
        };
        var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
        var principal = new ClaimsPrincipal(identity);

        await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);

        // Compatibilité avec ton code existant
        HttpContext.Session.SetInt32("UserId", user.Id);

        if (!string.IsNullOrWhiteSpace(returnUrl) && Url.IsLocalUrl(returnUrl))
            return Redirect(returnUrl);

        return RedirectToAction("Index", "Home");
    }

    // POST /Account/Logout
    [HttpPost, ValidateAntiForgeryToken]
    public async Task<IActionResult> Logout()
    {
        await HttpContext.SignOutAsync();
        HttpContext.Session.Clear();
        return RedirectToAction("Login");
    }

    // GET /Account/ForgotPassword
    [HttpGet]
    public IActionResult ForgotPassword() => View();

    // POST /Account/ForgotPassword
    [HttpPost, ValidateAntiForgeryToken]
    public async Task<IActionResult> ForgotPassword(string usernameOrEmail)
    {
        if (string.IsNullOrWhiteSpace(usernameOrEmail))
        {
            ModelState.AddModelError("", "Champ requis.");
            return View();
        }

        var user = await _db.Users
            .FirstOrDefaultAsync(u => u.Username == usernameOrEmail);

        // Par sécurité, on ne révèle pas si l’utilisateur existe
        if (user != null)
        {
            // Génère un token simple (tu peux le hasher si tu veux)
            var token = Convert.ToBase64String(Guid.NewGuid().ToByteArray())
                .Replace("+", "-").Replace("/", "_").TrimEnd('=');

            user.ResetToken = token;
            user.ResetTokenExpiresAt = DateTimeOffset.UtcNow.AddHours(1);
            await _db.SaveChangesAsync();

            var resetUrl = Url.Action("ResetPassword", "Account", new { token = token }, Request.Scheme);
            // TODO: envoyer resetUrl par email.
            // Temporaire : on l’affiche
            TempData["ResetLink"] = resetUrl;
        }

        TempData["Info"] = "Si un compte existe, un lien de réinitialisation a été envoyé.";
        return RedirectToAction("ForgotPassword");
    }

    // GET /Account/ResetPassword?token=...
    [HttpGet]
    public async Task<IActionResult> ResetPassword(string token)
    {
        if (string.IsNullOrWhiteSpace(token)) return RedirectToAction("Login");

        var user = await _db.Users.FirstOrDefaultAsync(u =>
            u.ResetToken == token && u.ResetTokenExpiresAt > DateTimeOffset.UtcNow);

        if (user == null)
        {
            TempData["Error"] = "Lien invalide ou expiré.";
            return RedirectToAction("ForgotPassword");
        }

        ViewBag.Token = token;
        return View();
    }

    // POST /Account/ResetPassword
    [HttpPost, ValidateAntiForgeryToken]
    public async Task<IActionResult> ResetPassword(string token, string newPassword, string confirmPassword)
    {
        if (string.IsNullOrWhiteSpace(token))
        {
            TempData["Error"] = "Token manquant.";
            return RedirectToAction("ForgotPassword");
        }
        if (string.IsNullOrWhiteSpace(newPassword) || newPassword != confirmPassword)
        {
            ModelState.AddModelError("", "Les mots de passe ne correspondent pas.");
            ViewBag.Token = token;
            return View();
        }

        var user = await _db.Users.FirstOrDefaultAsync(u =>
            u.ResetToken == token && u.ResetTokenExpiresAt > DateTimeOffset.UtcNow);

        if (user == null)
        {
            TempData["Error"] = "Lien invalide ou expiré.";
            return RedirectToAction("ForgotPassword");
        }

        user.PasswordHash = _hasher.HashPassword(user, newPassword);
        user.ResetToken = null;
        user.ResetTokenExpiresAt = null;
        await _db.SaveChangesAsync();

        TempData["Ok"] = "Mot de passe réinitialisé. Connecte-toi.";
        return RedirectToAction("Login");
    }

    // (Optionnel) création rapide d’un compte admin si tu n’as rien en BDD
    [HttpPost, ValidateAntiForgeryToken]
    public async Task<IActionResult> SeedAdmin(string username = "admin", string password = "ChangeMe!123")
    {
        if (await _db.Users.AnyAsync()) return BadRequest("Déjà des utilisateurs en BDD.");
        var u = new User { Username = username };
        u.PasswordHash = _hasher.HashPassword(u, password);
        _db.Users.Add(u);
        await _db.SaveChangesAsync();
        return Ok("Admin créé.");
    }
}
