package online.wesal.wesal.service;

import online.wesal.wesal.entity.InvitationCode;
import online.wesal.wesal.entity.User;
import online.wesal.wesal.repository.InvitationCodeRepository;
import online.wesal.wesal.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Optional;
import java.util.Random;

@Service
public class InvitationCodeService {
    
    @Autowired
    private InvitationCodeRepository invitationCodeRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    public boolean isValidCode(String code) {
        Optional<InvitationCode> invitationCodeOpt = invitationCodeRepository.findValidCodeByCode(code, LocalDateTime.now());
        return invitationCodeOpt.isPresent();
    }
    
    public Optional<InvitationCode> findValidCode(String code) {
        return invitationCodeRepository.findValidCodeByCode(code, LocalDateTime.now());
    }
    
    @Transactional
    public User registerUserWithCode(String code, String phoneNumber, String password) {
        // Check if phone number already exists
        if (userRepository.existsByPhoneNumber(phoneNumber)) {
            throw new RuntimeException("User with this phone number already exists");
        }
        
        // Validate invitation code
        Optional<InvitationCode> invitationCodeOpt = findValidCode(code);
        if (invitationCodeOpt.isEmpty()) {
            throw new RuntimeException("Invalid or expired invitation code");
        }
        
        InvitationCode invitationCode = invitationCodeOpt.get();
        
        // Create new user
        User user = new User();
        user.setPhoneNumber(phoneNumber);
        user.setPassword(passwordEncoder.encode(password));
        user.setDisplayName("Guest");
        user.setRole("USER");
        user.setActivated(false);
        user.setSubscriptions(Arrays.asList("postcomments", "newinvites", "invitesfollowup", "appnews"));
        
        // Save user
        User savedUser = userRepository.save(user);
        
        // Remove (delete) the invitation code so it can't be used again
        invitationCodeRepository.delete(invitationCode);
        
        return savedUser;
    }
    
    public InvitationCode generateInvitationCode() {
        String code;
        int attempts = 0;
        int maxAttempts = 100;
        
        // Generate a unique 6-character code
        do {
            code = generateRandomCode();
            attempts++;
            if (attempts > maxAttempts) {
                throw new RuntimeException("Unable to generate unique invitation code after " + maxAttempts + " attempts");
            }
        } while (invitationCodeRepository.existsByCode(code));
        
        InvitationCode invitationCode = new InvitationCode(code);
        return invitationCodeRepository.save(invitationCode);
    }
    
    private String generateRandomCode() {
        String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        
        for (int i = 0; i < 6; i++) {
            code.append(characters.charAt(random.nextInt(characters.length())));
        }
        
        return code.toString();
    }
}