package com.realnet.users.service;

import com.realnet.session.entity.AboutWork;
import com.realnet.users.entity.User;
import com.realnet.users.entity.UserDto;
import com.realnet.users.entity.UserProfileDTO;
import com.realnet.users.entity.UserSearchDTO;
import com.realnet.users.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import javax.validation.Valid;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public boolean insertOrSaveUser(User user) {
        userRepository.save(user);
        return true;
    }

    @Override
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

    @Override
    public List<User> getAll() {
        return userRepository.findAll();
    }

    @Override
    public void delete(long id) {
        userRepository.deleteById(id);
    }

    @Override
    public User getByUserNameAndPassword(String username, String password) {
        Optional<User> user = userRepository.findByUsername(username);
        if (user.isPresent() && bCryptPasswordEncoder.matches(password, user.get().getPassword())) {
            return user.get();
        }
        return null;
    }

    @Override
    public User getByUserName(String username) {
        return userRepository.findByUsername(username).orElse(null);
    }

    @Override
    public User getByEmail(String email) {
        return userRepository.findByEmail(email).orElse(null);
    }

    @Override
    public User getById(Long id) {
        return userRepository.findById(id).orElse(null);
    }

    @Override
    public boolean existsByEmail(String email) {
        return userRepository.existsByEmail(email);
    }

    @Override
    public User updateByEmail(String email, UserProfileDTO userProfile) {
        User user = userRepository.findByEmail(email).orElse(null);
        if (user != null) {
            user.setFirstName(userProfile.getFirstName());
            user.setLastName(userProfile.getLastName());
            user.setMobileNumber(userProfile.getMobileNumber());
            user.setAddress(userProfile.getAddress());
            user.setSkypeId(userProfile.getSkypeId());
            user.setLinkdinId(userProfile.getLinkdinId());
            user.setTwitterId(userProfile.getTwitterId());
            user.setFacebookId(userProfile.getFacebookId());
            user.setExt(userProfile.getExt());
            user.setDepartment(userProfile.getDepartment());
            user.setManager(userProfile.getManager());
            user.setEmployeeId(userProfile.getEmployeeId());
            user.setExtension(userProfile.getExtension());
            user.setAltMobileNumber(userProfile.getAltMobileNumber());
            user.setDob(userProfile.getDob());
            user.setMaritalStatus(userProfile.getMaritalStatus());
            user.setEmergencyContactNumber(userProfile.getEmergencyContactNumber());
            user.setBloodGroup(userProfile.getBloodGroup());
            user.setHobbies(userProfile.getHobbies());
            user.setAbout(userProfile.getAbout());
            user.setQuote(userProfile.getQuote());
            user.setZipCode(userProfile.getZipCode());
            user.setCountry(userProfile.getCountry());
            user.setState(userProfile.getState());
            user.setCity(userProfile.getCity());
            user.setGender(userProfile.getGender());
            user.setNationality(userProfile.getNationality());
            user.setMotherTongue(userProfile.getMotherTongue());
            user.setLanguageKnown(userProfile.getLanguageKnown());
            user.setPanNumber(userProfile.getPanNumber());
            user.setAadharNumber(userProfile.getAadharNumber());
            user.setPfNumber(userProfile.getPfNumber());
            user.setPassportNumber(userProfile.getPassportNumber());
            user.setVisaNumber(userProfile.getVisaNumber());
            user.setDrivingLicenseNumber(userProfile.getDrivingLicenseNumber());
            user.setVehicleNumber(userProfile.getVehicleNumber());
            user.setBankName(userProfile.getBankName());
            user.setBankAccountNumber(userProfile.getBankAccountNumber());
            user.setIfscCode(userProfile.getIfscCode());
            user.setBranchName(userProfile.getBranchName());
            user.setMicrCode(userProfile.getMicrCode());
            user.setSwiftCode(userProfile.getSwiftCode());
            user.setUanNumber(userProfile.getUanNumber());
            user.setNomineeName(userProfile.getNomineeName());
            user.setNomineeRelation(userProfile.getNomineeRelation());
            user.setNomineeContactNumber(userProfile.getNomineeContactNumber());
            user.setNomineeAddress(userProfile.getNomineeAddress());
            user.setNomineeEmail(userProfile.getNomineeEmail());
            user.setNomineeAadharNumber(userProfile.getNomineeAadharNumber());
            user.setNomineePanNumber(userProfile.getNomineePanNumber());
            user.setNomineePassportNumber(userProfile.getNomineePassportNumber());
            user.setNomineeDrivingLicenseNumber(userProfile.getNomineeDrivingLicenseNumber());
            user.setNomineeVehicleNumber(userProfile.getNomineeVehicleNumber());
            user.setNomineeBankName(userProfile.getNomineeBankName());
            user.setNomineeBankAccountNumber(userProfile.getNomineeBankAccountNumber());
            user.setNomineeIfscCode(userProfile.getNomineeIfscCode());
            user.setNomineeBranchName(userProfile.getNomineeBranchName());
            user.setNomineeMicrCode(userProfile.getNomineeMicrCode());
            user.setNomineeSwiftCode(userProfile.getNomineeSwiftCode());
            user.setNomineeUanNumber(userProfile.getNomineeUanNumber());
            return userRepository.save(user);
        }
        return null;
    }

    @Override
    public String getLoggedInUserEmail() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (principal instanceof UserDetails) {
            return ((UserDetails) principal).getUsername();
        } else {
            return principal.toString();
        }
    }

    @Override
    public Long getLoggedInUserId() {
        String email = getLoggedInUserEmail();
        User user = userRepository.findByEmail(email).orElse(null);
        return user != null ? user.getUserId() : null;
    }

    @Override
    public Long getLoggedInUserAccountId() {
        String email = getLoggedInUserEmail();
        User user = userRepository.findByEmail(email).orElse(null);
        return user != null ? user.getAccountId() : null;
    }

    @Override
    public User getLoggedInUser() {
        String email = getLoggedInUserEmail();
        return userRepository.findByEmail(email).orElse(null);
    }

    @Override
    public User getUserInfoByUserId(Long userId) {
        return userRepository.findById(userId).orElse(null);
    }

    @Override
    public User userResister(UserDto userDto) {
        User user = new User();
        user.setUsername(userDto.getUsername());
        user.setEmail(userDto.getEmail());
        user.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword()));
        return userRepository.save(user);
    }

    @Override
    public User createUserByAdmin(User user) {
        user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
        return userRepository.save(user);
    }

    @Override
    public User updateById(Long id, User userRequest) {
        User user = userRepository.findById(id).orElse(null);
        if (user != null) {
            user.setUsername(userRequest.getUsername());
            user.setEmail(userRequest.getEmail());
            user.setFirstName(userRequest.getFirstName());
            user.setLastName(userRequest.getLastName());
            // Update other fields as needed
            return userRepository.save(user);
        }
        return null;
    }

    @Override
    public boolean deleteById(Long id) {
        if (userRepository.existsById(id)) {
            userRepository.deleteById(id);
            return true;
        }
        return false;
    }

    @Override
    public boolean changePassword(String oldPassword, String newPassword) {
        User user = getLoggedInUser();
        if (user != null && bCryptPasswordEncoder.matches(oldPassword, user.getPassword())) {
            user.setPassword(bCryptPasswordEncoder.encode(newPassword));
            userRepository.save(user);
            return true;
        }
        return false;
    }

    @Override
    public void sendEmail(String email, Long id, Long checkNo) {
        // Implementation for sending email
    }

    @Override
    public User adddata(AboutWork about) {
        // Implementation for adding data
        return null;
    }

    @Override
    public User updateById(Long id, @Valid AboutWork aboutWork) {
        // Implementation for updating by id with AboutWork
        return null;
    }

    @Override
    public User updateById2(Long id, @Valid AboutWork aboutWork) {
        // Implementation for updating by id2 with AboutWork
        return null;
    }

    @Override
    public User userResister(User user, Long id) {
        // Implementation for user registration with id
        return null;
    }

    @Override
    public User updateByIdWorkingId(Long id, @Valid AboutWork aboutWork) {
        // Implementation for updating by id with working id
        return null;
    }

    @Override
    public User updateByMangingWork(Long id, @Valid AboutWork aboutWork) {
        // Implementation for updating by managing work
        return null;
    }

    @Override
    public User userResisteremail(User user) {
        // Implementation for user registration by email
        return null;
    }

    @Override
    public void sendEmail2(String email1, Long userId, Long checknumber) {
        // Implementation for sending email2
    }

    @Override
    public void sendEmail3(String email2, Long userId, Long checknumber) {
        // Implementation for sending email3
    }

    @Override
    public void sendEmail4(String email3, Long userId, Long checknumber) {
        // Implementation for sending email4
    }

    @Override
    public void sendEmail5(String email4, Long userId, Long checknumber) {
        // Implementation for sending email5
    }

    @Override
    public User exitbychecknumber(Long userId, Long checknumber) {
        // Implementation for exit by checknumber
        return null;
    }

    @Override
    public User save(User user) {
        return userRepository.save(user);
    }

    @Override
    public List<UserSearchDTO> searchUsers(String query) {
        List<User> users = userRepository.findByUsernameContainingIgnoreCaseOrEmailContainingIgnoreCase(query, query);
        return users.stream().map(user -> {
            UserSearchDTO dto = new UserSearchDTO();
            dto.setId(user.getUserId());
            dto.setUsername(user.getUsername());
            dto.setEmail(user.getEmail());
            dto.setFirstName(user.getFirstName());
            dto.setLastName(user.getLastName());
            return dto;
        }).collect(Collectors.toList());
    }
}