using System;
using System.Collections.Generic;
using System.Linq;
using CNCSystem.Data.Entities;
using Haoliang.Data;
using Haoliang.Data.Entities;
using CNCSystem.Models.User;

namespace CNCSystem.Data.Repositories
{
    public class UserRepository
    {
        private readonly CNCBusinessDbContext _context;

        public UserRepository(CNCBusinessDbContext context)
        {
            _context = context;
        }

        public List<User> GetAllUsers()
        {
            return _context.Users
                .Include(u => u.Role)
                .ToList();
        }

        public User GetUserById(int id)
        {
            return _context.Users
                .Include(u => u.Role)
                .FirstOrDefault(u => u.Id == id);
        }

        public User GetUserByUsername(string username)
        {
            return _context.Users
                .Include(u => u.Role)
                .FirstOrDefault(u => u.Username == username);
        }

        public User CreateUser(User user)
        {
            user.CreatedAt = DateTime.Now;
            user.UpdatedAt = DateTime.Now;
            
            // 加密密码
            user.PasswordHash = HashPassword(user.PasswordHash);
            
            _context.Users.Add(user);
            _context.SaveChanges();
            return user;
        }

        public User UpdateUser(User user)
        {
            user.UpdatedAt = DateTime.Now;
            
            // 如果密码有更新，重新加密
            if (!string.IsNullOrEmpty(user.PasswordHash))
            {
                user.PasswordHash = HashPassword(user.PasswordHash);
            }
            
            _context.Entry(user).State = System.Data.Entity.EntityState.Modified;
            _context.SaveChanges();
            return user;
        }

        public void DeleteUser(int id)
        {
            var user = _context.Users.Find(id);
            if (user != null)
            {
                _context.Users.Remove(user);
                _context.SaveChanges();
            }
        }

        public User AuthenticateUser(string username, string password)
        {
            var user = _context.Users
                .Include(u => u.Role)
                .FirstOrDefault(u => u.Username == username && u.IsActive);

            if (user != null && VerifyPassword(password, user.PasswordHash))
            {
                user.LastLoginTime = DateTime.Now;
                _context.SaveChanges();
                return user;
            }

            return null;
        }

        public bool IsUsernameExists(string username, int? excludeId = null)
        {
            var query = _context.Users.Where(u => u.Username == username);
            
            if (excludeId.HasValue)
            {
                query = query.Where(u => u.Id != excludeId.Value);
            }
            
            return query.Any();
        }

        private string HashPassword(string password)
        {
            // 使用BCrypt进行密码哈希
            return BCrypt.Net.BCrypt.HashPassword(password);
        }

        private bool VerifyPassword(string password, string hash)
        {
            return BCrypt.Net.BCrypt.Verify(password, hash);
        }
    }

    public class RoleRepository
    {
        private readonly CNCBusinessDbContext _context;

        public RoleRepository(CNCBusinessDbContext context)
        {
            _context = context;
        }

        public List<Role> GetAllRoles()
        {
            return _context.Roles.ToList();
        }

        public Role GetRoleById(int id)
        {
            return _context.Roles.FirstOrDefault(r => r.Id == id);
        }

        public Role GetRoleByName(string roleName)
        {
            return _context.Roles.FirstOrDefault(r => r.RoleName == roleName);
        }

        public Role CreateRole(Role role)
        {
            role.CreatedAt = DateTime.Now;
            role.UpdatedAt = DateTime.Now;
            _context.Roles.Add(role);
            _context.SaveChanges();
            return role;
        }

        public Role UpdateRole(Role role)
        {
            role.UpdatedAt = DateTime.Now;
            _context.Entry(role).State = System.Data.Entity.EntityState.Modified;
            _context.SaveChanges();
            return role;
        }

        public void DeleteRole(int id)
        {
            var role = _context.Roles.Find(id);
            if (role != null)
            {
                _context.Roles.Remove(role);
                _context.SaveChanges();
            }
        }

        public bool IsRoleNameExists(string roleName, int? excludeId = null)
        {
            var query = _context.Roles.Where(r => r.RoleName == roleName);
            
            if (excludeId.HasValue)
            {
                query = query.Where(r => r.Id != excludeId.Value);
            }
            
            return query.Any();
        }
    }

