<?php
defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * Calculate loyalty points for an order
 * @param float $orderTotal Order total amount
 * @param string $customerId Customer ID
 * @param string $orderId Order ID
 * @param object $common Common model instance
 * @return array Array with points earned, multipliers applied, and breakdown
 */
function calculate_loyalty_points($orderTotal, $customerId, $orderId, $common) {
    // Get loyalty settings
    $settings = get_loyalty_settings($common);
    
    if (empty($settings)) {
        return array('points' => 0, 'multiplier' => 1.0, 'breakdown' => array());
    }
    
    $basePointsPerDollar = isset($settings['pointsPerDollar']) ? floatval($settings['pointsPerDollar']) : 1.0;
    $basePoints = $orderTotal * $basePointsPerDollar;
    
    $multiplier = 1.0;
    $breakdown = array();
    
    // Check for double points day
    $doublePointsMultiplier = check_double_points_day($common);
    if ($doublePointsMultiplier > 1.0) {
        $multiplier *= $doublePointsMultiplier;
        $breakdown[] = array(
            'type' => 'double_points_day',
            'multiplier' => $doublePointsMultiplier,
            'description' => 'Double Points Day Bonus'
        );
    }
    
    // Check for VIP promotion
    $customer = $common->readdatadocument('Users', $customerId);
    if (!empty($customer)) {
        $customerTier = get_customer_tier($customer, $common);
        $vipMultiplier = check_vip_promotion($customerTier, $common);
        if ($vipMultiplier > 1.0) {
            $multiplier *= $vipMultiplier;
            $breakdown[] = array(
                'type' => 'vip_promotion',
                'multiplier' => $vipMultiplier,
                'tier' => $customerTier,
                'description' => 'VIP Promotion Bonus'
            );
        }
        
        // Apply tier bonus
        $tierBonus = get_tier_bonus($customerTier, $common);
        if ($tierBonus > 0) {
            $multiplier *= (1 + ($tierBonus / 100));
            $breakdown[] = array(
                'type' => 'tier_bonus',
                'bonus' => $tierBonus,
                'tier' => $customerTier,
                'description' => ucfirst($customerTier) . ' Tier Bonus (' . $tierBonus . '%)'
            );
        }
    }
    
    $finalPoints = round($basePoints * $multiplier);
    
    return array(
        'points' => $finalPoints,
        'basePoints' => $basePoints,
        'multiplier' => $multiplier,
        'breakdown' => $breakdown
    );
}

/**
 * Award loyalty points to customer
 * @param string $customerId Customer ID
 * @param int $points Points to award
 * @param string $type Transaction type (earned, redeemed, expired, birthday)
 * @param string $orderId Order ID (optional)
 * @param string $description Description
 * @param object $common Common model instance
 * @return bool Success status
 */
function award_loyalty_points($customerId, $points, $type = 'earned', $orderId = null, $description = '', $common) {
    // Get current customer points
    $customer = $common->readdatadocument('Users', $customerId);
    if (empty($customer)) {
        return false;
    }
    
    $currentPoints = isset($customer['points']) ? intval($customer['points']) : 0;
    
    // Calculate new points
    if ($type == 'earned' || $type == 'birthday') {
        $newPoints = $currentPoints + $points;
    } elseif ($type == 'redeemed') {
        $newPoints = max(0, $currentPoints - $points); // Don't go below 0
    } elseif ($type == 'expired') {
        $newPoints = max(0, $currentPoints - $points);
    } else {
        $newPoints = $currentPoints;
    }
    
    // Update customer points
    $updateData = array('points' => $newPoints);
    $common->updatedatamodel('Users', $customerId, $updateData);
    
    // Create transaction record
    $transaction = array(
        'customerId' => $customerId,
        'type' => $type,
        'points' => $points,
        'pointsBefore' => $currentPoints,
        'pointsAfter' => $newPoints,
        'description' => $description,
        'timestamp' => time() * 1000
    );
    
    if ($orderId) {
        $transaction['orderId'] = $orderId;
    }
    
    $transactionId = time() . '_' . rand(1000, 9999);
    $common->adddatamodel('LoyaltyTransactions', $transactionId, $transaction);
    
    // Check for tier advancement
    $oldTier = get_customer_tier_from_points($currentPoints, $common);
    $newTier = get_customer_tier_from_points($newPoints, $common);
    
    if ($newTier != $oldTier && $newTier != 'bronze') {
        // Tier advancement - send notification
        send_tier_advancement_notification($customerId, $newTier, $common);
    }
    
    // Check for milestone notifications
    check_loyalty_milestones($customerId, $newPoints, $common);
    
    return true;
}

