using LSFE.Domain.Contracts;
using LSFE.Infrastructure.Database;
using LSFE.Infrastructure.Dto.Account;
using LSFE.Infrastructure.Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using System.Data;

namespace LSFE.Domain.Services.Account
{
    public class NavigationService : INavigationService
    {
        private readonly LSFEDbContext _context;
        private readonly UserManager<AppsUsers> _userManager;

        public NavigationService(LSFEDbContext context, UserManager<AppsUsers> userManager)
        {
            _context = context;
            _userManager = userManager;
        }

        public async Task<NavigationResponseDto> GetUserNavigationAsync(string userId)
        {
            try
            {
                var user = await _userManager.FindByIdAsync(userId);

                if (user == null)
                {
                    return new NavigationResponseDto
                    {
                        Success = false,
                        Message = "User not found or inactive",
                        Data = new List<NavigationItemDto>()
                    };
                }

                // Get user roles using UserManager
                var roles = await _userManager.GetRolesAsync(user);

                if (!roles.Any())
                {
                    return new NavigationResponseDto
                    {
                        Success = false,
                        Message = "User has no assigned roles",
                        Data = new List<NavigationItemDto>()
                    };
                }

                // Get role IDs from role names
                var roleIds = await _context.Roles
                    .Where(r => roles.Contains(r.Name))
                    .Select(r => r.Id)
                    .ToListAsync();

                // Get navigation for all user roles
                var navigationItems = await GetNavigationByRoleIdsAsync(roleIds);

                return new NavigationResponseDto
                {
                    Success = true,
                    Data = navigationItems,
                    Message = "Navigation retrieved successfully"
                };
            }
            catch (Exception ex)
            {
                return new NavigationResponseDto
                {
                    Success = false,
                    Message = $"Error retrieving navigation: {ex.Message}",
                    Data = new List<NavigationItemDto>()
                };
            }
        }

        public async Task<List<NavigationItemDto>> GetNavigationByRoleIdsAsync(List<string> roleIds)
        {
            try
            {
                var roleIdsParam = string.Join(",", roleIds);

                using (var command = _context.Database.GetDbConnection().CreateCommand())
                {
                    command.CommandText = "GetUserNavigation";
                    command.CommandType = CommandType.StoredProcedure;
                    command.Parameters.Add(new SqlParameter("@RoleIds", roleIdsParam));

                    await _context.Database.OpenConnectionAsync();

                    using (var result = await command.ExecuteReaderAsync())
                    {
                        var rootModules = new List<NavigationItemDto>();
                        var childModules = new List<NavigationItemDto>();

                        // Read root modules
                        while (await result.ReadAsync())
                        {
                            rootModules.Add(new NavigationItemDto
                            {
                                Id = result["Id"].ToString(),
                                Label = result["Label"].ToString(),
                                Icon = result["Icon"].ToString(),
                                Route = result["Route"].ToString(),
                                Badge = result["Badge"]?.ToString(),
                                Permissions = new PermissionsDto
                                {
                                    CanView = Convert.ToBoolean(result["CanView"]),
                                    CanCreate = Convert.ToBoolean(result["CanCreate"]),
                                    CanEdit = Convert.ToBoolean(result["CanEdit"]),
                                    CanDelete = Convert.ToBoolean(result["CanDelete"])
                                },
                                Children = new List<NavigationItemDto>()
                            });
                        }

                        // Read child modules
                        if (await result.NextResultAsync())
                        {
                            while (await result.ReadAsync())
                            {
                                childModules.Add(new NavigationItemDto
                                {
                                    Id = result["Id"].ToString(),
                                    Label = result["Label"].ToString(),
                                    Icon = result["Icon"].ToString(),
                                    Route = result["Route"].ToString(),
                                    ParentModuleId = result["ParentModuleId"] != DBNull.Value
                                        ? Convert.ToInt32(result["ParentModuleId"])
                                        : (int?)null,
                                    Permissions = new PermissionsDto
                                    {
                                        CanView = Convert.ToBoolean(result["CanView"]),
                                        CanCreate = Convert.ToBoolean(result["CanCreate"]),
                                        CanEdit = Convert.ToBoolean(result["CanEdit"]),
                                        CanDelete = Convert.ToBoolean(result["CanDelete"])
                                    }
                                });
                            }
                        }

                        // Attach children to parents
                        foreach (var parent in rootModules)
                        {
                            var children = childModules
                                .Where(c => c.ParentModuleId.ToString() == parent.Id)
                                .ToList();

                            parent.Children = children.Any() ? children : null;
                        }

                        return rootModules;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error in GetNavigationByRoleIdsAsync: {ex.Message}");
                throw;
            }
        }
        // Optional: Add method to get single role navigation (for backwards compatibility)
        public async Task<List<NavigationItemDto>> GetNavigationByRoleAsync(string roleId)
        {
            return await GetNavigationByRoleIdsAsync(new List<string> { roleId });
        }
    }
}