using Lada.Framework.Data.Domains.Identity;
using Lada.Framework.Data.Repositories;
using Lada.Framework.DTO.SmartTable;
using Ladaer.BackEnd.Infrastructures.DTO.Models.Itentity;
using Ladaer.BackEnd.Infrastructures.DTO.Results.Identity;
using Ladaer.BackEnd.Infrastructures.Extensions;
using Lada.Framework.Data.Domains;
using Lada.Framework.DTO;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;

namespace Ladaer.BackEnd.Infrastructures.Services.Identity
{
    /// <summary>
    /// Service for managing Permission Groups and Role assignments
    /// </summary>
    public class PermissionService : IPermissionService
    {
        private readonly IRepository<Permission> _permissionRepository;
        private readonly IRepository<PermissionRole> _permissionRoleRepository;
        private readonly UserManager<User> _userManager;
        private readonly RoleManager<Role> _roleManager;
        private readonly IUserService _userService;

        public PermissionService(
            IRepository<Permission> permissionRepository,
            IRepository<PermissionRole> permissionRoleRepository,
            UserManager<User> userManager,
            RoleManager<Role> roleManager,
            IUserService userService)
        {
            _permissionRepository = permissionRepository;
            _permissionRoleRepository = permissionRoleRepository;
            _userManager = userManager;
            _roleManager = roleManager;
            _userService = userService;
        }

        public async Task<Permission> CreatePermissionAsync(string name, string? description, List<int> roleIds)
        {
            var permission = new Permission
            {
                Name = name,
                Description = description,
                IsActive = true,
                CreatedTime = DateTimeOffset.UtcNow,
                UpdatedTime = DateTimeOffset.UtcNow
            };

            await _permissionRepository.InsertAsync(permission);

            // Thêm các Role vào Permission
            foreach (var roleId in roleIds)
            {
                var permissionRole = new PermissionRole
                {
                    PermissionId = permission.Id,
                    RoleId = roleId,
                    CreatedTime = DateTimeOffset.UtcNow,
                    UpdatedTime = DateTimeOffset.UtcNow
                };
                await _permissionRoleRepository.InsertAsync(permissionRole);
            }

            return permission;
        }

        public async Task<Permission?> UpdatePermissionAsync(int permissionId, string name, string? description, List<int> roleIds)
        {
            var permission = await _permissionRepository.GetByIdAsync(permissionId);
            if (permission == null) return null;

            permission.Name = name;
            permission.Description = description;
            permission.UpdatedTime = DateTimeOffset.UtcNow;

            await _permissionRepository.UpdateAsync(permission);

            // Xóa tất cả PermissionRole cũ
            var existingPermissionRoles = _permissionRoleRepository.Query()
                .Where(pr => pr.PermissionId == permissionId);

            foreach (var pr in existingPermissionRoles)
            {
                await _permissionRoleRepository.DeleteAsync(pr);
            }

            // Thêm PermissionRole mới
            foreach (var roleId in roleIds)
            {
                var permissionRole = new PermissionRole
                {
                    PermissionId = permissionId,
                    RoleId = roleId,
                    CreatedTime = DateTimeOffset.UtcNow,
                    UpdatedTime = DateTimeOffset.UtcNow
                };
                await _permissionRoleRepository.InsertAsync(permissionRole);
            }

            return permission;
        }

        public async Task<bool> DeletePermissionAsync(int permissionId)
        {
            var permission = await _permissionRepository.GetByIdAsync(permissionId);
            if (permission == null) return false;

            // Xóa tất cả User có PermissionId này
            var users = _userManager.Users.Where(u => u.PermissionId == permissionId);
            foreach (var user in users)
            {
                await RemovePermissionFromUserAsync(user.Id);
            }

            // Xóa tất cả PermissionRole
            var permissionRoles = _permissionRoleRepository.Query()
                .Where(pr => pr.PermissionId == permissionId);

            foreach (var pr in permissionRoles)
            {
                await _permissionRoleRepository.DeleteAsync(pr);
            }

            // Xóa Permission
            await _permissionRepository.DeleteAsync(permission);
            return true;
        }

