<?php
if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * VMO Affiliate Manager
 * 
 * Handles the complete affiliate lifecycle:
 * 1. Tracking referrals via cookies
 * 2. Registering affiliates
 * 3. Calculating and recording commissions
 * 4. Providing frontend dashboards and tools
 */

if (!defined('ABSPATH')) exit;

class VMO_Affiliate_Manager {

    private $cookie_name = 'vmo_affiliate_ref';
    private $cookie_expiry = 30; // Days

    public function __construct() {
        // Tracking
        add_action('init', array($this, 'track_referral'));
        
        // Shortcodes for the AI to use in generated sites
        add_shortcode('vmo_affiliate_dashboard', array($this, 'render_dashboard'));
        add_shortcode('vmo_affiliate_register', array($this, 'render_registration_form'));
        add_shortcode('vmo_commission_calculator', array($this, 'render_calculator'));
        
        // AJAX Handlers
        add_action('wp_ajax_vmo_register_affiliate', array($this, 'handle_registration'));
        add_action('wp_ajax_nopriv_vmo_register_affiliate', array($this, 'handle_registration'));
        
        // ADMIN ONLY AJAX Handlers
        add_action('wp_ajax_vmo_get_affiliates_admin', array($this, 'get_all_affiliates_admin'));
        add_action('wp_ajax_vmo_get_users_admin', array($this, 'get_users_admin'));
        add_action('wp_ajax_vmo_create_affiliate_manual', array($this, 'create_affiliate_manual'));
    }

