<?php
/*
 * Voucher Generator Class
 * Generate username & password based on admin settings
 */

class VoucherGenerator {
    private $db;
    private $settings;
    
    public function __construct() {
        if (!function_exists('getDBConnection')) {
            require_once(__DIR__ . '/../include/db_config.php');
        }
        $this->db = getDBConnection();
        $this->loadSettings();
    }
    
    /**
     * Load voucher settings from database
     */
    private function loadSettings() {
        $stmt = $this->db->query("SELECT setting_key, setting_value FROM agent_settings WHERE setting_key LIKE 'voucher_%'");
        $this->settings = [];
        
        while ($row = $stmt->fetch()) {
            $this->settings[$row['setting_key']] = $row['setting_value'];
        }
        
        // Set defaults if not found
        $defaults = [
            'voucher_username_password_same' => '0',
            'voucher_username_type' => 'alphanumeric',
            'voucher_username_length' => '8',
            'voucher_password_type' => 'alphanumeric',
            'voucher_password_length' => '6',
            'voucher_prefix_enabled' => '1',
            'voucher_prefix' => 'AG',
            'voucher_uppercase' => '1'
        ];
        
        foreach ($defaults as $key => $value) {
            if (!isset($this->settings[$key])) {
                $this->settings[$key] = $value;
            }
        }
    }
    
    /**
     * Generate random string based on type
     */
    private function generateRandomString($type, $length) {
        $chars = '';
        
        switch($type) {
            case 'numeric':
                $chars = '0123456789';
                break;
            case 'alpha':
                $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
                break;
            case 'alphanumeric':
            default:
                $chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
                break;
        }
        
        $result = '';
        $charsLength = strlen($chars);
        
        for ($i = 0; $i < $length; $i++) {
            $result .= $chars[random_int(0, $charsLength - 1)];
        }
        
        return $result;
    }
    
    /**
     * Generate username
     */
    public function generateUsername() {
        $type = $this->settings['voucher_username_type'];
        $length = intval($this->settings['voucher_username_length']);
        $prefixEnabled = $this->settings['voucher_prefix_enabled'] == '1';
        $prefix = $this->settings['voucher_prefix'];
        $uppercase = $this->settings['voucher_uppercase'] == '1';
        
        // Generate random string
        $username = $this->generateRandomString($type, $length);
        
        // Add prefix if enabled
        if ($prefixEnabled && !empty($prefix)) {
            $username = $prefix . $username;
        }
        
        // Apply case
        if (!$uppercase && $type !== 'numeric') {
            $username = strtolower($username);
        }
        
        return $username;
    }
    
    /**
     * Generate password
     */
    public function generatePassword($username = null) {
        $isSame = $this->settings['voucher_username_password_same'] == '1';
        
        // If username and password should be same
        if ($isSame && $username !== null) {
            return $username;
        }
        
        $type = $this->settings['voucher_password_type'];
        $length = intval($this->settings['voucher_password_length']);
        $uppercase = $this->settings['voucher_uppercase'] == '1';
        
        // Generate random string
        $password = $this->generateRandomString($type, $length);
        
        // Apply case
        if (!$uppercase && $type !== 'numeric') {
            $password = strtolower($password);
        }
        
        return $password;
    }
    
    /**
     * Generate voucher (username + password)
     */
    public function generateVoucher() {
        $username = $this->generateUsername();
        $password = $this->generatePassword($username);
        
        return [
            'username' => $username,
            'password' => $password
        ];
    }
    
    /**
     * Generate multiple vouchers
     */
    public function generateMultipleVouchers($quantity) {
        $vouchers = [];
        $attempts = 0;
        $maxAttempts = $quantity * 10; // Prevent infinite loop
        
        while (count($vouchers) < $quantity && $attempts < $maxAttempts) {
            $voucher = $this->generateVoucher();
            
            // Check for duplicates in current batch
            $isDuplicate = false;
            foreach ($vouchers as $existing) {
                if ($existing['username'] === $voucher['username']) {
                    $isDuplicate = true;
                    break;
                }
            }
            
            if (!$isDuplicate) {
                $vouchers[] = $voucher;
            }
            
            $attempts++;
        }
        
        return $vouchers;
    }
    
    /**
     * Check if username exists in MikroTik
     */
    public function isUsernameExists($username, $API) {
        try {
            $users = $API->comm("/ip/hotspot/user/print", [
                "?name" => $username
            ]);
            return !empty($users);
        } catch (Exception $e) {
            return false;
        }
    }
    
    /**
     * Generate unique username (check against MikroTik)
     */
    public function generateUniqueUsername($API, $maxAttempts = 10) {
        $attempts = 0;
        
        while ($attempts < $maxAttempts) {
            $username = $this->generateUsername();
            
            if (!$this->isUsernameExists($username, $API)) {
                return $username;
            }
            
            $attempts++;
        }
        
        // If still not unique, add timestamp
        return $this->generateUsername() . time();
    }
    
    /**
     * Get current settings
     */
    public function getSettings() {
        return $this->settings;
    }
    
    /**
     * Get setting value
     */
    public function getSetting($key, $default = null) {
        return $this->settings[$key] ?? $default;
    }
}
