<?php

namespace Yajny\Member\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Yajny\Member\FraudDetection\FraudDetection;
use Yajny\Member\FraudDetection\Utils\FraudDetectionPeriodsUtil;

class FraudRule extends Model
{
    protected $table = 'fraud_rules';
    protected $primaryKey = 'id';
    protected $guarded = [];
    protected $casts = [
        'store_ids' => 'array'
    ];

    public static function boot()
    {
        parent::boot();

        static::created(function ($fraudRule) {
            if (strtotime($fraudRule->effective_from) <= strtotime('today - 2 weeks'))
                (new FraudDetection($fraudRule))->run();
        });
    }

    public function logs()
    {
        return $this->hasMany(FraudDetectionLog::class, 'fraud_rule_id', 'id');
    }

    public function getFraudUsersThatExceedsOrderCount($from, $to): array
    {
        $transactionGroupBy = '';
        switch ($this->order_count_per) {
            case FraudDetectionPeriodsUtil::PER_DAY:
                $transactionGroupBy = 'DATE(us.transaction_time)';
                break;
            case FraudDetectionPeriodsUtil::PER_WEEK:
                $transactionGroupBy = "YEARWEEK(us.transaction_time)";
                break;
            case FraudDetectionPeriodsUtil::PER_MONTH:
                $transactionGroupBy = "YEAR(us.transaction_time), MONTH(us.transaction_time)";
                break;
        }
        $storeIDs = implode(',', $this->store_ids);
        $query = "
                SELECT us.user_id, count(*) as orderCount 
                FROM user_sales us
                JOIN users u on u.user_id = us.user_id and u.is_merchant = 0 and u.`type` <> 'affiliate'
                WHERE us.store_id in ({$storeIDs}) and DATE(us.transaction_time) BETWEEN '{$from}' and '{$to}'
                GROUP BY us.user_id, us.store_id, {$transactionGroupBy}
                HAVING orderCount >= {$this->order_count}";
        $fraudUsers = DB::select($query);
        return Arr::pluck($fraudUsers, 'user_id');
    }

    public function getFraudUsersThatExceedsTotalOrderAmount($from, $to): array
    {
        $transactionGroupBy = '';
        switch ($this->total_order_amount_per) {
            case FraudDetectionPeriodsUtil::PER_DAY:
                $transactionGroupBy = 'DATE(us.transaction_time)';
                break;
            case FraudDetectionPeriodsUtil::PER_WEEK:
                $transactionGroupBy = "YEARWEEK(us.transaction_time)";
                break;
            case FraudDetectionPeriodsUtil::PER_MONTH:
                $transactionGroupBy = "YEAR(us.transaction_time), MONTH(us.transaction_time)";
                break;
        }
        $storeIDs = implode(',', $this->store_ids);
        $query = "
                SELECT us.user_id, sum(us.order_amount) as totalOrderAmount 
                FROM user_sales us
                JOIN users u on u.user_id = us.user_id and u.is_merchant = 0 and u.`type` <> 'affiliate'
                WHERE us.store_id in ({$storeIDs}) and DATE(us.transaction_time) BETWEEN '{$from}' and '{$to}'
                GROUP BY us.user_id, us.store_id, {$transactionGroupBy}
                HAVING totalOrderAmount >= {$this->total_order_amount}";
        $fraudUsers = DB::select($query);
        return Arr::pluck($fraudUsers, 'user_id');
    }
}