        public async Task<BaseResult> AssignPermissionToUserAsync(int userId, int permissionId)
        {
            var user = await _userManager.FindByIdAsync(userId.ToString());
            var result = new BaseResult();
            if (user == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy người dùng yêu cầu";
            }

            var permission = await _permissionRepository.GetByIdAsync(permissionId);
            if (permission == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy vai trò dùng yêu cầu";
            }
            // Xóa tất cả UserRole hiện tại
            var currentRoles = await _userManager.GetRolesAsync(user);
            if (currentRoles.Any())
            {
                await _userManager.RemoveFromRolesAsync(user, currentRoles);
            }

            // Cập nhật PermissionId cho User
            user.PermissionId = permissionId;
            await _userManager.UpdateAsync(user);

            // Thêm các Role từ Permission vào UserRole
            var roleIds = _permissionRoleRepository.Query()
                .Where(pr => pr.PermissionId == permissionId)
                .Select(pr => pr.RoleId)
                .ToList();

            foreach (var roleId in roleIds)
            {
                var role = await _roleManager.FindByIdAsync(roleId.ToString());
                if (role != null)
                {
                    await _userManager.AddToRoleAsync(user, role.Name!);
                }
            }

            return result;
        }

        public async Task<bool> RemovePermissionFromUserAsync(int userId)
        {
            var user = await _userManager.FindByIdAsync(userId.ToString());
            if (user == null) return false;

            // Xóa tất cả UserRole
            var currentRoles = await _userManager.GetRolesAsync(user);
            if (currentRoles.Any())
            {
                await _userManager.RemoveFromRolesAsync(user, currentRoles);
            }

            // Xóa PermissionId
            user.PermissionId = null;
            await _userManager.UpdateAsync(user);

            return true;
        }

        public async Task<List<Permission>> GetAllPermissionsAsync()
        {
            return await _permissionRepository.Query()
                .Where(p => p.IsActive)
                .OrderBy(p => p.Name)
                .ToListAsync();
        }

        public async Task<Permission?> GetPermissionByIdAsync(int permissionId)
        {
            return await _permissionRepository.GetByIdAsync(permissionId);
        }

        public async Task<List<Role>> GetRolesInPermissionAsync(int permissionId)
        {
            var roleIds = await _permissionRoleRepository.Query()
                .Where(pr => pr.PermissionId == permissionId)
                .Select(pr => pr.RoleId)
                .ToListAsync();

            var roles = new List<Role>();
            foreach (var roleId in roleIds)
            {
                var role = await _roleManager.FindByIdAsync(roleId.ToString());
                if (role != null)
                {
                    roles.Add(role);
                }
            }

            return roles;
        }

        public async Task<bool> UserHasRoleAsync(int userId, string roleName)
        {

            var user = await _userManager.FindByIdAsync(userId.ToString());

            if (user == null) return false;

            var hasRole = await _userManager.IsInRoleAsync(user, roleName);
            if (!hasRole)
            {
                if (!user.PermissionId.HasValue) return false;
                return await _permissionRoleRepository.Query().AnyAsync(pr => pr.Role.Name == roleName && pr.PermissionId == user.PermissionId.Value);
            }
            return true;
            
        }

        public async Task<SmartTableResult<Permission>> SearchAsync(SmartTableParam param)
        {
            var query = _permissionRepository.Query().Where(p => p.IsActive);

            // Tìm kiếm theo tên
            if (param.Search?.PredicateObject != null)
            {
                dynamic search = param.Search.PredicateObject;
                if (search.Keyword != null)
                {
                    string keyword = search.Keyword;
                    keyword = keyword.Trim();
                    if (!string.IsNullOrWhiteSpace(keyword))
                    {
                        query = query.Where(p => p.Name.Contains(keyword) ||
                                                (p.Description != null && p.Description.Contains(keyword)));
                    }
                }
            }

            // Sắp xếp mặc định
            param.Sort ??= new Sort { Predicate = "Name", Reverse = false };

            var gridData = await query.ToSmartTableResultAsync(param, x => x);
            return gridData;
        }