/**
 * Check and award birthday bonus points
 * @param string $customerId Customer ID
 * @param object $common Common model instance
 * @return bool Success status
 */
function check_birthday_bonus($customerId, $common) {
    $settings = get_loyalty_settings($common);
    
    if (empty($settings) || !isset($settings['birthdayBonusEnabled']) || !$settings['birthdayBonusEnabled']) {
        return false;
    }
    
    $customer = $common->readdatadocument('Users', $customerId);
    if (empty($customer) || !isset($customer['dateOfBirth'])) {
        return false;
    }
    
    // Check if birthday is today
    $birthday = isset($customer['dateOfBirth']) ? $customer['dateOfBirth'] : null;
    if (!$birthday) {
        return false;
    }
    
    // Parse birthday (assuming format: timestamp or date string)
    $birthdayTimestamp = is_numeric($birthday) ? $birthday : strtotime($birthday);
    $birthdayThisYear = mktime(0, 0, 0, date('m', $birthdayTimestamp), date('d', $birthdayTimestamp), date('Y'));
    $today = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
    
    if ($birthdayThisYear != $today) {
        return false; // Not birthday today
    }
    
    // Check if already awarded this year
    $lastBirthdayAward = isset($customer['lastBirthdayAward']) ? $customer['lastBirthdayAward'] : 0;
    if ($lastBirthdayAward >= $today * 1000) {
        return false; // Already awarded this year
    }
    
    // Award birthday bonus
    $bonusPoints = isset($settings['birthdayBonusPoints']) ? intval($settings['birthdayBonusPoints']) : 100;
    
    award_loyalty_points(
        $customerId,
        $bonusPoints,
        'birthday',
        null,
        'Birthday Bonus Points',
        $common
    );
    
    // Update last birthday award timestamp
    $updateData = array('lastBirthdayAward' => time() * 1000);
    $common->updatedatamodel('Users', $customerId, $updateData);
    
    // Send birthday notification
    send_birthday_notification($customerId, $bonusPoints, $common);
    
    return true;
}

/**
 * Get loyalty settings
 * @param object $common Common model instance
 * @return array Settings array
 */
function get_loyalty_settings($common) {
    $settings = $common->readdatadocument('LoyaltySettings', 'main');
    
    if (empty($settings)) {
        // Return default settings
        return array(
            'pointEarningRate' => 1.0,
            'pointsPerDollar' => 1.0,
            'birthdayBonusEnabled' => true,
            'birthdayBonusPoints' => 100,
            'pointsExpiryEnabled' => false,
            'pointsExpiryDays' => 365
        );
    }
    
    return $settings;
}

/**
 * Check if today is a double points day
 * @param object $common Common model instance
 * @return float Multiplier (1.0 if not a double points day)
 */