    private function verify_ajax_request() {
        $valid = check_ajax_referer('vmo_builder_nonce', 'security', false);
        if ($valid) {
            return true;
        }

        $rest_nonce = isset($_SERVER['HTTP_X_WP_NONCE']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_X_WP_NONCE'])) : '';
        return !empty($rest_nonce) && wp_verify_nonce($rest_nonce, 'wp_rest');
    }

    private function table_exists($table_name) {
        global $wpdb;

        return $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $table_name)) === $table_name;
    }

    private function find_affiliate_record($code, $active_only = true) {
        global $wpdb;

        $lookups = [
            [
                'table' => $wpdb->prefix . 'vmo_affiliates',
                'column' => 'referral_code',
                'active_clause' => '',
            ],
            [
                'table' => $wpdb->prefix . 'vmo_manager_affiliates',
                'column' => 'affiliate_code',
                'active_clause' => $active_only ? " AND status = 'active'" : '',
            ],
        ];

        foreach ($lookups as $lookup) {
            if (!$this->table_exists($lookup['table'])) {
                continue;
            }

            $sql = "SELECT * FROM {$lookup['table']} WHERE {$lookup['column']} = %s{$lookup['active_clause']} LIMIT 1";
            $record = $wpdb->get_row($wpdb->prepare($sql, $code), ARRAY_A);

            if (!empty($record)) {
                return $record;
            }
        }

        return null;
    }

    private function affiliate_code_exists($code) {
        return !empty($this->find_affiliate_record($code, false));
    }

    // --- ADMIN FUNCTIONS ---

    /**
     * Get All Affiliates for Master Admin Dashboard
     */
    public function get_all_affiliates_admin() {
        if (!$this->verify_ajax_request()) wp_send_json_error(['message' => 'Security check failed'], 403);
        if (!current_user_can('manage_options')) wp_send_json_error(['message' => 'Unauthorized']);
        
        global $wpdb;
        $t_aff = $wpdb->prefix . 'vmo_affiliates';
        $t_sign = $wpdb->prefix . 'vmo_affiliate_signups';

        // Fetch affiliates with referral count
        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $affiliates = $wpdb->get_results("
            SELECT a.*, 
            (SELECT COUNT(*) FROM $t_sign s WHERE s.affiliate_id = a.id) as referral_count,
            u.user_registered as user_registered_date
            FROM $t_aff a
            LEFT JOIN {$wpdb->users} u ON a.wp_user_id = u.ID
            ORDER BY a.created_at DESC
        ", ARRAY_A);

        // Process for display (add awards logic)
        foreach ($affiliates as &$aff) {
            $count = (int)$aff['referral_count'];
            // Use unique milestone logic that locks winners per milestone
            $aff['milestone_awards'] = $this->calculate_unique_milestones($aff['id'], $count);
            
            $aff['total_value'] = (float)$aff['total_earnings'] + $aff['milestone_awards'];
            // Mock Location (store in usermeta in real app)
            $aff['location'] = get_user_meta($aff['wp_user_id'], 'billing_country', true) ?: 'Global';
            $aff['bank_info'] = $aff['payment_address'] ?: 'Not Set';
        }

        wp_send_json_success(['affiliates' => $affiliates]);
    }

    /**
     * Get All Users for User Management Tab
     */
    public function get_users_admin() {
        if (!$this->verify_ajax_request()) wp_send_json_error(['message' => 'Security check failed'], 403);
        if (!current_user_can('manage_options')) wp_send_json_error(['message' => 'Unauthorized']);

        $args = [
            'number' => 100, // Pagination needed in future
            'orderby' => 'registered',
            'order' => 'DESC',
        ];

        // Filter Logic
        if (isset($_POST['filter_affiliate']) && !empty($_POST['filter_affiliate'])) {
            $code = sanitize_text_field(wp_unslash($_POST['filter_affiliate']));
            // Complex query needed to join user meta? Or just filter results. 
            // For MVP: Search users by meta
            // Note: Users sign up via cookie that sets usermeta 'vmo_referred_by'
            $args['meta_key'] = 'vmo_referred_by';
            $args['meta_value'] = $code;
        }

        $user_query = new WP_User_Query($args);
        $users = [];

        foreach ($user_query->get_results() as $user) {
            $ref_code = get_user_meta($user->ID, 'vmo_referred_by', true) ?: '-';
            $plan = get_user_meta($user->ID, 'vmo_subscription_plan', true) ?: 'Free Tier';
            
            // Calc months active
            $registered = new DateTime($user->user_registered);
            $now = new DateTime();
            $interval = $registered->diff($now);
            $months = ($interval->y * 12) + $interval->m;

            $users[] = [
                'id' => $user->ID,
                'name' => $user->display_name,
                'email' => $user->user_email,
                'domain' => get_user_meta($user->ID, 'vmo_business_url', true) ?: 'N/A',
                'phone' => get_user_meta($user->ID, 'billing_phone', true) ?: '-',
                'ref_code' => $ref_code,
                'plan' => $plan,
                'joined' => $user->user_registered,
                'months_active' => $months
            ];
        }

        wp_send_json_success(['users' => $users]);
    }

    /**
     * Manual Affiliate Creation
     */
    public function create_affiliate_manual() {
        if (!$this->verify_ajax_request()) wp_send_json_error(['message' => 'Security check failed'], 403);
        if (!current_user_can('manage_options')) wp_send_json_error(['message' => 'Unauthorized']);
        
        $email = isset($_POST['email']) ? sanitize_email(wp_unslash($_POST['email'])) : '';
        $user = get_user_by('email', $email);
        
        if (!$user) {
            wp_send_json_error(['message' => 'User not found. Users must register on VMO first.']);
        }

        $code = $this->generate_affiliate_code($user->ID);
        if ($this->create_affiliate_record($code, $user->ID)) {
             update_user_meta($user->ID, 'vmo_affiliate_code', $code);
             wp_send_json_success(['message' => 'Affiliate Created', 'code' => $code]);
        } else {
             wp_send_json_error(['message' => 'Failed to create record. Code might exist.']);
        }
    }

    /**
     * Calculate Unique Milestone Awards
     * Only ONE affiliate can claim each milestone (First to Reach).
     */
    private function calculate_unique_milestones($affiliate_id, $count) {
        $award = 0;
        // Format: [UserCount => CashBonus]
        $milestones = [
            100 => 100,
            500 => 500,
            1000 => 1000,
            50000 => 50000,
            1000000 => 1000000
        ];

        foreach ($milestones as $target => $bonus) {
            if ($count >= $target) {
                // Check if this milestone is already claimed globally
                $option_key = 'vmo_milestone_winner_' . $target;
                $winner_id = get_option($option_key); // Returns affiliate_id

                if (!$winner_id) {
                    // No winner yet? Claim it for this affiliate!
                    // Note: In a high-concurrency environment, this needs db locking,
                    // but for this plugin scope, this check-then-set is sufficient.
                    update_option($option_key, $affiliate_id);
                    $award += $bonus;
                } elseif ($winner_id == $affiliate_id) {
                    // This affiliate is the recorded winner
                    $award += $bonus;
                }
                // If winner_id exists and != affiliate_id, they get nothing for this tier.
            }
        }
        
        return $award;
    }

    /**
     * 1. TRACKING: Capture ?ref=ID from URL
     */
    public function track_referral() {
        if (!isset($_GET['ref']) || isset($_COOKIE[$this->cookie_name])) {
            return;
        }

        $affiliate_code = sanitize_text_field(wp_unslash($_GET['ref']));
        if ($affiliate_code === '') {
            return;
        }

        // Verify affiliate exists in manager affiliates table
        if ($this->affiliate_code_is_active($affiliate_code)) {
            setcookie($this->cookie_name, $affiliate_code, time() + ($this->cookie_expiry * 86400), COOKIEPATH, COOKIE_DOMAIN);
        }
    }

    /**
     * Check if a user is a registered affiliate
     */
    public function is_affiliate($user_id) {
        $code = (string) get_user_meta((int)$user_id, 'vmo_affiliate_code', true);
        if ($code === '') return false;
        return $this->affiliate_code_is_active($code);
    }
    
    /**
     * Get Stats for Frontend Dashboard (AJAX)
     */
    public function get_dashboard_stats($user_id = null) {
        if (!$user_id) $user_id = get_current_user_id();
        $code = (string) get_user_meta($user_id, 'vmo_affiliate_code', true);
        
        // If not registered, return basic structure to trigger "Join" UI
        if (!$code) return ['is_registered' => false];

        return [
            'is_registered' => true,
            'code' => $code,
            'link' => home_url('/?ref=' . rawurlencode($code)),
            'stats' => $this->get_affiliate_stats($code),
            'referrals' => $this->get_referrals_list($code)
        ];
    }

    /**
     * 2. REGISTRATION: Handle sign-up AJAX
     */
    public function handle_registration() {
        if (!$this->verify_ajax_request()) {
            wp_send_json_error(['message' => 'Security check failed'], 403);
        }
        
        $user_id = get_current_user_id();
        if (!$user_id) {
            // Handle new user registration logic here if needed
            // For now, assume user must be logged in or register first
            wp_send_json_error(['message' => 'Please login or register an account first.']);
        }

        $existing_code = (string) get_user_meta($user_id, 'vmo_affiliate_code', true);
        $code = $existing_code ?: $this->generate_affiliate_code($user_id);

        // Ensure affiliate exists in manager table
        $affiliate = $this->get_affiliate_by_code($code);
        if (!$affiliate) {
            $created = $this->create_affiliate_record($code, $user_id);
            if (!$created) {
                wp_send_json_error(['message' => 'Unable to create affiliate record. Please try again.']);
            }
        }

        update_user_meta($user_id, 'vmo_affiliate_code', $code);
        update_user_meta($user_id, 'vmo_affiliate_status', 'active');
        update_user_meta($user_id, 'vmo_affiliate_joined', current_time('mysql'));

        wp_send_json_success([
            'message' => 'Welcome to the VMO Affiliate Program!', 
            'affiliate_code' => $code,
            'link' => home_url('/?ref=' . rawurlencode($code))
        ]);
    }

    /**
     * Helper: Generate unique affiliate code
     */
    private function generate_affiliate_code($user_id) {
        $user = get_userdata($user_id);
        $login = $user ? (string) $user->user_login : '';
        $base = strtoupper(substr(preg_replace('/[^a-zA-Z0-9]/', '', $login), 0, 6));
        if (strlen($base) < 3) $base = 'VMO';

        for ($attempt = 0; $attempt < 10; $attempt++) {
            $code = substr($base . strtoupper(wp_generate_password(4, false, false)), 0, 10);
            if (!$this->affiliate_code_exists($code)) {
                return $code;
            }
        }

        do {
            $fallback = 'VMO' . strtoupper(wp_generate_password(6, false, false));
        } while ($this->affiliate_code_exists($fallback));

        return $fallback;
    }

    /**
     * Helper: Check if code is active
     */
    private function affiliate_code_is_active($code) {
        return !empty($this->find_affiliate_record($code, true));
    }

    /**
     * Helper: Create record
     */
    private function create_affiliate_record($code, $user_id) {
        global $wpdb;
        $table = $wpdb->prefix . 'vmo_affiliates';
        
        // Ensure table exists
        require_once dirname(__FILE__) . '/vmo_admin_tables.php';
        vmo_create_admin_tables();

        $user = get_userdata($user_id);
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        return $wpdb->insert($table, [
            'wp_user_id' => $user_id,
            'name' => $user->display_name,
            'email' => $user->user_email,
            'referral_code' => $code,
            'created_at' => current_time('mysql')
        ]);
    }

    /**
     * Helper: Get Stats
     */
    private function get_affiliate_stats($code) {
        global $wpdb;
        $t_aff = $wpdb->prefix . 'vmo_affiliates';
        $t_sign = $wpdb->prefix . 'vmo_affiliate_signups';
        
        // Get ID
        $aff_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM $t_aff WHERE referral_code = %s", $code));
        if (!$aff_id) return ['earnings' => 0, 'referrals' => 0, 'conversion_rate' => 0];
        
        // Count Referrals
        $referrals = (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $t_sign WHERE affiliate_id = %d", $aff_id));
        
        // Count conversions (referrals that resulted in a purchase/activation)
        $conversions = (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $t_sign WHERE affiliate_id = %d AND converted = 1", $aff_id));
        
        // Get Earnings
        $earnings = (float) $wpdb->get_var($wpdb->prepare("SELECT total_earnings FROM $t_aff WHERE id = %d", $aff_id));
        
        return [
            'earnings' => $earnings,
            'referrals' => $referrals,
            'conversion_rate' => ($referrals > 0) ? round(($conversions / $referrals) * 100, 1) : 0
        ];
    }
    
    /**
     * Helper: Get Referrals List
     */
    private function get_referrals_list($code) {
        global $wpdb;
        $t_aff = $wpdb->prefix . 'vmo_affiliates';
        $t_sign = $wpdb->prefix . 'vmo_affiliate_signups';
        
        $aff_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM $t_aff WHERE referral_code = %s", $code));
        if (!$aff_id) return [];
        
        return $wpdb->get_results($wpdb->prepare(
            "SELECT referred_email, registered_at FROM $t_sign WHERE affiliate_id = %d ORDER BY registered_at DESC LIMIT 10", 
            $aff_id
        ), ARRAY_A);
    }

    /**
     * 3. DASHBOARD: Render the Affiliate Area
     */
    public function render_dashboard($atts) {
        if (!is_user_logged_in()) {
            return '<div class="vmo-alert">Please <a href="/login">log in</a> to view your affiliate dashboard.</div>';
        }

        $user_id = get_current_user_id();
        if (!$this->is_affiliate($user_id)) {
            return do_shortcode('[vmo_affiliate_register]');
        }

        $affiliate_code = (string) get_user_meta($user_id, 'vmo_affiliate_code', true);
        $ref_link = home_url('/?ref=' . rawurlencode($affiliate_code));
        $stats = $this->get_affiliate_stats($affiliate_code);

        ob_start();
        ?>
        <div class="vmo-affiliate-dashboard">
            <div class="vmo-stats-grid">
                <div class="vmo-stat-card">
                    <h3>Total Earnings</h3>
                    <div class="vmo-stat-value">$<?php echo number_format($stats['earnings'], 2); ?></div>
                </div>
                <div class="vmo-stat-card">
                    <h3>Referrals</h3>
                    <div class="vmo-stat-value"><?php echo esc_attr( $stats['referrals'] ); ?></div>
                </div>
                <div class="vmo-stat-card">
                    <h3>Conversion Rate</h3>
                    <div class="vmo-stat-value"><?php echo esc_attr( $stats['conversion_rate'] ); ?>%</div>
                </div>
            </div>

            <div class="vmo-marketing-tools">
                <h3>Your Affiliate Link</h3>
                <div class="vmo-link-box">
                    <input type="text" value="<?php echo esc_attr($ref_link); ?>" readonly id="vmo-ref-link">
                    <button onclick="copyRefLink()">Copy Link</button>
                </div>
                
                <h3>Share on Social Media</h3>
                <div class="vmo-social-share">
                    <a href="https://twitter.com/intent/tweet?text=Check+out+VMO!&url=<?php echo urlencode($ref_link); ?>" target="_blank" class="btn-twitter">Twitter</a>
                    <a href="https://www.facebook.com/sharer/sharer.php?u=<?php echo urlencode($ref_link); ?>" target="_blank" class="btn-facebook">Facebook</a>
                    <a href="https://www.linkedin.com/sharing/share-offsite/?url=<?php echo urlencode($ref_link); ?>" target="_blank" class="btn-linkedin">LinkedIn</a>
                </div>
            </div>
        </div>
        
        <script>
        function copyRefLink() {
            var copyText = document.getElementById("vmo-ref-link");
            copyText.select();
            document.execCommand("copy");
            alert("Affiliate link copied to clipboard!");
        }
        </script>
        
        <style>
            .vmo-stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; }
            .vmo-stat-card { background: #f8f9fa; padding: 20px; border-radius: 8px; text-align: center; border: 1px solid #e9ecef; }
            .vmo-stat-value { font-size: 24px; font-weight: bold; color: #2c3e50; margin-top: 10px; }
            .vmo-link-box { display: flex; gap: 10px; margin-bottom: 20px; }
            .vmo-link-box input { flex: 1; padding: 10px; border: 1px solid #ddd; border-radius: 4px; }
            .vmo-link-box button { padding: 10px 20px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; }
            .vmo-social-share { display: flex; gap: 10px; }
            .vmo-social-share a { padding: 8px 16px; text-decoration: none; color: white; border-radius: 4px; font-size: 14px; }
            .btn-twitter { background: #1DA1F2; }
            .btn-facebook { background: #4267B2; }
            .btn-linkedin { background: #0077b5; }
        </style>
        <?php
        return ob_get_clean();
    }

    /**
     * 4. CALCULATOR: Live Commission Calculator
     */
    public function render_calculator($atts) {
        ob_start();
        ?>
        <div class="vmo-commission-calculator">
            <h3>Calculate Your Potential Earnings</h3>
            <div class="calc-inputs">
                <div class="form-group">
                    <label>Monthly Referrals</label>
                    <input type="range" min="1" max="100" value="10" id="calc-referrals" oninput="updateCalc()">
                    <span id="val-referrals">10</span> users
                </div>
                <div class="form-group">
                    <label>Average Plan Value</label>
                    <select id="calc-plan" onchange="updateCalc()">
                        <option value="49.99">Tester ($49.99/mo)</option>
                        <option value="99.99">Starter ($99.99/mo)</option>
                        <option value="199.99">Pro ($199.99/mo)</option>
                        <option value="499.99">Elite ($499.99/mo)</option>
                    </select>
                </div>
            </div>
            <div class="calc-result">
                <h4>Estimated Monthly Income</h4>
                <div class="amount">$<span id="calc-total">0</span></div>
                <p class="note">*Based on a fixed 5% recurring commission</p>
            </div>
        </div>

        <script>
        function updateCalc() {
            const referrals = document.getElementById('calc-referrals').value;
            const planPrice = document.getElementById('calc-plan').value;
            const commissionRate = 0.05;
            
            document.getElementById('val-referrals').innerText = referrals;
            
            const monthly = referrals * planPrice * commissionRate;
            document.getElementById('calc-total').innerText = monthly.toFixed(2);
        }
        // Init
        document.addEventListener('DOMContentLoaded', updateCalc);
        </script>

        <style>
            .vmo-commission-calculator { background: #fff; padding: 25px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); max-width: 400px; margin: 20px auto; }
            .calc-inputs .form-group { margin-bottom: 15px; }
            .calc-inputs label { display: block; margin-bottom: 5px; font-weight: 600; }
            .calc-inputs input[type="range"] { width: 100%; }
            .calc-result { text-align: center; margin-top: 20px; padding-top: 20px; border-top: 1px solid #eee; }
            .calc-result .amount { font-size: 36px; font-weight: 800; color: #27ae60; }
            .calc-result .note { font-size: 12px; color: #7f8c8d; }
        </style>
        <?php
        return ob_get_clean();
    }

    private function get_affiliate_by_code($affiliate_code) {
        return $this->find_affiliate_record($affiliate_code, true);
    }

    /**
     * Helper: Render Registration Form
     */
    public function render_registration_form() {
        $ajax_config = [
            'ajaxurl' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('vmo_builder_nonce'),
        ];

        ob_start();
        ?>
        <div class="vmo-affiliate-register">
            <h3>Join the VMO Partner Program</h3>
            <p>Earn 5% recurring commissions on every business you refer.</p>
            <button id="vmo-join-btn" onclick="registerAffiliate()">Activate Affiliate Account</button>
            <div id="vmo-join-msg"></div>
        </div>

        <script>
        const vmoAffiliateAjax = <?php echo wp_json_encode($ajax_config); ?>;

        function registerAffiliate() {
            const btn = document.getElementById('vmo-join-btn');
            const msg = document.getElementById('vmo-join-msg');
            const originalText = btn.innerText;
            btn.disabled = true;
            btn.innerText = 'Activating...';

            jQuery.post(vmoAffiliateAjax.ajaxurl, {
                action: 'vmo_register_affiliate'
                ,security: vmoAffiliateAjax.nonce
            }).done(function(response) {
                if(response.success) {
                    msg.innerHTML = '<p class="success"></p>';
                    msg.querySelector('p').textContent = response.data.message || 'Affiliate account activated.';
                    setTimeout(function(){ location.reload(); }, 1500);
                } else {
                    msg.innerHTML = '<p class="error"></p>';
                    msg.querySelector('p').textContent = (response.data && response.data.message) ? response.data.message : 'Unable to activate affiliate account.';
                    btn.disabled = false;
                    btn.innerText = originalText;
                }
            }).fail(function(xhr) {
                let message = 'Unable to activate affiliate account.';
                if (xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) {
                    message = xhr.responseJSON.data.message;
                }
                msg.innerHTML = '<p class="error"></p>';
                msg.querySelector('p').textContent = message;
                btn.disabled = false;
                btn.innerText = originalText;
            });
        }
        </script>
        <?php
        return ob_get_clean();
    }
}
