<?php

namespace Yajny\Member\FraudDetection;

use Yajny\Member\FraudDetection\Actions\FraudDetectionActionApplier;
use Yajny\Member\FraudDetection\Factors\FraudDetectionFactorsApplier;
use Yajny\Member\Models\FraudDetectionLog;
use Yajny\Member\Models\FraudRule;

class FraudDetection
{
    private $fraudRule;
    private $fromDate;
    private $toDate;
    private $matchedUsers = [];

    public function __construct(FraudRule $rule, $fromDate = null, $toDate = null)
    {
        $this->fraudRule = $rule;
        $this->fromDate = $fromDate ?? $rule->last_run_date ?? $rule->effective_from;
        $toDateTimestamp = strtotime('today - 2 weeks');
        if ($rule->effective_to) {
            $toDateTimestamp = min($toDateTimestamp, strtotime($rule->effective_to));
        }
        $toDateTimestamp = max($toDateTimestamp, strtotime($this->fromDate));
        $this->toDate = $toDate ?? date('Y-m-d', $toDateTimestamp);
    }

    public function run(): array
    {
        $this->matchedUsers = $this->getFraudUserIDs();

        $this->applyAction();

        $this->addLog();

        return $this->matchedUsers;
    }

    public function simulate(): array
    {
        return $this->getFraudUserIDs();
    }

    private function getFraudUserIDs(): array
    {
        $fraudDetectionRulesApplier = new FraudDetectionFactorsApplier($this->fraudRule);
        return $fraudDetectionRulesApplier->getFraudUserWhoMatchTheRules($this->fromDate, $this->toDate);
    }

    private function applyAction()
    {
        $fraudDetectionActionApplier = new FraudDetectionActionApplier($this->fraudRule);
        $fraudDetectionActionApplier->applyRuleAction($this->matchedUsers);
    }

    private function addLog()
    {
        FraudDetectionLog::addLog($this);
        $this->fraudRule->last_run_date = $this->toDate;
        $this->fraudRule->save();
    }

    public function getLogData()
    {
        return [
            'detection_date_from' => $this->fromDate,
            'detection_date_to' => $this->toDate,
            'fraud_rule_id' => $this->fraudRule->id,
            'user_ids' => $this->matchedUsers,
            'users_count' => count($this->matchedUsers)
        ];
    }
}