function check_double_points_day($common) {
    $today = mktime(0, 0, 0, date('m'), date('d'), date('Y')) * 1000;
    
    $doublePointsDays = $common->readdatafromcollectionwhereclause('DoublePointsDays');
    
    foreach ($doublePointsDays as $day) {
        if (!isset($day['enabled']) || !$day['enabled']) {
            continue;
        }
        
        $dayDate = isset($day['date']) ? $day['date'] : 0;
        $dayStart = mktime(0, 0, 0, date('m', $dayDate / 1000), date('d', $dayDate / 1000), date('Y', $dayDate / 1000)) * 1000;
        $dayEnd = $dayStart + (24 * 60 * 60 * 1000) - 1;
        
        if ($today >= $dayStart && $today <= $dayEnd) {
            return isset($day['multiplier']) ? floatval($day['multiplier']) : 2.0;
        }
    }
    
    return 1.0;
}

/**
 * Check for active VIP promotion for customer tier
 * @param string $customerTier Customer tier (bronze, silver, gold, platinum)
 * @param object $common Common model instance
 * @return float Multiplier (1.0 if no active promotion)
 */
function check_vip_promotion($customerTier, $common) {
    $now = time() * 1000;
    
    $vipPromotions = $common->readdatafromcollectionwhereclause('VIPPromotions');
    
    foreach ($vipPromotions as $promo) {
        if (!isset($promo['enabled']) || !$promo['enabled']) {
            continue;
        }
        
        $startDate = isset($promo['startDate']) ? $promo['startDate'] : 0;
        $endDate = isset($promo['endDate']) ? $promo['endDate'] : 0;
        $tierRequired = isset($promo['tierRequired']) ? $promo['tierRequired'] : '';
        
        // Check if promotion is active and customer tier qualifies
        if ($now >= $startDate && $now <= $endDate && $customerTier == $tierRequired) {
            return isset($promo['pointsMultiplier']) ? floatval($promo['pointsMultiplier']) : 1.5;
        }
    }
    
    return 1.0;
}

/**
 * Get customer tier based on points
 * @param array $customer Customer data
 * @param object $common Common model instance
 * @return string Tier name (bronze, silver, gold, platinum)
 */
function get_customer_tier($customer, $common) {
    $points = isset($customer['points']) ? intval($customer['points']) : 0;
    return get_customer_tier_from_points($points, $common);
}

/**
 * Get customer tier from points
 * @param int $points Customer points
 * @param object $common Common model instance
 * @return string Tier name
 */
function get_customer_tier_from_points($points, $common) {
    $settings = get_loyalty_settings($common);
    $tiers = isset($settings['tiers']) ? $settings['tiers'] : array();
    
    // Sort tiers by threshold descending
    $sortedTiers = array();
    foreach ($tiers as $tierKey => $tier) {
        if (isset($tier['enabled']) && $tier['enabled']) {
            $sortedTiers[$tierKey] = isset($tier['threshold']) ? intval($tier['threshold']) : 0;
        }
    }
    arsort($sortedTiers);
    
    // Find highest tier customer qualifies for
    foreach ($sortedTiers as $tierKey => $threshold) {
        if ($points >= $threshold) {
            return $tierKey;
        }
    }
    
    return 'bronze'; // Default tier
}

/**
 * Get tier bonus percentage
 * @param string $tier Tier name
 * @param object $common Common model instance
 * @return float Bonus percentage
 */
function get_tier_bonus($tier, $common) {
    $settings = get_loyalty_settings($common);
    $tiers = isset($settings['tiers']) ? $settings['tiers'] : array();
    
    if (isset($tiers[$tier]) && isset($tiers[$tier]['benefits'])) {
        // Extract percentage from benefits string (e.g., "5% bonus points")
        $benefits = $tiers[$tier]['benefits'];
        if (preg_match('/(\d+)%/', $benefits, $matches)) {
            return floatval($matches[1]);
        }
    }
    
    return 0;
}

/**
 * Check for loyalty milestones and send notifications
 * @param string $customerId Customer ID
 * @param int $points Current points
 * @param object $common Common model instance
 */