        public async Task<List<Role>> GetAllAvailableRolesAsync()
        {
            return await _roleManager.Roles
                .Where(r => r.Name != null)
                .OrderBy(r => r.Name)
                .ToListAsync();
        }

        #region CreateOrUpdate Pattern (theo AgencyController)

        public async Task<PermissionResult> CreateOrUpdate(PermissionModel model)
        {
            var permission = model.ToEntity();

            // Cập nhật thông tin chung của thực thể
            permission = permission.UpdateCommonInt(model.UpdatedBy, model.UpdatedByUserName);

            if (permission.Id > 0)
            {
                // Cập nhật
                return await Update(permission);
            }
            else
            {
                // Thêm mới
                return await Create(permission);
            }
        }

        private async Task<PermissionResult> Create(Permission permission)
        {
            var result = new PermissionResult();
            try
            {
                await _permissionRepository.InsertAsync(permission);
                result.Id = permission.Id;
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
                result.Id = 0;
            }
            return result;
        }

        private async Task<PermissionResult> Update(Permission permission)
        {
            var result = new PermissionResult();
            var permissionForUpdate = await _permissionRepository.GetByIdAsync(permission.Id);

            if (permissionForUpdate == null)
            {
                result.Result = Result.Failed;
                result.Message = "Không tìm thấy Permission";
                return result;
            }

            try
            {
                permissionForUpdate.Name = permission.Name;
                permissionForUpdate.Description = permission.Description;
                permissionForUpdate.IsActive = permission.IsActive;

                // Cập nhật thông tin chung của thực thể
                permissionForUpdate = permissionForUpdate.UpdateCommonInt();

                await _permissionRepository.UpdateAsync(permissionForUpdate);
                result.Id = permissionForUpdate.Id;
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
                result.Id = 0;
            }
            return result;
        }

        public async Task<PermissionModel> GetById(int id)
        {
            var permission = await _permissionRepository.GetByIdAsync(id);
            if (permission == null)
            {
                return new PermissionModel();
            }

            var model = permission.ToModel();

            // Lấy danh sách Role IDs cho Permission này
            var roleIds = await _permissionRoleRepository.Query()
                .Where(pr => pr.PermissionId == id)
                .Select(pr => pr.RoleId)
                .ToListAsync();

            model.RoleIds = roleIds;
            return model;
        }

        #endregion

        #region Update Permission Roles (hàm riêng biệt)

        public async Task<PermissionResult> UpdatePermissionRoles(PermissionRoleModel model)
        {
            var result = new PermissionResult();

            try
            {
                var permission = await _permissionRepository.GetByIdAsync(model.Id);
                if (permission == null)
                {
                    result.Result = Result.Failed;
                    result.Message = "Không tìm thấy Permission";
                    return result;
                }

                // Xóa tất cả PermissionRole cũ
                var existingPermissionRoles = _permissionRoleRepository.Query()
                    .Where(pr => pr.PermissionId == model.Id);

                if (existingPermissionRoles.Any()) await _permissionRoleRepository.RemoveAsync(existingPermissionRoles);

                // Thêm các PermissionRole mới
                var permissionRoles = new List<PermissionRole>();

                foreach (var roleId in model.RoleIds)
                {
                    permissionRoles.Add(new PermissionRole
                    {
                        PermissionId = model.Id,
                        RoleId = roleId,
                        CreatedTime = DateTimeOffset.UtcNow,
                        UpdatedTime = DateTimeOffset.UtcNow
                    });

                }
                if (permissionRoles.Any())
                {
                    await _permissionRoleRepository.InsertAsync(permissionRoles);
                }

                // Không cần cập nhật UserRole vì roles giờ được lấy trực tiếp từ PermissionRole
                // User sẽ tự động có roles mới ở lần login tiếp theo

                result.Id = model.Id;
                result.Message = "Cập nhật Role cho Permission thành công";
            }
            catch (Exception e)
            {
                result.Result = Result.SystemError;
                result.Message = e.ToString();
                result.Id = 0;
            }

            return result;
        }

        #endregion
    }
}
