<?php
/**
 * ============================================================
 * PROMO CODE SERVICE
 * ============================================================
 * Handles promo code validation and discount calculation
 */

class PromoService {
    
    /**
     * Validate and apply promo code
     * @param string $code
     * @param float $subtotal Cart subtotal before discount
     * @return array
     */
    public static function apply(string $code, float $subtotal): array {
        $code = strtoupper(trim($code));
        
        if (empty($code)) {
            return [
                'success' => false,
                'message' => 'প্রোমো কোড দিন'
            ];
        }
        
        // Find promo code
        $promo = Database::fetchOne(
            "SELECT * FROM promo_codes WHERE code = ? AND is_active = 1",
            [$code]
        );
        
        if (!$promo) {
            return [
                'success' => false,
                'message' => 'অবৈধ প্রোমো কোড'
            ];
        }
        
        // Check expiry
        if ($promo['expires_at'] && strtotime($promo['expires_at']) < time()) {
            return [
                'success' => false,
                'message' => 'প্রোমো কোডের মেয়াদ শেষ হয়ে গেছে'
            ];
        }
        
        // Check start date
        if ($promo['starts_at'] && strtotime($promo['starts_at']) > time()) {
            return [
                'success' => false,
                'message' => 'প্রোমো কোড এখনও সক্রিয় হয়নি'
            ];
        }
        
        // Check usage limit
        if ($promo['usage_limit'] !== null && $promo['used_count'] >= $promo['usage_limit']) {
            return [
                'success' => false,
                'message' => 'প্রোমো কোডের ব্যবহার সীমা শেষ'
            ];
        }
        
        // Check minimum order amount
        if ($subtotal < $promo['min_order_amount']) {
            $minAmount = formatPrice($promo['min_order_amount']);
            return [
                'success' => false,
                'message' => "সর্বনিম্ন অর্ডার {$minAmount} হতে হবে"
            ];
        }
        
        // Calculate discount
        $discountAmount = self::calculateDiscount($promo, $subtotal);
        
        // Calculate new totals
        $vatAmount = $subtotal * (VAT_PERCENT / 100);
        $taxAmount = $subtotal * (TAX_PERCENT / 100);
        $grandTotal = $subtotal + $vatAmount + $taxAmount - $discountAmount;
        
        return [
            'success' => true,
            'message' => 'প্রোমো কোড প্রয়োগ হয়েছে!',
            'promo' => [
                'id' => $promo['id'],
                'code' => $promo['code'],
                'description' => $promo['description'],
                'discount_type' => $promo['discount_type'],
                'discount_value' => $promo['discount_value']
            ],
            'discount_amount' => round($discountAmount, 2),
            'subtotal' => round($subtotal, 2),
            'vat_amount' => round($vatAmount, 2),
            'tax_amount' => round($taxAmount, 2),
            'grand_total' => round($grandTotal, 2)
        ];
    }
    
    /**
     * Calculate discount amount
     * @param array $promo
     * @param float $subtotal
     * @return float
     */
    private static function calculateDiscount(array $promo, float $subtotal): float {
        if ($promo['discount_type'] === 'percent') {
            $discount = $subtotal * ($promo['discount_value'] / 100);
            
            // Apply max discount cap if set
            if ($promo['max_discount_amount'] !== null && $discount > $promo['max_discount_amount']) {
                $discount = $promo['max_discount_amount'];
            }
        } else {
            // Fixed amount discount
            $discount = $promo['discount_value'];
        }
        
        // Discount cannot exceed subtotal
        if ($discount > $subtotal) {
            $discount = $subtotal;
        }
        
        return $discount;
    }
    
    /**
     * Increment usage count when order is placed
     * @param int $promoId
     */
    public static function incrementUsage(int $promoId): void {
        Database::execute(
            "UPDATE promo_codes SET used_count = used_count + 1 WHERE id = ?",
            [$promoId]
        );
    }
    
    /**
     * Get promo code by ID
     * @param int $id
     * @return array|null
     */
    public static function getById(int $id): ?array {
        return Database::fetchOne("SELECT * FROM promo_codes WHERE id = ?", [$id]);
    }
    
    /**
     * Get all active promo codes (for admin)
     * @return array
     */
    public static function getAll(): array {
        return Database::fetchAll(
            "SELECT * FROM promo_codes ORDER BY created_at DESC"
        );
    }
    
    /**
     * Create new promo code (admin)
     * @param array $data
     * @return int|false
     */
    public static function create(array $data) {
        $code = strtoupper(trim($data['code']));
        
        // Check if code exists
        $exists = Database::fetchColumn(
            "SELECT COUNT(*) FROM promo_codes WHERE code = ?",
            [$code]
        );
        
        if ($exists) {
            return false;
        }
        
        return Database::insert(
            "INSERT INTO promo_codes (code, description, discount_type, discount_value, 
             min_order_amount, max_discount_amount, usage_limit, starts_at, expires_at, is_active)
             VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
            [
                $code,
                $data['description'] ?? null,
                $data['discount_type'] ?? 'percent',
                $data['discount_value'],
                $data['min_order_amount'] ?? 0,
                $data['max_discount_amount'] ?? null,
                $data['usage_limit'] ?? null,
                $data['starts_at'] ?? null,
                $data['expires_at'] ?? null,
                $data['is_active'] ?? 1
            ]
        );
    }
    
    /**
     * Update promo code (admin)
     * @param int $id
     * @param array $data
     * @return bool
     */
    public static function update(int $id, array $data): bool {
        $code = strtoupper(trim($data['code']));
        
        // Check if code exists for another promo
        $exists = Database::fetchColumn(
            "SELECT COUNT(*) FROM promo_codes WHERE code = ? AND id != ?",
            [$code, $id]
        );
        
        if ($exists) {
            return false;
        }
        
        return Database::execute(
            "UPDATE promo_codes SET code = ?, description = ?, discount_type = ?, 
             discount_value = ?, min_order_amount = ?, max_discount_amount = ?, 
             usage_limit = ?, starts_at = ?, expires_at = ?, is_active = ?
             WHERE id = ?",
            [
                $code,
                $data['description'] ?? null,
                $data['discount_type'] ?? 'percent',
                $data['discount_value'],
                $data['min_order_amount'] ?? 0,
                $data['max_discount_amount'] ?? null,
                $data['usage_limit'] ?? null,
                $data['starts_at'] ?? null,
                $data['expires_at'] ?? null,
                $data['is_active'] ?? 1,
                $id
            ]
        ) > 0;
    }
    
    /**
     * Delete promo code (admin)
     * @param int $id
     * @return bool
     */
    public static function delete(int $id): bool {
        return Database::execute("DELETE FROM promo_codes WHERE id = ?", [$id]) > 0;
    }
}
