<?php

namespace MtcPharmacy\ReferAFriend\Models;

use Illuminate\Database\Eloquent\Model;
use Mtc\Modules\Members\Models\Member;
use Mtc\Shop\Order;

class Referral extends Model
{
    protected $table = 'referrals';

    protected $fillable = [
        'referrer_id',
        'referee_id',
        'referee_email',
        'referral_code',
        'channel',
        'status',
        'qualifying_order_id',
        'referee_ip_hash',
        'referee_cookie',
        'reminder_sent_at',
        'expires_at',
    ];

    protected $casts = [
        'reminder_sent_at' => 'datetime',
        'expires_at'       => 'datetime',
    ];

    // --- Relationships ---

    public function referrer()
    {
        return $this->belongsTo(Member::class, 'referrer_id');
    }

    public function referee()
    {
        return $this->belongsTo(Member::class, 'referee_id');
    }

    public function rewards()
    {
        return $this->hasMany(ReferralReward::class, 'referral_id');
    }

    public function qualifyingOrder()
    {
        return $this->belongsTo(Order::class, 'qualifying_order_id');
    }

    public function activityLog()
    {
        return $this->hasMany(ReferralActivityLog::class, 'referral_id');
    }

    // --- Scopes ---

    public function scopePending($query)
    {
        return $query->where('status', 'pending');
    }

    public function scopeActive($query)
    {
        return $query->whereNotIn('status', ['expired', 'cancelled', 'rewarded', 'fraud_flagged']);
    }

    public function scopeByReferrer($query, $referrerId)
    {
        return $query->where('referrer_id', $referrerId);
    }

    public function scopeByEmail($query, $email)
    {
        return $query->where('referee_email', $email);
    }

    public function scopeExpired($query)
    {
        return $query->where('expires_at', '<', now())->where('status', 'pending');
    }

    // --- Static Methods ---

    public static function hashIp(?string $ip): ?string
    {
        if ($ip === null || $ip === '') {
            return null;
        }

        return hash_hmac('sha256', $ip, (string) config('app.key'));
    }

    public static function generateCode(): string
    {
        $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
        $size = strlen($chars);
        $tries = 0;

        do {
            if (++$tries >= 1000) {
                throw new \RuntimeException('Unable to generate a unique referral code after 1000 attempts.');
            }

            $code = 'REF-';
            for ($i = 0; $i < 8; $i++) {
                $code .= $chars[random_int(0, $size - 1)];
            }
        } while (self::where('referral_code', $code)->exists());

        return $code;
    }
}
