using FamilyBudget.Data;
using FamilyBudget.Models;
using FamilyBudget.ViewModels;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace FamilyBudget.Controllers
{
    public class DepenseController : Controller
    {
        //public IActionResult depense()
        //{
        //    return View();
        //}

        private readonly ApplicationDbContext _context;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public DepenseController(ApplicationDbContext context, IHttpContextAccessor httpContextAccessor)
        {
            _context = context;
            _httpContextAccessor = httpContextAccessor;
        }

        public async Task<IActionResult> depense()
        {
            var idUtilisateur = HttpContext.Session.GetInt32("IdUtilisateur");
            var depenses = _context.Depenses.Include(d => d.IdBudgetNavigation)
                                            .Where(d => d.Compte.IdUtilisateur == idUtilisateur)
                                            //.Include(d => d.IdFactureNavigation)
                                            .Include(d => d.IdUtilisateurNavigation);
            return View(await depenses.ToListAsync());
        }


        public async Task<IActionResult> Details(int? id)
        {
            if (id == null)
                return NotFound();

            var depense = await _context.Depenses
                .Include(d => d.IdBudgetNavigation)
                //.Include(d => d.IdFactureNavigation)
                .Include(d => d.IdUtilisateurNavigation)
                .Include(d => d.Compte)
                .FirstOrDefaultAsync(m => m.IdDepenses == id);

            if (depense == null)
                return NotFound();

            return View(depense);
        }

        public async Task<IActionResult> DetailAll()
        {
            var idUtilisateur = HttpContext.Session.GetInt32("IdUtilisateur");
            var depense = await _context.Depenses
                .Include(d => d.IdBudgetNavigation)
                .Include(d => d.IdUtilisateurNavigation)
                .Where(d => d.IdUtilisateurNavigation.IdUtilisateur == idUtilisateur)
                .Include(d => d.Compte)
                .ToListAsync();
            var facture = await _context.Factures.Where(d => d.Compte.IdUtilisateurNavigation.IdUtilisateur == idUtilisateur).Include(d => d.Compte).ToListAsync();

            if (depense == null && facture == null)
                return NotFound();

            var viewModel = new DepenseFactureViewModel
            {
                Depenses = depense,
                Factures = facture
            };

            return View(viewModel);
        }

        public IActionResult Create()
        {
            var idUtilisateur = HttpContext.Session.GetInt32("IdUtilisateur");
            //ViewData["IdFacture"] = new SelectList(_context.Factures, "IdFacture", "CategorieFacture");
            ViewData["IdBudget"] = new SelectList(_context.Bugdets
                .Where(c => c.IdUtilisateur == idUtilisateur.Value)
                , "IdBudget", "Categorie");
            ViewData["IdCompte"] = new SelectList(_context.Comptes
                                                            .Where(c => c.IdUtilisateur == idUtilisateur.Value),
                                                             "IdCompte", "Type");
            //prouving
            
            if (idUtilisateur != 0)
            {
                var utilisateur = _context.Utilisateurs
                                          .Where(u => u.IdUtilisateur == idUtilisateur)
                                          .ToList();

                ViewData["IdUtilisateur"] = new SelectList(utilisateur, "IdUtilisateur", "Nom");
            }
            else
            {
                TempData["ErreurUtilisateur"] = "Utilisateur non connecté ou ID non trouvé.";
                ViewData["IdUtilisateur"] = new SelectList(new List<Utilisateur>(), "IdUtilisateur", "Nom");
            }
            //ViewData["IdUtilisateur"] = new SelectList(_context.Utilisateurs, "IdUtilisateur", "Nom");
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("IdUtilisateur,IdCompte,IdBudget,Montant,DateDepense")] Depense depense)  //,IdFacture,Nom,Type
        {
            if (ModelState.IsValid)
            {
                try
                {
                    _context.Add(depense);

                    var idUtilisateur = HttpContext.Session.GetInt32("IdUtilisateur");
                    // Mise à jour du solde du compte
                    var compte = await _context.Comptes.FindAsync(depense.IdCompte);
                    if (compte != null)
                    {
                        if (compte.Solde < depense.Montant)
                        {
                            ViewBag.Message = "Le solde de votre compte est Insuffisant";
                            return View();
                        }
                        else
                        {
                            compte.Solde -= depense.Montant; // On soustrait le montant de la dépense
                            _context.Update(compte);
                        }

                    }

                    // Mise à jour du budget
                    var budget = await _context.Bugdets.FindAsync(depense.IdBudget);
                    if (budget != null)
                    {
                        if (budget.MontantAlloue < depense.Montant)
                        {
                            budget.MontantAlloue -= depense.Montant;
                            _context.Update(budget);
                        }
                        else
                        {
                            budget.MontantAlloue -= depense.Montant;
                            _context.Update(budget);
                        }
                    }

                    await _context.SaveChangesAsync();
                    return RedirectToAction("Depense", "depense");
                }
                catch (DbUpdateException ex)
                {
                    // Vérifier si l'erreur vient du trigger SQL
                    if (ex.InnerException is SqlException sqlEx) // Code d'erreur du THROW SQL Server
                    {
                        ModelState.AddModelError("", sqlEx.Message);
                    }
                    else
                    {
                        ModelState.AddModelError("", "Une erreur s'est produite lors de l'ajout de la depense.");
                    }
                }
                
            }
            return View(depense);
        }

        public async Task<IActionResult> Edit(int? id)
        {
            var idUtilisateur = HttpContext.Session.GetInt32("IdUtilisateur");
            if (id == null)
                return NotFound();

            var depense = await _context.Depenses.FindAsync(id);
            if (depense == null)
                return NotFound();

            ViewData["IdBudget"] = new SelectList(_context.Bugdets.Where(c => c.IdUtilisateur == idUtilisateur.Value), "IdBudget", "Categorie");
            //ViewData["IdFacture"] = new SelectList(_context.Factures, "IdFacture", "CategorieFacture");
            ViewData["IdCompte"] = new SelectList(_context.Comptes.Where(c => c.IdUtilisateur == idUtilisateur.Value),
                                                             "IdCompte", "Type");
            //prouving
           
            if (idUtilisateur != 0)
            {
                var utilisateur = _context.Utilisateurs
                                          .Where(u => u.IdUtilisateur == idUtilisateur)
                                          .ToList();

                ViewData["IdUtilisateur"] = new SelectList(utilisateur, "IdUtilisateur", "Nom");
            }
            else
            {
                TempData["ErreurUtilisateur"] = "Utilisateur non connecté ou ID non trouvé.";
                ViewData["IdUtilisateur"] = new SelectList(new List<Utilisateur>(), "IdUtilisateur", "Nom");
            }
            //ViewData["IdUtilisateur"] = new SelectList(_context.Utilisateurs, "IdUtilisateur", "Nom");
            return View(depense);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("IdDepenses,IdCompte,IdUtilisateur,IdBudget,Montant,DateDepense")] Depense depense) //,IdFacture,Nom,,Type
        {
            if (id != depense.IdDepenses)
                return NotFound();

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(depense);

                    var compte = await _context.Comptes.FindAsync(depense.IdCompte);
                    if (compte != null)
                    {
                        if (compte.Solde < depense.Montant)
                        {
                            ViewBag.Message = "Le solde de votre compte est Insuffisant";
                            return View();
                        }
                        else
                        {
                            compte.Solde -= depense.Montant; // On soustrait le montant de la dépense
                            _context.Update(compte);
                        }

                    }

                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!_context.Depenses.Any(e => e.IdDepenses == depense.IdDepenses))
                        ModelState.AddModelError("", "Une erreur s'est produite lors de l'dition de la depense.");
                    else
                        throw;
                }
                return RedirectToAction("Depense", "depense");
            }
            return View(depense);
        }

        public async Task<IActionResult> Delete(int? id)
        {
            if (id == null)
                return NotFound();

            var depense = await _context.Depenses
                .Include(d => d.IdBudgetNavigation)
                //.Include(d => d.IdFactureNavigation)
                .Include(d => d.IdUtilisateurNavigation)
                .Include(d => d.Compte)
                .FirstOrDefaultAsync(m => m.IdDepenses == id);

            if (depense == null)
                return NotFound();

            return View(depense);
        }

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            var depense = await _context.Depenses.FindAsync(id);
            try
            {
                if (depense != null)
                {
                    var compte = await _context.Comptes.FindAsync(depense.IdCompte);
                    if (compte != null)
                    {
                        compte.Solde += depense.Montant; // On restitue le montant au compte
                        _context.Update(compte);
                    }

                    var budget = await _context.Bugdets.FindAsync(depense.IdBudget);
                    if (budget != null)
                    {
                        budget.MontantAlloue += depense.Montant; // On restitue le montant au budget
                        _context.Update(budget);
                    }

                    _context.Depenses.Remove(depense);
                    await _context.SaveChangesAsync();
                    return RedirectToAction("Depense", "depense");
                }
            }
            catch (DbUpdateException ex)
            {
                // Vérifier si l'erreur vient du trigger SQL
                if (ex.InnerException is SqlException sqlEx) // Code d'erreur du THROW SQL Server
                {
                    ModelState.AddModelError("", sqlEx.Message);
                }
                else
                {
                    ModelState.AddModelError("", "Une erreur s'est produite lors de l'ajout du livre.");
                }
            }

            return View(depense);
        }
    }
}