    public class EmployeeRepository
    {
        private readonly CNCBusinessDbContext _context;

        public EmployeeRepository(CNCBusinessDbContext context)
        {
            _context = context;
        }

        public List<Employee> GetAllEmployees()
        {
            return _context.Employees.ToList();
        }

        public Employee GetEmployeeById(int id)
        {
            return _context.Employees.FirstOrDefault(e => e.Id == id);
        }

        public Employee GetEmployeeByCode(string employeeCode)
        {
            return _context.Employees.FirstOrDefault(e => e.EmployeeCode == employeeCode);
        }

        public Employee CreateEmployee(Employee employee)
        {
            employee.CreatedAt = DateTime.Now;
            employee.UpdatedAt = DateTime.Now;
            _context.Employees.Add(employee);
            _context.SaveChanges();
            return employee;
        }

        public Employee UpdateEmployee(Employee employee)
        {
            employee.UpdatedAt = DateTime.Now;
            _context.Entry(employee).State = System.Data.Entity.EntityState.Modified;
            _context.SaveChanges();
            return employee;
        }

        public void DeleteEmployee(int id)
        {
            var employee = _context.Employees.Find(id);
            if (employee != null)
            {
                _context.Employees.Remove(employee);
                _context.SaveChanges();
            }
        }

        public bool IsEmployeeCodeExists(string employeeCode, int? excludeId = null)
        {
            var query = _context.Employees.Where(e => e.EmployeeCode == employeeCode);
            
            if (excludeId.HasValue)
            {
                query = query.Where(e => e.Id != excludeId.Value);
            }
            
            return query.Any();
        }

        public List<Employee> GetEmployeesByDeviceId(int deviceId)
        {
            var assignments = _context.DeviceAssignments
                .Where(da => da.DeviceId == deviceId && da.EndDate == null)
                .ToList();

            var employeeIds = assignments.Select(da => da.EmployeeId).ToList();
            
            return _context.Employees
                .Where(e => employeeIds.Contains(e.Id))
                .ToList();
        }

        public List<Employee> GetUnassignedEmployees()
        {
            var assignedEmployeeIds = _context.DeviceAssignments
                .Where(da => da.EndDate == null)
                .Select(da => da.EmployeeId)
                .ToList();

            return _context.Employees
                .Where(e => !assignedEmployeeIds.Contains(e.Id))
                .ToList();
        }
    }

    public class DeviceAssignmentRepository
    {
        private readonly CNCBusinessDbContext _context;

        public DeviceAssignmentRepository(CNCBusinessDbContext context)
        {
            _context = context;
        }

        public List<DeviceAssignment> GetAllAssignments()
        {
            return _context.DeviceAssignments.ToList();
        }

        public List<DeviceAssignment> GetActiveAssignments()
        {
            return _context.DeviceAssignments
                .Where(da => da.EndDate == null)
                .ToList();
        }

        public List<DeviceAssignment> GetAssignmentsByEmployeeId(int employeeId)
        {
            return _context.DeviceAssignments
                .Where(da => da.EmployeeId == employeeId)
                .ToList();
        }

        public List<DeviceAssignment> GetAssignmentsByDeviceId(int deviceId)
        {
            return _context.DeviceAssignments
                .Where(da => da.DeviceId == deviceId)
                .ToList();
        }

        public DeviceAssignment GetActiveAssignmentByDeviceId(int deviceId)
        {
            return _context.DeviceAssignments
                .FirstOrDefault(da => da.DeviceId == deviceId && da.EndDate == null);
        }

        public DeviceAssignment CreateAssignment(DeviceAssignment assignment)
        {
            // 检查设备是否已被分配
            var existingAssignment = GetActiveAssignmentByDeviceId(assignment.DeviceId);
            if (existingAssignment != null)
            {
                throw new Exception("设备已被其他员工分配");
            }

            assignment.CreatedAt = DateTime.Now;
            _context.DeviceAssignments.Add(assignment);
            _context.SaveChanges();
            return assignment;
        }