function check_loyalty_milestones($customerId, $points, $common) {
    $milestones = array(100, 250, 500, 750, 1000, 1500, 2000, 2500, 3000, 5000);
    
    foreach ($milestones as $milestone) {
        // Check if customer just crossed this milestone
        if ($points >= $milestone && ($points - 100) < $milestone) {
            send_milestone_notification($customerId, $milestone, $common);
        }
        
        // Check if customer is close to next milestone
        $nextMilestone = null;
        foreach ($milestones as $m) {
            if ($m > $points) {
                $nextMilestone = $m;
                break;
            }
        }
        
        if ($nextMilestone && ($nextMilestone - $points) <= 100) {
            send_approaching_milestone_notification($customerId, $nextMilestone, $points, $common);
        }
    }
}

/**
 * Send tier advancement notification
 * @param string $customerId Customer ID
 * @param string $newTier New tier name
 * @param object $common Common model instance
 */
function send_tier_advancement_notification($customerId, $newTier, $common) {
    $customer = $common->readdatadocument('Users', $customerId);
    if (empty($customer) || !isset($customer['fcmToken'])) {
        return;
    }
    
    $tierName = ucfirst($newTier);
    $title = "Congratulations! You've reached {$tierName} Tier!";
    $body = "You've unlocked exclusive {$tierName} tier benefits. Enjoy enhanced rewards!";
    
    // Send push notification
    send_push_notification($customer['fcmToken'], $title, $body, $common);
}

/**
 * Send milestone notification
 * @param string $customerId Customer ID
 * @param int $milestone Milestone points
 * @param object $common Common model instance
 */
function send_milestone_notification($customerId, $milestone, $common) {
    $customer = $common->readdatadocument('Users', $customerId);
    if (empty($customer) || !isset($customer['fcmToken'])) {
        return;
    }
    
    $title = "Milestone Achieved! 🎉";
    $body = "Congratulations! You've reached {$milestone} loyalty points!";
    
    send_push_notification($customer['fcmToken'], $title, $body, $common);
}

/**
 * Send approaching milestone notification
 * @param string $customerId Customer ID
 * @param int $milestone Next milestone
 * @param int $currentPoints Current points
 * @param object $common Common model instance
 */
function send_approaching_milestone_notification($customerId, $milestone, $currentPoints, $common) {
    $customer = $common->readdatadocument('Users', $customerId);
    if (empty($customer) || !isset($customer['fcmToken'])) {
        return;
    }
    
    $pointsNeeded = $milestone - $currentPoints;
    $title = "You're Almost There!";
    $body = "You're {$pointsNeeded} points away from your next reward!";
    
    send_push_notification($customer['fcmToken'], $title, $body, $common);
}

/**
 * Send birthday notification
 * @param string $customerId Customer ID
 * @param int $bonusPoints Bonus points awarded
 * @param object $common Common model instance
 */
function send_birthday_notification($customerId, $bonusPoints, $common) {
    $customer = $common->readdatadocument('Users', $customerId);
    if (empty($customer) || !isset($customer['fcmToken'])) {
        return;
    }
    
    $title = "Happy Birthday! 🎂";
    $body = "We've added {$bonusPoints} bonus loyalty points to your account!";
    
    send_push_notification($customer['fcmToken'], $title, $body, $common);
}

/**
 * Send push notification
 * @param string $fcmToken FCM token
 * @param string $title Notification title
 * @param string $body Notification body
 * @param object $common Common model instance
 */
function send_push_notification($fcmToken, $title, $body, $common) {
    if (empty($fcmToken)) {
        return;
    }
    
    // This would integrate with your existing push notification system
    // For now, we'll create a notification record
    $notification = array(
        'userId' => null, // Will need customer ID
        'title' => $title,
        'body' => $body,
        'type' => 'loyalty',
        'timestamp' => time() * 1000,
        'read' => false
    );
    
    // You can integrate with your existing notification sending logic here
    // For example, if you have a send_notification function in your Promotion controller
}
