<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;


class Coupon extends Model
{

    protected $fillable = [
        'user_id',
        'code',
        'discount_type',
        'discount_value',
        'min_usage',
        'max_usage',
        'usage_count',
        'is_active',
        'expires_at',
    ];

    protected $casts = [
        'discount_value' => 'decimal:2',
        'min_usage' => 'integer',
        'max_usage' => 'integer',
        'usage_count' => 'integer',
        'is_active' => 'boolean',
        'expires_at' => 'datetime',
    ];

    /**
     * Generate a unique, hard-to-guess coupon code
     * Format: CBFR + 6 alphanumeric characters (e.g., CBFR7X9K2M)
     * This gives 36^6 = 2,176,782,336 possible combinations
     */
    public static function generateCode(): string
    {
        $prefix = 'CBFR';
        $characters = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ'; // Removed I, O to avoid confusion with 1, 0
        $suffixLength = 6; // 6 characters = 34^6 = 1.5 billion combinations
        $maxAttempts = 100;
        $attempts = 0;
        
        do {
            $attempts++;
            
            // Generate random alphanumeric suffix
            $suffix = '';
            for ($i = 0; $i < $suffixLength; $i++) {
                $suffix .= $characters[random_int(0, strlen($characters) - 1)];
            }
            $code = $prefix . $suffix;
            
            // Safety: extend length if too many attempts
            if ($attempts > $maxAttempts) {
                $suffix .= $characters[random_int(0, strlen($characters) - 1)];
                $code = $prefix . $suffix;
            }
        } while (self::where('code', $code)->exists());

        return $code;
    }

    /**
     * Check if coupon is valid for use
     */
    public function isValid(): bool
    {
        if (!$this->is_active) {
            return false;
        }

        if ($this->expires_at && $this->expires_at->isPast()) {
            return false;
        }

        if ($this->max_usage && $this->usage_count >= $this->max_usage) {
            return false;
        }

        return true;
    }

    /**
     * Check if coupon has reached minimum usage
     */
    public function hasReachedMinUsage(): bool
    {
        return $this->usage_count >= $this->min_usage;
    }

    /**
     * Increment the usage count
     */
    public function incrementUsage(): void
    {
        $this->increment('usage_count');
    }

    /**
     * Get remaining uses
     */
    public function getRemainingUsesAttribute(): ?int
    {
        if (!$this->max_usage) {
            return null;
        }

        return max(0, $this->max_usage - $this->usage_count);
    }

    /**
     * Usage records for this coupon.
     */
    public function usages()
    {
        return $this->hasMany(CouponUsage::class);
    }

    /**
     * Scope for active coupons
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * Scope for valid coupons
     */
    public function scopeValid($query)
    {
        return $query->active()
            ->where(function ($q) {
                $q->whereNull('expires_at')
                    ->orWhere('expires_at', '>', now());
            })
            ->where(function ($q) {
                $q->whereNull('max_usage')
                    ->orWhereColumn('usage_count', '<', 'max_usage');
            });
    }
}