        public DeviceAssignment EndAssignment(int id)
        {
            var assignment = _context.DeviceAssignments.Find(id);
            if (assignment != null)
            {
                assignment.EndDate = DateTime.Now;
                _context.Entry(assignment).State = System.Data.Entity.EntityState.Modified;
                _context.SaveChanges();
                return assignment;
            }
            return null;
        }

        public void DeleteAssignment(int id)
        {
            var assignment = _context.DeviceAssignments.Find(id);
            if (assignment != null)
            {
                _context.DeviceAssignments.Remove(assignment);
                _context.SaveChanges();
            }
        }
    }

    public class UserService
    {
        private readonly UserRepository _userRepository;
        private readonly RoleRepository _roleRepository;
        private readonly EmployeeRepository _employeeRepository;
        private readonly DeviceAssignmentRepository _assignmentRepository;

        public UserService(UserRepository userRepository, RoleRepository roleRepository,
            EmployeeRepository employeeRepository, DeviceAssignmentRepository assignmentRepository)
        {
            _userRepository = userRepository;
            _roleRepository = roleRepository;
            _employeeRepository = employeeRepository;
            _assignmentRepository = assignmentRepository;
        }

        public LoginResponse Login(LoginRequest request)
        {
            var user = _userRepository.AuthenticateUser(request.Username, request.Password);
            
            if (user != null)
            {
                // 生成JWT token
                var token = GenerateJwtToken(user);
                
                return new LoginResponse
                {
                    Success = true,
                    Token = token,
                    User = user,
                    Message = "登录成功"
                };
            }
            
            return new LoginResponse
            {
                Success = false,
                Token = null,
                User = null,
                Message = "用户名或密码错误"
            };
        }

        public User CreateUser(User user)
        {
            // 验证用户名唯一性
            if (_userRepository.IsUsernameExists(user.Username))
            {
                throw new Exception("用户名已存在");
            }

            // 验证角色是否存在
            var role = _roleRepository.GetRoleById(user.RoleId);
            if (role == null)
            {
                throw new Exception("指定的角色不存在");
            }

            return _userRepository.CreateUser(user);
        }

        public User UpdateUser(User user)
        {
            // 验证用户名唯一性
            if (_userRepository.IsUsernameExists(user.Username, user.Id))
            {
                throw new Exception("用户名已存在");
            }

            // 验证角色是否存在
            var role = _roleRepository.GetRoleById(user.RoleId);
            if (role == null)
            {
                throw new Exception("指定的角色不存在");
            }

            return _userRepository.UpdateUser(user);
        }

        public Employee CreateEmployee(Employee employee)
        {
            // 验证员工编号唯一性
            if (_employeeRepository.IsEmployeeCodeExists(employee.EmployeeCode))
            {
                throw new Exception("员工编号已存在");
            }

            return _employeeRepository.CreateEmployee(employee);
        }

        public Employee UpdateEmployee(Employee employee)
        {
            // 验证员工编号唯一性
            if (_employeeRepository.IsEmployeeCodeExists(employee.EmployeeCode, employee.Id))
            {
                throw new Exception("员工编号已存在");
            }

            return _employeeRepository.UpdateEmployee(employee);
        }

        public DeviceAssignment AssignDevice(DeviceAssignment assignment)
        {
            return _assignmentRepository.CreateAssignment(assignment);
        }

        public DeviceAssignment UnassignDevice(int assignmentId)
        {
            return _assignmentRepository.EndAssignment(assignmentId);
        }

        public List<UserViewModel> GetAllUserViewModels()
        {
            var users = _userRepository.GetAllUsers();
            return users.Select(u => new UserViewModel
            {
                Id = u.Id,
                Username = u.Username,
                RealName = u.RealName,
                Email = u.Email,
                Phone = u.Phone,
                RoleName = u.Role?.RoleName,
                IsActive = u.IsActive,
                LastLoginTime = u.LastLoginTime,
                CreatedAt = u.CreatedAt
            }).ToList();
        }

        private string GenerateJwtToken(User user)
        {
            // 这里应该使用JWT库生成token
            // 简化实现，返回一个固定token
            return "jwt_token_" + user.Id + "_" + DateTime.Now.Ticks;
        }
    }
}